xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-vscode/lldb-vscode.cpp (revision 824adb5411e4389b29bae28eba5c2c2bbd147f34)
1 //===-- lldb-vscode.cpp -----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <assert.h>
10 #include <limits.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #if defined(_WIN32)
18 // We need to #define NOMINMAX in order to skip `min()` and `max()` macro
19 // definitions that conflict with other system headers.
20 // We also need to #undef GetObject (which is defined to GetObjectW) because
21 // the JSON code we use also has methods named `GetObject()` and we conflict
22 // against these.
23 #define NOMINMAX
24 #include <windows.h>
25 #undef GetObject
26 #include <io.h>
27 #else
28 #include <netinet/in.h>
29 #include <sys/socket.h>
30 #include <unistd.h>
31 #endif
32 
33 #include <algorithm>
34 #include <chrono>
35 #include <fstream>
36 #include <map>
37 #include <memory>
38 #include <mutex>
39 #include <set>
40 #include <sstream>
41 #include <thread>
42 #include <vector>
43 
44 #include "llvm/ADT/ArrayRef.h"
45 #include "llvm/Option/Arg.h"
46 #include "llvm/Option/ArgList.h"
47 #include "llvm/Option/Option.h"
48 #include "llvm/Support/Errno.h"
49 #include "llvm/Support/FileSystem.h"
50 #include "llvm/Support/Path.h"
51 #include "llvm/Support/raw_ostream.h"
52 
53 #include "JSONUtils.h"
54 #include "LLDBUtils.h"
55 #include "VSCode.h"
56 
57 #if defined(_WIN32)
58 #ifndef PATH_MAX
59 #define PATH_MAX MAX_PATH
60 #endif
61 typedef int socklen_t;
62 constexpr const char *dev_null_path = "nul";
63 
64 #else
65 constexpr const char *dev_null_path = "/dev/null";
66 
67 #endif
68 
69 using namespace lldb_vscode;
70 
71 namespace {
72 enum ID {
73   OPT_INVALID = 0, // This is not an option ID.
74 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
75                HELPTEXT, METAVAR, VALUES)                                      \
76   OPT_##ID,
77 #include "Options.inc"
78 #undef OPTION
79 };
80 
81 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
82 #include "Options.inc"
83 #undef PREFIX
84 
85 static const llvm::opt::OptTable::Info InfoTable[] = {
86 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
87                HELPTEXT, METAVAR, VALUES)                                      \
88   {PREFIX,      NAME,      HELPTEXT,                                           \
89    METAVAR,     OPT_##ID,  llvm::opt::Option::KIND##Class,                     \
90    PARAM,       FLAGS,     OPT_##GROUP,                                        \
91    OPT_##ALIAS, ALIASARGS, VALUES},
92 #include "Options.inc"
93 #undef OPTION
94 };
95 class LLDBVSCodeOptTable : public llvm::opt::OptTable {
96 public:
97   LLDBVSCodeOptTable() : OptTable(InfoTable, true) {}
98 };
99 
100 typedef void (*RequestCallback)(const llvm::json::Object &command);
101 
102 enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
103 
104 SOCKET AcceptConnection(int portno) {
105   // Accept a socket connection from any host on "portno".
106   SOCKET newsockfd = -1;
107   struct sockaddr_in serv_addr, cli_addr;
108   SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
109   if (sockfd < 0) {
110     if (g_vsc.log)
111       *g_vsc.log << "error: opening socket (" << strerror(errno) << ")"
112                  << std::endl;
113   } else {
114     memset((char *)&serv_addr, 0, sizeof(serv_addr));
115     serv_addr.sin_family = AF_INET;
116     // serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
117     serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
118     serv_addr.sin_port = htons(portno);
119     if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
120       if (g_vsc.log)
121         *g_vsc.log << "error: binding socket (" << strerror(errno) << ")"
122                    << std::endl;
123     } else {
124       listen(sockfd, 5);
125       socklen_t clilen = sizeof(cli_addr);
126       newsockfd =
127           llvm::sys::RetryAfterSignal(static_cast<SOCKET>(-1), accept, sockfd,
128                                       (struct sockaddr *)&cli_addr, &clilen);
129       if (newsockfd < 0)
130         if (g_vsc.log)
131           *g_vsc.log << "error: accept (" << strerror(errno) << ")"
132                      << std::endl;
133     }
134 #if defined(_WIN32)
135     closesocket(sockfd);
136 #else
137     close(sockfd);
138 #endif
139   }
140   return newsockfd;
141 }
142 
143 std::vector<const char *> MakeArgv(const llvm::ArrayRef<std::string> &strs) {
144   // Create and return an array of "const char *", one for each C string in
145   // "strs" and terminate the list with a NULL. This can be used for argument
146   // vectors (argv) or environment vectors (envp) like those passed to the
147   // "main" function in C programs.
148   std::vector<const char *> argv;
149   for (const auto &s : strs)
150     argv.push_back(s.c_str());
151   argv.push_back(nullptr);
152   return argv;
153 }
154 
155 // Send a "exited" event to indicate the process has exited.
156 void SendProcessExitedEvent(lldb::SBProcess &process) {
157   llvm::json::Object event(CreateEventObject("exited"));
158   llvm::json::Object body;
159   body.try_emplace("exitCode", (int64_t)process.GetExitStatus());
160   event.try_emplace("body", std::move(body));
161   g_vsc.SendJSON(llvm::json::Value(std::move(event)));
162 }
163 
164 void SendThreadExitedEvent(lldb::tid_t tid) {
165   llvm::json::Object event(CreateEventObject("thread"));
166   llvm::json::Object body;
167   body.try_emplace("reason", "exited");
168   body.try_emplace("threadId", (int64_t)tid);
169   event.try_emplace("body", std::move(body));
170   g_vsc.SendJSON(llvm::json::Value(std::move(event)));
171 }
172 
173 // Send a "terminated" event to indicate the process is done being
174 // debugged.
175 void SendTerminatedEvent() {
176   if (!g_vsc.sent_terminated_event) {
177     g_vsc.sent_terminated_event = true;
178     g_vsc.RunTerminateCommands();
179     // Send a "terminated" event
180     llvm::json::Object event(CreateEventObject("terminated"));
181     g_vsc.SendJSON(llvm::json::Value(std::move(event)));
182   }
183 }
184 
185 // Send a thread stopped event for all threads as long as the process
186 // is stopped.
187 void SendThreadStoppedEvent() {
188   lldb::SBProcess process = g_vsc.target.GetProcess();
189   if (process.IsValid()) {
190     auto state = process.GetState();
191     if (state == lldb::eStateStopped) {
192       llvm::DenseSet<lldb::tid_t> old_thread_ids;
193       old_thread_ids.swap(g_vsc.thread_ids);
194       uint32_t stop_id = process.GetStopID();
195       const uint32_t num_threads = process.GetNumThreads();
196 
197       // First make a pass through the threads to see if the focused thread
198       // has a stop reason. In case the focus thread doesn't have a stop
199       // reason, remember the first thread that has a stop reason so we can
200       // set it as the focus thread if below if needed.
201       lldb::tid_t first_tid_with_reason = LLDB_INVALID_THREAD_ID;
202       uint32_t num_threads_with_reason = 0;
203       for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
204         lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
205         const lldb::tid_t tid = thread.GetThreadID();
206         const bool has_reason = ThreadHasStopReason(thread);
207         // If the focus thread doesn't have a stop reason, clear the thread ID
208         if (tid == g_vsc.focus_tid && !has_reason)
209           g_vsc.focus_tid = LLDB_INVALID_THREAD_ID;
210         if (has_reason) {
211           ++num_threads_with_reason;
212           if (first_tid_with_reason == LLDB_INVALID_THREAD_ID)
213             first_tid_with_reason = tid;
214         }
215       }
216 
217       // We will have cleared g_vsc.focus_tid if he focus thread doesn't
218       // have a stop reason, so if it was cleared, or wasn't set, then set the
219       // focus thread to the first thread with a stop reason.
220       if (g_vsc.focus_tid == LLDB_INVALID_THREAD_ID)
221         g_vsc.focus_tid = first_tid_with_reason;
222 
223       // If no threads stopped with a reason, then report the first one so
224       // we at least let the UI know we stopped.
225       if (num_threads_with_reason == 0) {
226         lldb::SBThread thread = process.GetThreadAtIndex(0);
227         g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
228       } else {
229         for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
230           lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
231           g_vsc.thread_ids.insert(thread.GetThreadID());
232           if (ThreadHasStopReason(thread)) {
233             g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
234           }
235         }
236       }
237 
238       for (auto tid : old_thread_ids) {
239         auto end = g_vsc.thread_ids.end();
240         auto pos = g_vsc.thread_ids.find(tid);
241         if (pos == end)
242           SendThreadExitedEvent(tid);
243       }
244     } else {
245       if (g_vsc.log)
246         *g_vsc.log << "error: SendThreadStoppedEvent() when process"
247                       " isn't stopped ("
248                    << lldb::SBDebugger::StateAsCString(state) << ')'
249                    << std::endl;
250     }
251   } else {
252     if (g_vsc.log)
253       *g_vsc.log << "error: SendThreadStoppedEvent() invalid process"
254                  << std::endl;
255   }
256   g_vsc.RunStopCommands();
257 }
258 
259 // "ProcessEvent": {
260 //   "allOf": [
261 //     { "$ref": "#/definitions/Event" },
262 //     {
263 //       "type": "object",
264 //       "description": "Event message for 'process' event type. The event
265 //                       indicates that the debugger has begun debugging a
266 //                       new process. Either one that it has launched, or one
267 //                       that it has attached to.",
268 //       "properties": {
269 //         "event": {
270 //           "type": "string",
271 //           "enum": [ "process" ]
272 //         },
273 //         "body": {
274 //           "type": "object",
275 //           "properties": {
276 //             "name": {
277 //               "type": "string",
278 //               "description": "The logical name of the process. This is
279 //                               usually the full path to process's executable
280 //                               file. Example: /home/myproj/program.js."
281 //             },
282 //             "systemProcessId": {
283 //               "type": "integer",
284 //               "description": "The system process id of the debugged process.
285 //                               This property will be missing for non-system
286 //                               processes."
287 //             },
288 //             "isLocalProcess": {
289 //               "type": "boolean",
290 //               "description": "If true, the process is running on the same
291 //                               computer as the debug adapter."
292 //             },
293 //             "startMethod": {
294 //               "type": "string",
295 //               "enum": [ "launch", "attach", "attachForSuspendedLaunch" ],
296 //               "description": "Describes how the debug engine started
297 //                               debugging this process.",
298 //               "enumDescriptions": [
299 //                 "Process was launched under the debugger.",
300 //                 "Debugger attached to an existing process.",
301 //                 "A project launcher component has launched a new process in
302 //                  a suspended state and then asked the debugger to attach."
303 //               ]
304 //             }
305 //           },
306 //           "required": [ "name" ]
307 //         }
308 //       },
309 //       "required": [ "event", "body" ]
310 //     }
311 //   ]
312 // }
313 void SendProcessEvent(LaunchMethod launch_method) {
314   lldb::SBFileSpec exe_fspec = g_vsc.target.GetExecutable();
315   char exe_path[PATH_MAX];
316   exe_fspec.GetPath(exe_path, sizeof(exe_path));
317   llvm::json::Object event(CreateEventObject("process"));
318   llvm::json::Object body;
319   EmplaceSafeString(body, "name", std::string(exe_path));
320   const auto pid = g_vsc.target.GetProcess().GetProcessID();
321   body.try_emplace("systemProcessId", (int64_t)pid);
322   body.try_emplace("isLocalProcess", true);
323   const char *startMethod = nullptr;
324   switch (launch_method) {
325   case Launch:
326     startMethod = "launch";
327     break;
328   case Attach:
329     startMethod = "attach";
330     break;
331   case AttachForSuspendedLaunch:
332     startMethod = "attachForSuspendedLaunch";
333     break;
334   }
335   body.try_emplace("startMethod", startMethod);
336   event.try_emplace("body", std::move(body));
337   g_vsc.SendJSON(llvm::json::Value(std::move(event)));
338 }
339 
340 // Grab any STDOUT and STDERR from the process and send it up to VS Code
341 // via an "output" event to the "stdout" and "stderr" categories.
342 void SendStdOutStdErr(lldb::SBProcess &process) {
343   char buffer[1024];
344   size_t count;
345   while ((count = process.GetSTDOUT(buffer, sizeof(buffer))) > 0)
346   g_vsc.SendOutput(OutputType::Stdout, llvm::StringRef(buffer, count));
347   while ((count = process.GetSTDERR(buffer, sizeof(buffer))) > 0)
348     g_vsc.SendOutput(OutputType::Stderr, llvm::StringRef(buffer, count));
349 }
350 
351 // All events from the debugger, target, process, thread and frames are
352 // received in this function that runs in its own thread. We are using a
353 // "FILE *" to output packets back to VS Code and they have mutexes in them
354 // them prevent multiple threads from writing simultaneously so no locking
355 // is required.
356 void EventThreadFunction() {
357   lldb::SBEvent event;
358   lldb::SBListener listener = g_vsc.debugger.GetListener();
359   bool done = false;
360   while (!done) {
361     if (listener.WaitForEvent(1, event)) {
362       const auto event_mask = event.GetType();
363       if (lldb::SBProcess::EventIsProcessEvent(event)) {
364         lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(event);
365         if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
366           auto state = lldb::SBProcess::GetStateFromEvent(event);
367           switch (state) {
368           case lldb::eStateInvalid:
369             // Not a state event
370             break;
371           case lldb::eStateUnloaded:
372             break;
373           case lldb::eStateConnected:
374             break;
375           case lldb::eStateAttaching:
376             break;
377           case lldb::eStateLaunching:
378             break;
379           case lldb::eStateStepping:
380             break;
381           case lldb::eStateCrashed:
382             break;
383           case lldb::eStateDetached:
384             break;
385           case lldb::eStateSuspended:
386             break;
387           case lldb::eStateStopped:
388             // Only report a stopped event if the process was not restarted.
389             if (!lldb::SBProcess::GetRestartedFromEvent(event)) {
390               SendStdOutStdErr(process);
391               SendThreadStoppedEvent();
392             }
393             break;
394           case lldb::eStateRunning:
395             break;
396           case lldb::eStateExited: {
397             // Run any exit LLDB commands the user specified in the
398             // launch.json
399             g_vsc.RunExitCommands();
400             SendProcessExitedEvent(process);
401             SendTerminatedEvent();
402             done = true;
403           } break;
404           }
405         } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
406                    (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
407           SendStdOutStdErr(process);
408         }
409       } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(event)) {
410         if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
411           auto event_type =
412               lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(event);
413           auto bp = lldb::SBBreakpoint::GetBreakpointFromEvent(event);
414           // If the breakpoint was originated from the IDE, it will have the
415           // BreakpointBase::GetBreakpointLabel() label attached. Regardless
416           // of wether the locations were added or removed, the breakpoint
417           // ins't going away, so we the reason is always "changed".
418           if ((event_type & lldb::eBreakpointEventTypeLocationsAdded ||
419                event_type & lldb::eBreakpointEventTypeLocationsRemoved) &&
420               bp.MatchesName(BreakpointBase::GetBreakpointLabel())) {
421             auto bp_event = CreateEventObject("breakpoint");
422             llvm::json::Object body;
423             // As VSCode already knows the path of this breakpoint, we don't
424             // need to send it back as part of a "changed" event. This
425             // prevent us from sending to VSCode paths that should be source
426             // mapped. Note that CreateBreakpoint doesn't apply source mapping.
427             // Besides, the current implementation of VSCode ignores the
428             // "source" element of breakpoint events.
429             llvm::json::Value source_bp = CreateBreakpoint(bp);
430             source_bp.getAsObject()->erase("source");
431 
432             body.try_emplace("breakpoint", source_bp);
433             body.try_emplace("reason", "changed");
434             bp_event.try_emplace("body", std::move(body));
435             g_vsc.SendJSON(llvm::json::Value(std::move(bp_event)));
436           }
437         }
438       } else if (lldb::SBTarget::EventIsTargetEvent(event)) {
439         if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
440             event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
441             event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded) {
442           int num_modules = lldb::SBTarget::GetNumModulesFromEvent(event);
443           for (int i = 0; i < num_modules; i++) {
444             auto module = lldb::SBTarget::GetModuleAtIndexFromEvent(i, event);
445             auto module_event = CreateEventObject("module");
446             llvm::json::Value module_value = CreateModule(module);
447             llvm::json::Object body;
448             if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded) {
449               body.try_emplace("reason", "new");
450             } else if (event_mask &
451                         lldb::SBTarget::eBroadcastBitModulesUnloaded) {
452               body.try_emplace("reason", "removed");
453             } else if (event_mask &
454                         lldb::SBTarget::eBroadcastBitSymbolsLoaded) {
455               body.try_emplace("reason", "changed");
456             }
457             body.try_emplace("module", module_value);
458             module_event.try_emplace("body", std::move(body));
459             g_vsc.SendJSON(llvm::json::Value(std::move(module_event)));
460           }
461         }
462       } else if (event.BroadcasterMatchesRef(g_vsc.broadcaster)) {
463         if (event_mask & eBroadcastBitStopEventThread) {
464           done = true;
465         }
466       }
467     }
468   }
469 }
470 
471 // Both attach and launch take a either a sourcePath or sourceMap
472 // argument (or neither), from which we need to set the target.source-map.
473 void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
474   const char *sourceMapHelp =
475       "source must be be an array of two-element arrays, "
476       "each containing a source and replacement path string.\n";
477 
478   std::string sourceMapCommand;
479   llvm::raw_string_ostream strm(sourceMapCommand);
480   strm << "settings set target.source-map ";
481   auto sourcePath = GetString(arguments, "sourcePath");
482 
483   // sourceMap is the new, more general form of sourcePath and overrides it.
484   auto sourceMap = arguments.getArray("sourceMap");
485   if (sourceMap) {
486     for (const auto &value : *sourceMap) {
487       auto mapping = value.getAsArray();
488       if (mapping == nullptr || mapping->size() != 2 ||
489           (*mapping)[0].kind() != llvm::json::Value::String ||
490           (*mapping)[1].kind() != llvm::json::Value::String) {
491         g_vsc.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
492         return;
493       }
494       auto mapFrom = GetAsString((*mapping)[0]);
495       auto mapTo = GetAsString((*mapping)[1]);
496       strm << "\"" << mapFrom << "\" \"" << mapTo << "\" ";
497     }
498   } else {
499     if (ObjectContainsKey(arguments, "sourceMap")) {
500       g_vsc.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
501       return;
502     }
503     if (sourcePath.empty())
504       return;
505     // Do any source remapping needed before we create our targets
506     strm << "\".\" \"" << sourcePath << "\"";
507   }
508   strm.flush();
509   if (!sourceMapCommand.empty()) {
510     g_vsc.RunLLDBCommands("Setting source map:", {sourceMapCommand});
511   }
512 }
513 
514 // "AttachRequest": {
515 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
516 //     "type": "object",
517 //     "description": "Attach request; value of command field is 'attach'.",
518 //     "properties": {
519 //       "command": {
520 //         "type": "string",
521 //         "enum": [ "attach" ]
522 //       },
523 //       "arguments": {
524 //         "$ref": "#/definitions/AttachRequestArguments"
525 //       }
526 //     },
527 //     "required": [ "command", "arguments" ]
528 //   }]
529 // },
530 // "AttachRequestArguments": {
531 //   "type": "object",
532 //   "description": "Arguments for 'attach' request.\nThe attach request has no
533 //   standardized attributes."
534 // },
535 // "AttachResponse": {
536 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
537 //     "type": "object",
538 //     "description": "Response to 'attach' request. This is just an
539 //     acknowledgement, so no body field is required."
540 //   }]
541 // }
542 void request_attach(const llvm::json::Object &request) {
543   g_vsc.is_attach = true;
544   llvm::json::Object response;
545   lldb::SBError error;
546   FillResponse(request, response);
547   lldb::SBAttachInfo attach_info;
548   auto arguments = request.getObject("arguments");
549   const lldb::pid_t pid =
550       GetUnsigned(arguments, "pid", LLDB_INVALID_PROCESS_ID);
551   if (pid != LLDB_INVALID_PROCESS_ID)
552     attach_info.SetProcessID(pid);
553   const auto wait_for = GetBoolean(arguments, "waitFor", false);
554   attach_info.SetWaitForLaunch(wait_for, false /*async*/);
555   g_vsc.init_commands = GetStrings(arguments, "initCommands");
556   g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
557   g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
558   g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
559   g_vsc.terminate_commands = GetStrings(arguments, "terminateCommands");
560   auto attachCommands = GetStrings(arguments, "attachCommands");
561   llvm::StringRef core_file = GetString(arguments, "coreFile");
562   g_vsc.stop_at_entry =
563       core_file.empty() ? GetBoolean(arguments, "stopOnEntry", false) : true;
564   const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
565 
566   // This is a hack for loading DWARF in .o files on Mac where the .o files
567   // in the debug map of the main executable have relative paths which require
568   // the lldb-vscode binary to have its working directory set to that relative
569   // root for the .o files in order to be able to load debug info.
570   if (!debuggerRoot.empty())
571     llvm::sys::fs::set_current_path(debuggerRoot);
572 
573   // Run any initialize LLDB commands the user specified in the launch.json
574   g_vsc.RunInitCommands();
575 
576   lldb::SBError status;
577   g_vsc.SetTarget(g_vsc.CreateTargetFromArguments(*arguments, status));
578   if (status.Fail()) {
579     response["success"] = llvm::json::Value(false);
580     EmplaceSafeString(response, "message", status.GetCString());
581     g_vsc.SendJSON(llvm::json::Value(std::move(response)));
582     return;
583   }
584 
585   // Run any pre run LLDB commands the user specified in the launch.json
586   g_vsc.RunPreRunCommands();
587 
588   if (pid == LLDB_INVALID_PROCESS_ID && wait_for) {
589     char attach_msg[256];
590     auto attach_msg_len = snprintf(attach_msg, sizeof(attach_msg),
591                                    "Waiting to attach to \"%s\"...",
592                                    g_vsc.target.GetExecutable().GetFilename());
593     g_vsc.SendOutput(OutputType::Console,
594                      llvm::StringRef(attach_msg, attach_msg_len));
595   }
596   if (attachCommands.empty()) {
597     // No "attachCommands", just attach normally.
598     // Disable async events so the attach will be successful when we return from
599     // the launch call and the launch will happen synchronously
600     g_vsc.debugger.SetAsync(false);
601     if (core_file.empty())
602       g_vsc.target.Attach(attach_info, error);
603     else
604       g_vsc.target.LoadCore(core_file.data(), error);
605     // Reenable async events
606     g_vsc.debugger.SetAsync(true);
607   } else {
608     // We have "attachCommands" that are a set of commands that are expected
609     // to execute the commands after which a process should be created. If there
610     // is no valid process after running these commands, we have failed.
611     g_vsc.RunLLDBCommands("Running attachCommands:", attachCommands);
612     // The custom commands might have created a new target so we should use the
613     // selected target after these commands are run.
614     g_vsc.target = g_vsc.debugger.GetSelectedTarget();
615   }
616 
617   SetSourceMapFromArguments(*arguments);
618 
619   if (error.Success() && core_file.empty()) {
620     auto attached_pid = g_vsc.target.GetProcess().GetProcessID();
621     if (attached_pid == LLDB_INVALID_PROCESS_ID) {
622       if (attachCommands.empty())
623         error.SetErrorString("failed to attach to a process");
624       else
625         error.SetErrorString("attachCommands failed to attach to a process");
626     }
627   }
628 
629   if (error.Fail()) {
630     response["success"] = llvm::json::Value(false);
631     EmplaceSafeString(response, "message", std::string(error.GetCString()));
632   }
633   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
634   if (error.Success()) {
635     SendProcessEvent(Attach);
636     g_vsc.SendJSON(CreateEventObject("initialized"));
637     // SendThreadStoppedEvent();
638   }
639 }
640 
641 // "ContinueRequest": {
642 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
643 //     "type": "object",
644 //     "description": "Continue request; value of command field is 'continue'.
645 //                     The request starts the debuggee to run again.",
646 //     "properties": {
647 //       "command": {
648 //         "type": "string",
649 //         "enum": [ "continue" ]
650 //       },
651 //       "arguments": {
652 //         "$ref": "#/definitions/ContinueArguments"
653 //       }
654 //     },
655 //     "required": [ "command", "arguments"  ]
656 //   }]
657 // },
658 // "ContinueArguments": {
659 //   "type": "object",
660 //   "description": "Arguments for 'continue' request.",
661 //   "properties": {
662 //     "threadId": {
663 //       "type": "integer",
664 //       "description": "Continue execution for the specified thread (if
665 //                       possible). If the backend cannot continue on a single
666 //                       thread but will continue on all threads, it should
667 //                       set the allThreadsContinued attribute in the response
668 //                       to true."
669 //     }
670 //   },
671 //   "required": [ "threadId" ]
672 // },
673 // "ContinueResponse": {
674 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
675 //     "type": "object",
676 //     "description": "Response to 'continue' request.",
677 //     "properties": {
678 //       "body": {
679 //         "type": "object",
680 //         "properties": {
681 //           "allThreadsContinued": {
682 //             "type": "boolean",
683 //             "description": "If true, the continue request has ignored the
684 //                             specified thread and continued all threads
685 //                             instead. If this attribute is missing a value
686 //                             of 'true' is assumed for backward
687 //                             compatibility."
688 //           }
689 //         }
690 //       }
691 //     },
692 //     "required": [ "body" ]
693 //   }]
694 // }
695 void request_continue(const llvm::json::Object &request) {
696   llvm::json::Object response;
697   FillResponse(request, response);
698   lldb::SBProcess process = g_vsc.target.GetProcess();
699   auto arguments = request.getObject("arguments");
700   // Remember the thread ID that caused the resume so we can set the
701   // "threadCausedFocus" boolean value in the "stopped" events.
702   g_vsc.focus_tid = GetUnsigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
703   lldb::SBError error = process.Continue();
704   llvm::json::Object body;
705   body.try_emplace("allThreadsContinued", true);
706   response.try_emplace("body", std::move(body));
707   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
708 }
709 
710 // "ConfigurationDoneRequest": {
711 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
712 //             "type": "object",
713 //             "description": "ConfigurationDone request; value of command field
714 //             is 'configurationDone'.\nThe client of the debug protocol must
715 //             send this request at the end of the sequence of configuration
716 //             requests (which was started by the InitializedEvent).",
717 //             "properties": {
718 //             "command": {
719 //             "type": "string",
720 //             "enum": [ "configurationDone" ]
721 //             },
722 //             "arguments": {
723 //             "$ref": "#/definitions/ConfigurationDoneArguments"
724 //             }
725 //             },
726 //             "required": [ "command" ]
727 //             }]
728 // },
729 // "ConfigurationDoneArguments": {
730 //   "type": "object",
731 //   "description": "Arguments for 'configurationDone' request.\nThe
732 //   configurationDone request has no standardized attributes."
733 // },
734 // "ConfigurationDoneResponse": {
735 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
736 //             "type": "object",
737 //             "description": "Response to 'configurationDone' request. This is
738 //             just an acknowledgement, so no body field is required."
739 //             }]
740 // },
741 void request_configurationDone(const llvm::json::Object &request) {
742   llvm::json::Object response;
743   FillResponse(request, response);
744   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
745   if (g_vsc.stop_at_entry)
746     SendThreadStoppedEvent();
747   else
748     g_vsc.target.GetProcess().Continue();
749 }
750 
751 // "DisconnectRequest": {
752 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
753 //     "type": "object",
754 //     "description": "Disconnect request; value of command field is
755 //                     'disconnect'.",
756 //     "properties": {
757 //       "command": {
758 //         "type": "string",
759 //         "enum": [ "disconnect" ]
760 //       },
761 //       "arguments": {
762 //         "$ref": "#/definitions/DisconnectArguments"
763 //       }
764 //     },
765 //     "required": [ "command" ]
766 //   }]
767 // },
768 // "DisconnectArguments": {
769 //   "type": "object",
770 //   "description": "Arguments for 'disconnect' request.",
771 //   "properties": {
772 //     "terminateDebuggee": {
773 //       "type": "boolean",
774 //       "description": "Indicates whether the debuggee should be terminated
775 //                       when the debugger is disconnected. If unspecified,
776 //                       the debug adapter is free to do whatever it thinks
777 //                       is best. A client can only rely on this attribute
778 //                       being properly honored if a debug adapter returns
779 //                       true for the 'supportTerminateDebuggee' capability."
780 //     },
781 //     "restart": {
782 //       "type": "boolean",
783 //       "description": "Indicates whether the debuggee should be restart
784 //                       the process."
785 //     }
786 //   }
787 // },
788 // "DisconnectResponse": {
789 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
790 //     "type": "object",
791 //     "description": "Response to 'disconnect' request. This is just an
792 //                     acknowledgement, so no body field is required."
793 //   }]
794 // }
795 void request_disconnect(const llvm::json::Object &request) {
796   llvm::json::Object response;
797   FillResponse(request, response);
798   auto arguments = request.getObject("arguments");
799 
800   bool defaultTerminateDebuggee = g_vsc.is_attach ? false : true;
801   bool terminateDebuggee =
802       GetBoolean(arguments, "terminateDebuggee", defaultTerminateDebuggee);
803   lldb::SBProcess process = g_vsc.target.GetProcess();
804   auto state = process.GetState();
805   switch (state) {
806   case lldb::eStateInvalid:
807   case lldb::eStateUnloaded:
808   case lldb::eStateDetached:
809   case lldb::eStateExited:
810     break;
811   case lldb::eStateConnected:
812   case lldb::eStateAttaching:
813   case lldb::eStateLaunching:
814   case lldb::eStateStepping:
815   case lldb::eStateCrashed:
816   case lldb::eStateSuspended:
817   case lldb::eStateStopped:
818   case lldb::eStateRunning:
819     g_vsc.debugger.SetAsync(false);
820     lldb::SBError error = terminateDebuggee ? process.Kill() : process.Detach();
821     if (!error.Success())
822       response.try_emplace("error", error.GetCString());
823     g_vsc.debugger.SetAsync(true);
824     break;
825   }
826   SendTerminatedEvent();
827   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
828   if (g_vsc.event_thread.joinable()) {
829     g_vsc.broadcaster.BroadcastEventByType(eBroadcastBitStopEventThread);
830     g_vsc.event_thread.join();
831   }
832 }
833 
834 void request_exceptionInfo(const llvm::json::Object &request) {
835   llvm::json::Object response;
836   FillResponse(request, response);
837   auto arguments = request.getObject("arguments");
838   llvm::json::Object body;
839   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
840   if (thread.IsValid()) {
841     auto stopReason = thread.GetStopReason();
842     if (stopReason == lldb::eStopReasonSignal)
843       body.try_emplace("exceptionId", "signal");
844     else if (stopReason == lldb::eStopReasonBreakpoint) {
845       ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
846       if (exc_bp) {
847         EmplaceSafeString(body, "exceptionId", exc_bp->filter);
848         EmplaceSafeString(body, "description", exc_bp->label);
849       } else {
850         body.try_emplace("exceptionId", "exception");
851       }
852     } else {
853       body.try_emplace("exceptionId", "exception");
854     }
855     if (!ObjectContainsKey(body, "description")) {
856       char description[1024];
857       if (thread.GetStopDescription(description, sizeof(description))) {
858         EmplaceSafeString(body, "description", std::string(description));
859       }
860     }
861     body.try_emplace("breakMode", "always");
862     // auto excInfoCount = thread.GetStopReasonDataCount();
863     // for (auto i=0; i<excInfoCount; ++i) {
864     //   uint64_t exc_data = thread.GetStopReasonDataAtIndex(i);
865     // }
866   } else {
867     response["success"] = llvm::json::Value(false);
868   }
869   response.try_emplace("body", std::move(body));
870   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
871 }
872 
873 // "CompletionsRequest": {
874 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
875 //     "type": "object",
876 //     "description": "Returns a list of possible completions for a given caret position and text.\nThe CompletionsRequest may only be called if the 'supportsCompletionsRequest' capability exists and is true.",
877 //     "properties": {
878 //       "command": {
879 //         "type": "string",
880 //         "enum": [ "completions" ]
881 //       },
882 //       "arguments": {
883 //         "$ref": "#/definitions/CompletionsArguments"
884 //       }
885 //     },
886 //     "required": [ "command", "arguments"  ]
887 //   }]
888 // },
889 // "CompletionsArguments": {
890 //   "type": "object",
891 //   "description": "Arguments for 'completions' request.",
892 //   "properties": {
893 //     "frameId": {
894 //       "type": "integer",
895 //       "description": "Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope."
896 //     },
897 //     "text": {
898 //       "type": "string",
899 //       "description": "One or more source lines. Typically this is the text a user has typed into the debug console before he asked for completion."
900 //     },
901 //     "column": {
902 //       "type": "integer",
903 //       "description": "The character position for which to determine the completion proposals."
904 //     },
905 //     "line": {
906 //       "type": "integer",
907 //       "description": "An optional line for which to determine the completion proposals. If missing the first line of the text is assumed."
908 //     }
909 //   },
910 //   "required": [ "text", "column" ]
911 // },
912 // "CompletionsResponse": {
913 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
914 //     "type": "object",
915 //     "description": "Response to 'completions' request.",
916 //     "properties": {
917 //       "body": {
918 //         "type": "object",
919 //         "properties": {
920 //           "targets": {
921 //             "type": "array",
922 //             "items": {
923 //               "$ref": "#/definitions/CompletionItem"
924 //             },
925 //             "description": "The possible completions for ."
926 //           }
927 //         },
928 //         "required": [ "targets" ]
929 //       }
930 //     },
931 //     "required": [ "body" ]
932 //   }]
933 // },
934 // "CompletionItem": {
935 //   "type": "object",
936 //   "description": "CompletionItems are the suggestions returned from the CompletionsRequest.",
937 //   "properties": {
938 //     "label": {
939 //       "type": "string",
940 //       "description": "The label of this completion item. By default this is also the text that is inserted when selecting this completion."
941 //     },
942 //     "text": {
943 //       "type": "string",
944 //       "description": "If text is not falsy then it is inserted instead of the label."
945 //     },
946 //     "sortText": {
947 //       "type": "string",
948 //       "description": "A string that should be used when comparing this item with other items. When `falsy` the label is used."
949 //     },
950 //     "type": {
951 //       "$ref": "#/definitions/CompletionItemType",
952 //       "description": "The item's type. Typically the client uses this information to render the item in the UI with an icon."
953 //     },
954 //     "start": {
955 //       "type": "integer",
956 //       "description": "This value determines the location (in the CompletionsRequest's 'text' attribute) where the completion text is added.\nIf missing the text is added at the location specified by the CompletionsRequest's 'column' attribute."
957 //     },
958 //     "length": {
959 //       "type": "integer",
960 //       "description": "This value determines how many characters are overwritten by the completion text.\nIf missing the value 0 is assumed which results in the completion text being inserted."
961 //     }
962 //   },
963 //   "required": [ "label" ]
964 // },
965 // "CompletionItemType": {
966 //   "type": "string",
967 //   "description": "Some predefined types for the CompletionItem. Please note that not all clients have specific icons for all of them.",
968 //   "enum": [ "method", "function", "constructor", "field", "variable", "class", "interface", "module", "property", "unit", "value", "enum", "keyword", "snippet", "text", "color", "file", "reference", "customcolor" ]
969 // }
970 void request_completions(const llvm::json::Object &request) {
971   llvm::json::Object response;
972   FillResponse(request, response);
973   llvm::json::Object body;
974   auto arguments = request.getObject("arguments");
975   std::string text = std::string(GetString(arguments, "text"));
976   auto original_column = GetSigned(arguments, "column", text.size());
977   auto actual_column = original_column - 1;
978   llvm::json::Array targets;
979   // NOTE: the 'line' argument is not needed, as multiline expressions
980   // work well already
981   // TODO: support frameID. Currently
982   // g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions
983   // is frame-unaware.
984 
985   if (!text.empty() && text[0] == '`') {
986     text = text.substr(1);
987     actual_column--;
988   } else {
989     text = "p " + text;
990     actual_column += 2;
991   }
992   lldb::SBStringList matches;
993   lldb::SBStringList descriptions;
994   g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
995     text.c_str(),
996     actual_column,
997     0, -1, matches, descriptions);
998   size_t count = std::min((uint32_t)100, matches.GetSize());
999   targets.reserve(count);
1000   for (size_t i = 0; i < count; i++) {
1001     std::string match = matches.GetStringAtIndex(i);
1002     std::string description = descriptions.GetStringAtIndex(i);
1003 
1004     llvm::json::Object item;
1005 
1006     llvm::StringRef match_ref = match;
1007     for(llvm::StringRef commit_point: {".", "->"}) {
1008       if (match_ref.contains(commit_point)){
1009         match_ref = match_ref.rsplit(commit_point).second;
1010       }
1011     }
1012     EmplaceSafeString(item, "text", match_ref);
1013 
1014     if (description.empty())
1015       EmplaceSafeString(item, "label", match);
1016     else
1017       EmplaceSafeString(item, "label", match + " -- " + description);
1018 
1019     targets.emplace_back(std::move(item));
1020   }
1021 
1022   body.try_emplace("targets", std::move(targets));
1023   response.try_emplace("body", std::move(body));
1024   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1025 }
1026 
1027 //  "EvaluateRequest": {
1028 //    "allOf": [ { "$ref": "#/definitions/Request" }, {
1029 //      "type": "object",
1030 //      "description": "Evaluate request; value of command field is 'evaluate'.
1031 //                      Evaluates the given expression in the context of the
1032 //                      top most stack frame. The expression has access to any
1033 //                      variables and arguments that are in scope.",
1034 //      "properties": {
1035 //        "command": {
1036 //          "type": "string",
1037 //          "enum": [ "evaluate" ]
1038 //        },
1039 //        "arguments": {
1040 //          "$ref": "#/definitions/EvaluateArguments"
1041 //        }
1042 //      },
1043 //      "required": [ "command", "arguments"  ]
1044 //    }]
1045 //  },
1046 //  "EvaluateArguments": {
1047 //    "type": "object",
1048 //    "description": "Arguments for 'evaluate' request.",
1049 //    "properties": {
1050 //      "expression": {
1051 //        "type": "string",
1052 //        "description": "The expression to evaluate."
1053 //      },
1054 //      "frameId": {
1055 //        "type": "integer",
1056 //        "description": "Evaluate the expression in the scope of this stack
1057 //                        frame. If not specified, the expression is evaluated
1058 //                        in the global scope."
1059 //      },
1060 //      "context": {
1061 //        "type": "string",
1062 //        "_enum": [ "watch", "repl", "hover" ],
1063 //        "enumDescriptions": [
1064 //          "evaluate is run in a watch.",
1065 //          "evaluate is run from REPL console.",
1066 //          "evaluate is run from a data hover."
1067 //        ],
1068 //        "description": "The context in which the evaluate request is run."
1069 //      },
1070 //      "format": {
1071 //        "$ref": "#/definitions/ValueFormat",
1072 //        "description": "Specifies details on how to format the Evaluate
1073 //                        result."
1074 //      }
1075 //    },
1076 //    "required": [ "expression" ]
1077 //  },
1078 //  "EvaluateResponse": {
1079 //    "allOf": [ { "$ref": "#/definitions/Response" }, {
1080 //      "type": "object",
1081 //      "description": "Response to 'evaluate' request.",
1082 //      "properties": {
1083 //        "body": {
1084 //          "type": "object",
1085 //          "properties": {
1086 //            "result": {
1087 //              "type": "string",
1088 //              "description": "The result of the evaluate request."
1089 //            },
1090 //            "type": {
1091 //              "type": "string",
1092 //              "description": "The optional type of the evaluate result."
1093 //            },
1094 //            "presentationHint": {
1095 //              "$ref": "#/definitions/VariablePresentationHint",
1096 //              "description": "Properties of a evaluate result that can be
1097 //                              used to determine how to render the result in
1098 //                              the UI."
1099 //            },
1100 //            "variablesReference": {
1101 //              "type": "number",
1102 //              "description": "If variablesReference is > 0, the evaluate
1103 //                              result is structured and its children can be
1104 //                              retrieved by passing variablesReference to the
1105 //                              VariablesRequest."
1106 //            },
1107 //            "namedVariables": {
1108 //              "type": "number",
1109 //              "description": "The number of named child variables. The
1110 //                              client can use this optional information to
1111 //                              present the variables in a paged UI and fetch
1112 //                              them in chunks."
1113 //            },
1114 //            "indexedVariables": {
1115 //              "type": "number",
1116 //              "description": "The number of indexed child variables. The
1117 //                              client can use this optional information to
1118 //                              present the variables in a paged UI and fetch
1119 //                              them in chunks."
1120 //            }
1121 //          },
1122 //          "required": [ "result", "variablesReference" ]
1123 //        }
1124 //      },
1125 //      "required": [ "body" ]
1126 //    }]
1127 //  }
1128 void request_evaluate(const llvm::json::Object &request) {
1129   llvm::json::Object response;
1130   FillResponse(request, response);
1131   llvm::json::Object body;
1132   auto arguments = request.getObject("arguments");
1133   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
1134   const auto expression = GetString(arguments, "expression");
1135 
1136   if (!expression.empty() && expression[0] == '`') {
1137     auto result =
1138         RunLLDBCommands(llvm::StringRef(), {std::string(expression.substr(1))});
1139     EmplaceSafeString(body, "result", result);
1140     body.try_emplace("variablesReference", (int64_t)0);
1141   } else {
1142     // Always try to get the answer from the local variables if possible. If
1143     // this fails, then actually evaluate an expression using the expression
1144     // parser. "frame variable" is more reliable than the expression parser in
1145     // many cases and it is faster.
1146     lldb::SBValue value = frame.GetValueForVariablePath(
1147         expression.data(), lldb::eDynamicDontRunTarget);
1148     if (value.GetError().Fail())
1149       value = frame.EvaluateExpression(expression.data());
1150     if (value.GetError().Fail()) {
1151       response["success"] = llvm::json::Value(false);
1152       // This error object must live until we're done with the pointer returned
1153       // by GetCString().
1154       lldb::SBError error = value.GetError();
1155       const char *error_cstr = error.GetCString();
1156       if (error_cstr && error_cstr[0])
1157         EmplaceSafeString(response, "message", std::string(error_cstr));
1158       else
1159         EmplaceSafeString(response, "message", "evaluate failed");
1160     } else {
1161       SetValueForKey(value, body, "result");
1162       auto value_typename = value.GetType().GetDisplayTypeName();
1163       EmplaceSafeString(body, "type", value_typename ? value_typename : NO_TYPENAME);
1164       if (value.MightHaveChildren()) {
1165         auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
1166         g_vsc.variables.Append(value);
1167         body.try_emplace("variablesReference", variablesReference);
1168       } else {
1169         body.try_emplace("variablesReference", (int64_t)0);
1170       }
1171     }
1172   }
1173   response.try_emplace("body", std::move(body));
1174   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1175 }
1176 
1177 // "getCompileUnitsRequest": {
1178 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1179 //     "type": "object",
1180 //     "description": "Compile Unit request; value of command field is
1181 //                     'getCompileUnits'.",
1182 //     "properties": {
1183 //       "command": {
1184 //         "type": "string",
1185 //         "enum": [ "getCompileUnits" ]
1186 //       },
1187 //       "arguments": {
1188 //         "$ref": "#/definitions/getCompileUnitRequestArguments"
1189 //       }
1190 //     },
1191 //     "required": [ "command", "arguments" ]
1192 //   }]
1193 // },
1194 // "getCompileUnitsRequestArguments": {
1195 //   "type": "object",
1196 //   "description": "Arguments for 'getCompileUnits' request.",
1197 //   "properties": {
1198 //     "moduleId": {
1199 //       "type": "string",
1200 //       "description": "The ID of the module."
1201 //     }
1202 //   },
1203 //   "required": [ "moduleId" ]
1204 // },
1205 // "getCompileUnitsResponse": {
1206 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1207 //     "type": "object",
1208 //     "description": "Response to 'getCompileUnits' request.",
1209 //     "properties": {
1210 //       "body": {
1211 //         "description": "Response to 'getCompileUnits' request. Array of
1212 //                         paths of compile units."
1213 //       }
1214 //     }
1215 //   }]
1216 // }
1217 
1218 void request_getCompileUnits(const llvm::json::Object &request) {
1219   llvm::json::Object response;
1220   FillResponse(request, response);
1221   lldb::SBProcess process = g_vsc.target.GetProcess();
1222   llvm::json::Object body;
1223   llvm::json::Array units;
1224   auto arguments = request.getObject("arguments");
1225   std::string module_id = std::string(GetString(arguments, "moduleId"));
1226   int num_modules = g_vsc.target.GetNumModules();
1227   for (int i = 0; i < num_modules; i++) {
1228     auto curr_module = g_vsc.target.GetModuleAtIndex(i);
1229     if (module_id == curr_module.GetUUIDString()) {
1230       int num_units = curr_module.GetNumCompileUnits();
1231       for (int j = 0; j < num_units; j++) {
1232         auto curr_unit = curr_module.GetCompileUnitAtIndex(j);\
1233         units.emplace_back(CreateCompileUnit(curr_unit));\
1234       }
1235       body.try_emplace("compileUnits", std::move(units));
1236       break;
1237     }
1238   }
1239   response.try_emplace("body", std::move(body));
1240   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1241 }
1242 
1243 // "InitializeRequest": {
1244 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1245 //     "type": "object",
1246 //     "description": "Initialize request; value of command field is
1247 //                     'initialize'.",
1248 //     "properties": {
1249 //       "command": {
1250 //         "type": "string",
1251 //         "enum": [ "initialize" ]
1252 //       },
1253 //       "arguments": {
1254 //         "$ref": "#/definitions/InitializeRequestArguments"
1255 //       }
1256 //     },
1257 //     "required": [ "command", "arguments" ]
1258 //   }]
1259 // },
1260 // "InitializeRequestArguments": {
1261 //   "type": "object",
1262 //   "description": "Arguments for 'initialize' request.",
1263 //   "properties": {
1264 //     "clientID": {
1265 //       "type": "string",
1266 //       "description": "The ID of the (frontend) client using this adapter."
1267 //     },
1268 //     "adapterID": {
1269 //       "type": "string",
1270 //       "description": "The ID of the debug adapter."
1271 //     },
1272 //     "locale": {
1273 //       "type": "string",
1274 //       "description": "The ISO-639 locale of the (frontend) client using
1275 //                       this adapter, e.g. en-US or de-CH."
1276 //     },
1277 //     "linesStartAt1": {
1278 //       "type": "boolean",
1279 //       "description": "If true all line numbers are 1-based (default)."
1280 //     },
1281 //     "columnsStartAt1": {
1282 //       "type": "boolean",
1283 //       "description": "If true all column numbers are 1-based (default)."
1284 //     },
1285 //     "pathFormat": {
1286 //       "type": "string",
1287 //       "_enum": [ "path", "uri" ],
1288 //       "description": "Determines in what format paths are specified. The
1289 //                       default is 'path', which is the native format."
1290 //     },
1291 //     "supportsVariableType": {
1292 //       "type": "boolean",
1293 //       "description": "Client supports the optional type attribute for
1294 //                       variables."
1295 //     },
1296 //     "supportsVariablePaging": {
1297 //       "type": "boolean",
1298 //       "description": "Client supports the paging of variables."
1299 //     },
1300 //     "supportsRunInTerminalRequest": {
1301 //       "type": "boolean",
1302 //       "description": "Client supports the runInTerminal request."
1303 //     }
1304 //   },
1305 //   "required": [ "adapterID" ]
1306 // },
1307 // "InitializeResponse": {
1308 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1309 //     "type": "object",
1310 //     "description": "Response to 'initialize' request.",
1311 //     "properties": {
1312 //       "body": {
1313 //         "$ref": "#/definitions/Capabilities",
1314 //         "description": "The capabilities of this debug adapter."
1315 //       }
1316 //     }
1317 //   }]
1318 // }
1319 void request_initialize(const llvm::json::Object &request) {
1320   g_vsc.debugger = lldb::SBDebugger::Create(true /*source_init_files*/);
1321   // Create an empty target right away since we might get breakpoint requests
1322   // before we are given an executable to launch in a "launch" request, or a
1323   // executable when attaching to a process by process ID in a "attach"
1324   // request.
1325   FILE *out = llvm::sys::RetryAfterSignal(nullptr, fopen, dev_null_path, "w");
1326   if (out) {
1327     // Set the output and error file handles to redirect into nothing otherwise
1328     // if any code in LLDB prints to the debugger file handles, the output and
1329     // error file handles are initialized to STDOUT and STDERR and any output
1330     // will kill our debug session.
1331     g_vsc.debugger.SetOutputFileHandle(out, true);
1332     g_vsc.debugger.SetErrorFileHandle(out, false);
1333   }
1334 
1335   // Start our event thread so we can receive events from the debugger, target,
1336   // process and more.
1337   g_vsc.event_thread = std::thread(EventThreadFunction);
1338 
1339   llvm::json::Object response;
1340   FillResponse(request, response);
1341   llvm::json::Object body;
1342   // The debug adapter supports the configurationDoneRequest.
1343   body.try_emplace("supportsConfigurationDoneRequest", true);
1344   // The debug adapter supports function breakpoints.
1345   body.try_emplace("supportsFunctionBreakpoints", true);
1346   // The debug adapter supports conditional breakpoints.
1347   body.try_emplace("supportsConditionalBreakpoints", true);
1348   // The debug adapter supports breakpoints that break execution after a
1349   // specified number of hits.
1350   body.try_emplace("supportsHitConditionalBreakpoints", true);
1351   // The debug adapter supports a (side effect free) evaluate request for
1352   // data hovers.
1353   body.try_emplace("supportsEvaluateForHovers", true);
1354   // Available filters or options for the setExceptionBreakpoints request.
1355   llvm::json::Array filters;
1356   for (const auto &exc_bp : g_vsc.exception_breakpoints) {
1357     filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
1358   }
1359   body.try_emplace("exceptionBreakpointFilters", std::move(filters));
1360   // The debug adapter supports stepping back via the stepBack and
1361   // reverseContinue requests.
1362   body.try_emplace("supportsStepBack", false);
1363   // The debug adapter supports setting a variable to a value.
1364   body.try_emplace("supportsSetVariable", true);
1365   // The debug adapter supports restarting a frame.
1366   body.try_emplace("supportsRestartFrame", false);
1367   // The debug adapter supports the gotoTargetsRequest.
1368   body.try_emplace("supportsGotoTargetsRequest", false);
1369   // The debug adapter supports the stepInTargetsRequest.
1370   body.try_emplace("supportsStepInTargetsRequest", false);
1371   // We need to improve the current implementation of completions in order to
1372   // enable it again. For some context, this is how VSCode works:
1373   // - VSCode sends a completion request whenever chars are added, the user
1374   //   triggers completion manually via CTRL-space or similar mechanisms, but
1375   //   not when there's a deletion. Besides, VSCode doesn't let us know which
1376   //   of these events we are handling. What is more, the use can paste or cut
1377   //   sections of the text arbitrarily.
1378   //   https://github.com/microsoft/vscode/issues/89531 tracks part of the
1379   //   issue just mentioned.
1380   // This behavior causes many problems with the current way completion is
1381   // implemented in lldb-vscode, as these requests could be really expensive,
1382   // blocking the debugger, and there could be many concurrent requests unless
1383   // the user types very slowly... We need to address this specific issue, or
1384   // at least trigger completion only when the user explicitly wants it, which
1385   // is the behavior of LLDB CLI, that expects a TAB.
1386   body.try_emplace("supportsCompletionsRequest", false);
1387   // The debug adapter supports the modules request.
1388   body.try_emplace("supportsModulesRequest", false);
1389   // The set of additional module information exposed by the debug adapter.
1390   //   body.try_emplace("additionalModuleColumns"] = ColumnDescriptor
1391   // Checksum algorithms supported by the debug adapter.
1392   //   body.try_emplace("supportedChecksumAlgorithms"] = ChecksumAlgorithm
1393   // The debug adapter supports the RestartRequest. In this case a client
1394   // should not implement 'restart' by terminating and relaunching the adapter
1395   // but by calling the RestartRequest.
1396   body.try_emplace("supportsRestartRequest", false);
1397   // The debug adapter supports 'exceptionOptions' on the
1398   // setExceptionBreakpoints request.
1399   body.try_emplace("supportsExceptionOptions", true);
1400   // The debug adapter supports a 'format' attribute on the stackTraceRequest,
1401   // variablesRequest, and evaluateRequest.
1402   body.try_emplace("supportsValueFormattingOptions", true);
1403   // The debug adapter supports the exceptionInfo request.
1404   body.try_emplace("supportsExceptionInfoRequest", true);
1405   // The debug adapter supports the 'terminateDebuggee' attribute on the
1406   // 'disconnect' request.
1407   body.try_emplace("supportTerminateDebuggee", true);
1408   // The debug adapter supports the delayed loading of parts of the stack,
1409   // which requires that both the 'startFrame' and 'levels' arguments and the
1410   // 'totalFrames' result of the 'StackTrace' request are supported.
1411   body.try_emplace("supportsDelayedStackTraceLoading", true);
1412   // The debug adapter supports the 'loadedSources' request.
1413   body.try_emplace("supportsLoadedSourcesRequest", false);
1414 
1415   response.try_emplace("body", std::move(body));
1416   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1417 }
1418 
1419 // "LaunchRequest": {
1420 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1421 //     "type": "object",
1422 //     "description": "Launch request; value of command field is 'launch'.",
1423 //     "properties": {
1424 //       "command": {
1425 //         "type": "string",
1426 //         "enum": [ "launch" ]
1427 //       },
1428 //       "arguments": {
1429 //         "$ref": "#/definitions/LaunchRequestArguments"
1430 //       }
1431 //     },
1432 //     "required": [ "command", "arguments"  ]
1433 //   }]
1434 // },
1435 // "LaunchRequestArguments": {
1436 //   "type": "object",
1437 //   "description": "Arguments for 'launch' request.",
1438 //   "properties": {
1439 //     "noDebug": {
1440 //       "type": "boolean",
1441 //       "description": "If noDebug is true the launch request should launch
1442 //                       the program without enabling debugging."
1443 //     }
1444 //   }
1445 // },
1446 // "LaunchResponse": {
1447 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1448 //     "type": "object",
1449 //     "description": "Response to 'launch' request. This is just an
1450 //                     acknowledgement, so no body field is required."
1451 //   }]
1452 // }
1453 void request_launch(const llvm::json::Object &request) {
1454   g_vsc.is_attach = false;
1455   llvm::json::Object response;
1456   lldb::SBError error;
1457   FillResponse(request, response);
1458   auto arguments = request.getObject("arguments");
1459   g_vsc.init_commands = GetStrings(arguments, "initCommands");
1460   g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
1461   g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
1462   g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
1463   g_vsc.terminate_commands = GetStrings(arguments, "terminateCommands");
1464   auto launchCommands = GetStrings(arguments, "launchCommands");
1465   g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
1466   const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
1467 
1468   // This is a hack for loading DWARF in .o files on Mac where the .o files
1469   // in the debug map of the main executable have relative paths which require
1470   // the lldb-vscode binary to have its working directory set to that relative
1471   // root for the .o files in order to be able to load debug info.
1472   if (!debuggerRoot.empty())
1473     llvm::sys::fs::set_current_path(debuggerRoot);
1474 
1475   // Run any initialize LLDB commands the user specified in the launch.json.
1476   // This is run before target is created, so commands can't do anything with
1477   // the targets - preRunCommands are run with the target.
1478   g_vsc.RunInitCommands();
1479 
1480   SetSourceMapFromArguments(*arguments);
1481 
1482   lldb::SBError status;
1483   g_vsc.SetTarget(g_vsc.CreateTargetFromArguments(*arguments, status));
1484   if (status.Fail()) {
1485     response["success"] = llvm::json::Value(false);
1486     EmplaceSafeString(response, "message", status.GetCString());
1487     g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1488     return;
1489   }
1490 
1491   // Instantiate a launch info instance for the target.
1492   auto launch_info = g_vsc.target.GetLaunchInfo();
1493 
1494   // Grab the current working directory if there is one and set it in the
1495   // launch info.
1496   const auto cwd = GetString(arguments, "cwd");
1497   if (!cwd.empty())
1498     launch_info.SetWorkingDirectory(cwd.data());
1499 
1500   // Extract any extra arguments and append them to our program arguments for
1501   // when we launch
1502   auto args = GetStrings(arguments, "args");
1503   if (!args.empty())
1504     launch_info.SetArguments(MakeArgv(args).data(), true);
1505 
1506   // Pass any environment variables along that the user specified.
1507   auto envs = GetStrings(arguments, "env");
1508   if (!envs.empty())
1509     launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
1510 
1511   auto flags = launch_info.GetLaunchFlags();
1512 
1513   if (GetBoolean(arguments, "disableASLR", true))
1514     flags |= lldb::eLaunchFlagDisableASLR;
1515   if (GetBoolean(arguments, "disableSTDIO", false))
1516     flags |= lldb::eLaunchFlagDisableSTDIO;
1517   if (GetBoolean(arguments, "shellExpandArguments", false))
1518     flags |= lldb::eLaunchFlagShellExpandArguments;
1519   const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
1520   launch_info.SetDetachOnError(detatchOnError);
1521   launch_info.SetLaunchFlags(flags | lldb::eLaunchFlagDebug |
1522                              lldb::eLaunchFlagStopAtEntry);
1523 
1524   // Run any pre run LLDB commands the user specified in the launch.json
1525   g_vsc.RunPreRunCommands();
1526   if (launchCommands.empty()) {
1527     // Disable async events so the launch will be successful when we return from
1528     // the launch call and the launch will happen synchronously
1529     g_vsc.debugger.SetAsync(false);
1530     g_vsc.target.Launch(launch_info, error);
1531     g_vsc.debugger.SetAsync(true);
1532   } else {
1533     g_vsc.RunLLDBCommands("Running launchCommands:", launchCommands);
1534     // The custom commands might have created a new target so we should use the
1535     // selected target after these commands are run.
1536     g_vsc.target = g_vsc.debugger.GetSelectedTarget();
1537   }
1538 
1539   if (error.Fail()) {
1540     response["success"] = llvm::json::Value(false);
1541     EmplaceSafeString(response, "message", std::string(error.GetCString()));
1542   }
1543   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1544 
1545   SendProcessEvent(Launch);
1546   g_vsc.SendJSON(llvm::json::Value(CreateEventObject("initialized")));
1547   // Reenable async events and start the event thread to catch async events.
1548   // g_vsc.debugger.SetAsync(true);
1549 }
1550 
1551 // "NextRequest": {
1552 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1553 //     "type": "object",
1554 //     "description": "Next request; value of command field is 'next'. The
1555 //                     request starts the debuggee to run again for one step.
1556 //                     The debug adapter first sends the NextResponse and then
1557 //                     a StoppedEvent (event type 'step') after the step has
1558 //                     completed.",
1559 //     "properties": {
1560 //       "command": {
1561 //         "type": "string",
1562 //         "enum": [ "next" ]
1563 //       },
1564 //       "arguments": {
1565 //         "$ref": "#/definitions/NextArguments"
1566 //       }
1567 //     },
1568 //     "required": [ "command", "arguments"  ]
1569 //   }]
1570 // },
1571 // "NextArguments": {
1572 //   "type": "object",
1573 //   "description": "Arguments for 'next' request.",
1574 //   "properties": {
1575 //     "threadId": {
1576 //       "type": "integer",
1577 //       "description": "Execute 'next' for this thread."
1578 //     }
1579 //   },
1580 //   "required": [ "threadId" ]
1581 // },
1582 // "NextResponse": {
1583 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1584 //     "type": "object",
1585 //     "description": "Response to 'next' request. This is just an
1586 //                     acknowledgement, so no body field is required."
1587 //   }]
1588 // }
1589 void request_next(const llvm::json::Object &request) {
1590   llvm::json::Object response;
1591   FillResponse(request, response);
1592   auto arguments = request.getObject("arguments");
1593   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
1594   if (thread.IsValid()) {
1595     // Remember the thread ID that caused the resume so we can set the
1596     // "threadCausedFocus" boolean value in the "stopped" events.
1597     g_vsc.focus_tid = thread.GetThreadID();
1598     thread.StepOver();
1599   } else {
1600     response["success"] = llvm::json::Value(false);
1601   }
1602   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1603 }
1604 
1605 // "PauseRequest": {
1606 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1607 //     "type": "object",
1608 //     "description": "Pause request; value of command field is 'pause'. The
1609 //     request suspenses the debuggee. The debug adapter first sends the
1610 //     PauseResponse and then a StoppedEvent (event type 'pause') after the
1611 //     thread has been paused successfully.", "properties": {
1612 //       "command": {
1613 //         "type": "string",
1614 //         "enum": [ "pause" ]
1615 //       },
1616 //       "arguments": {
1617 //         "$ref": "#/definitions/PauseArguments"
1618 //       }
1619 //     },
1620 //     "required": [ "command", "arguments"  ]
1621 //   }]
1622 // },
1623 // "PauseArguments": {
1624 //   "type": "object",
1625 //   "description": "Arguments for 'pause' request.",
1626 //   "properties": {
1627 //     "threadId": {
1628 //       "type": "integer",
1629 //       "description": "Pause execution for this thread."
1630 //     }
1631 //   },
1632 //   "required": [ "threadId" ]
1633 // },
1634 // "PauseResponse": {
1635 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1636 //     "type": "object",
1637 //     "description": "Response to 'pause' request. This is just an
1638 //     acknowledgement, so no body field is required."
1639 //   }]
1640 // }
1641 void request_pause(const llvm::json::Object &request) {
1642   llvm::json::Object response;
1643   FillResponse(request, response);
1644   lldb::SBProcess process = g_vsc.target.GetProcess();
1645   lldb::SBError error = process.Stop();
1646   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1647 }
1648 
1649 // "ScopesRequest": {
1650 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1651 //     "type": "object",
1652 //     "description": "Scopes request; value of command field is 'scopes'. The
1653 //     request returns the variable scopes for a given stackframe ID.",
1654 //     "properties": {
1655 //       "command": {
1656 //         "type": "string",
1657 //         "enum": [ "scopes" ]
1658 //       },
1659 //       "arguments": {
1660 //         "$ref": "#/definitions/ScopesArguments"
1661 //       }
1662 //     },
1663 //     "required": [ "command", "arguments"  ]
1664 //   }]
1665 // },
1666 // "ScopesArguments": {
1667 //   "type": "object",
1668 //   "description": "Arguments for 'scopes' request.",
1669 //   "properties": {
1670 //     "frameId": {
1671 //       "type": "integer",
1672 //       "description": "Retrieve the scopes for this stackframe."
1673 //     }
1674 //   },
1675 //   "required": [ "frameId" ]
1676 // },
1677 // "ScopesResponse": {
1678 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1679 //     "type": "object",
1680 //     "description": "Response to 'scopes' request.",
1681 //     "properties": {
1682 //       "body": {
1683 //         "type": "object",
1684 //         "properties": {
1685 //           "scopes": {
1686 //             "type": "array",
1687 //             "items": {
1688 //               "$ref": "#/definitions/Scope"
1689 //             },
1690 //             "description": "The scopes of the stackframe. If the array has
1691 //             length zero, there are no scopes available."
1692 //           }
1693 //         },
1694 //         "required": [ "scopes" ]
1695 //       }
1696 //     },
1697 //     "required": [ "body" ]
1698 //   }]
1699 // }
1700 void request_scopes(const llvm::json::Object &request) {
1701   llvm::json::Object response;
1702   FillResponse(request, response);
1703   llvm::json::Object body;
1704   auto arguments = request.getObject("arguments");
1705   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
1706   // As the user selects different stack frames in the GUI, a "scopes" request
1707   // will be sent to the DAP. This is the only way we know that the user has
1708   // selected a frame in a thread. There are no other notifications that are
1709   // sent and VS code doesn't allow multiple frames to show variables
1710   // concurrently. If we select the thread and frame as the "scopes" requests
1711   // are sent, this allows users to type commands in the debugger console
1712   // with a backtick character to run lldb commands and these lldb commands
1713   // will now have the right context selected as they are run. If the user
1714   // types "`bt" into the debugger console and we had another thread selected
1715   // in the LLDB library, we would show the wrong thing to the user. If the
1716   // users switches threads with a lldb command like "`thread select 14", the
1717   // GUI will not update as there are no "event" notification packets that
1718   // allow us to change the currently selected thread or frame in the GUI that
1719   // I am aware of.
1720   if (frame.IsValid()) {
1721     frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
1722     frame.GetThread().SetSelectedFrame(frame.GetFrameID());
1723   }
1724   g_vsc.variables.Clear();
1725   g_vsc.variables.Append(frame.GetVariables(true,   // arguments
1726                                             true,   // locals
1727                                             false,  // statics
1728                                             true)); // in_scope_only
1729   g_vsc.num_locals = g_vsc.variables.GetSize();
1730   g_vsc.variables.Append(frame.GetVariables(false,  // arguments
1731                                             false,  // locals
1732                                             true,   // statics
1733                                             true)); // in_scope_only
1734   g_vsc.num_globals = g_vsc.variables.GetSize() - (g_vsc.num_locals);
1735   g_vsc.variables.Append(frame.GetRegisters());
1736   g_vsc.num_regs =
1737       g_vsc.variables.GetSize() - (g_vsc.num_locals + g_vsc.num_globals);
1738   body.try_emplace("scopes", g_vsc.CreateTopLevelScopes());
1739   response.try_emplace("body", std::move(body));
1740   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1741 }
1742 
1743 // "SetBreakpointsRequest": {
1744 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1745 //     "type": "object",
1746 //     "description": "SetBreakpoints request; value of command field is
1747 //     'setBreakpoints'. Sets multiple breakpoints for a single source and
1748 //     clears all previous breakpoints in that source. To clear all breakpoint
1749 //     for a source, specify an empty array. When a breakpoint is hit, a
1750 //     StoppedEvent (event type 'breakpoint') is generated.", "properties": {
1751 //       "command": {
1752 //         "type": "string",
1753 //         "enum": [ "setBreakpoints" ]
1754 //       },
1755 //       "arguments": {
1756 //         "$ref": "#/definitions/SetBreakpointsArguments"
1757 //       }
1758 //     },
1759 //     "required": [ "command", "arguments"  ]
1760 //   }]
1761 // },
1762 // "SetBreakpointsArguments": {
1763 //   "type": "object",
1764 //   "description": "Arguments for 'setBreakpoints' request.",
1765 //   "properties": {
1766 //     "source": {
1767 //       "$ref": "#/definitions/Source",
1768 //       "description": "The source location of the breakpoints; either
1769 //       source.path or source.reference must be specified."
1770 //     },
1771 //     "breakpoints": {
1772 //       "type": "array",
1773 //       "items": {
1774 //         "$ref": "#/definitions/SourceBreakpoint"
1775 //       },
1776 //       "description": "The code locations of the breakpoints."
1777 //     },
1778 //     "lines": {
1779 //       "type": "array",
1780 //       "items": {
1781 //         "type": "integer"
1782 //       },
1783 //       "description": "Deprecated: The code locations of the breakpoints."
1784 //     },
1785 //     "sourceModified": {
1786 //       "type": "boolean",
1787 //       "description": "A value of true indicates that the underlying source
1788 //       has been modified which results in new breakpoint locations."
1789 //     }
1790 //   },
1791 //   "required": [ "source" ]
1792 // },
1793 // "SetBreakpointsResponse": {
1794 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1795 //     "type": "object",
1796 //     "description": "Response to 'setBreakpoints' request. Returned is
1797 //     information about each breakpoint created by this request. This includes
1798 //     the actual code location and whether the breakpoint could be verified.
1799 //     The breakpoints returned are in the same order as the elements of the
1800 //     'breakpoints' (or the deprecated 'lines') in the
1801 //     SetBreakpointsArguments.", "properties": {
1802 //       "body": {
1803 //         "type": "object",
1804 //         "properties": {
1805 //           "breakpoints": {
1806 //             "type": "array",
1807 //             "items": {
1808 //               "$ref": "#/definitions/Breakpoint"
1809 //             },
1810 //             "description": "Information about the breakpoints. The array
1811 //             elements are in the same order as the elements of the
1812 //             'breakpoints' (or the deprecated 'lines') in the
1813 //             SetBreakpointsArguments."
1814 //           }
1815 //         },
1816 //         "required": [ "breakpoints" ]
1817 //       }
1818 //     },
1819 //     "required": [ "body" ]
1820 //   }]
1821 // },
1822 // "SourceBreakpoint": {
1823 //   "type": "object",
1824 //   "description": "Properties of a breakpoint or logpoint passed to the
1825 //   setBreakpoints request.", "properties": {
1826 //     "line": {
1827 //       "type": "integer",
1828 //       "description": "The source line of the breakpoint or logpoint."
1829 //     },
1830 //     "column": {
1831 //       "type": "integer",
1832 //       "description": "An optional source column of the breakpoint."
1833 //     },
1834 //     "condition": {
1835 //       "type": "string",
1836 //       "description": "An optional expression for conditional breakpoints."
1837 //     },
1838 //     "hitCondition": {
1839 //       "type": "string",
1840 //       "description": "An optional expression that controls how many hits of
1841 //       the breakpoint are ignored. The backend is expected to interpret the
1842 //       expression as needed."
1843 //     },
1844 //     "logMessage": {
1845 //       "type": "string",
1846 //       "description": "If this attribute exists and is non-empty, the backend
1847 //       must not 'break' (stop) but log the message instead. Expressions within
1848 //       {} are interpolated."
1849 //     }
1850 //   },
1851 //   "required": [ "line" ]
1852 // }
1853 void request_setBreakpoints(const llvm::json::Object &request) {
1854   llvm::json::Object response;
1855   lldb::SBError error;
1856   FillResponse(request, response);
1857   auto arguments = request.getObject("arguments");
1858   auto source = arguments->getObject("source");
1859   const auto path = GetString(source, "path");
1860   auto breakpoints = arguments->getArray("breakpoints");
1861   llvm::json::Array response_breakpoints;
1862 
1863   // Decode the source breakpoint infos for this "setBreakpoints" request
1864   SourceBreakpointMap request_bps;
1865   for (const auto &bp : *breakpoints) {
1866     auto bp_obj = bp.getAsObject();
1867     if (bp_obj) {
1868       SourceBreakpoint src_bp(*bp_obj);
1869       request_bps[src_bp.line] = src_bp;
1870 
1871       // We check if this breakpoint already exists to update it
1872       auto existing_source_bps = g_vsc.source_breakpoints.find(path);
1873       if (existing_source_bps != g_vsc.source_breakpoints.end()) {
1874         const auto &existing_bp = existing_source_bps->second.find(src_bp.line);
1875         if (existing_bp != existing_source_bps->second.end()) {
1876           existing_bp->second.UpdateBreakpoint(src_bp);
1877           AppendBreakpoint(existing_bp->second.bp, response_breakpoints, path,
1878                            src_bp.line);
1879           continue;
1880         }
1881       }
1882       // At this point the breakpoint is new
1883       src_bp.SetBreakpoint(path.data());
1884       AppendBreakpoint(src_bp.bp, response_breakpoints, path, src_bp.line);
1885       g_vsc.source_breakpoints[path][src_bp.line] = std::move(src_bp);
1886     }
1887   }
1888 
1889   // Delete any breakpoints in this source file that aren't in the
1890   // request_bps set. There is no call to remove breakpoints other than
1891   // calling this function with a smaller or empty "breakpoints" list.
1892   auto old_src_bp_pos = g_vsc.source_breakpoints.find(path);
1893   if (old_src_bp_pos != g_vsc.source_breakpoints.end()) {
1894     for (auto &old_bp : old_src_bp_pos->second) {
1895       auto request_pos = request_bps.find(old_bp.first);
1896       if (request_pos == request_bps.end()) {
1897         // This breakpoint no longer exists in this source file, delete it
1898         g_vsc.target.BreakpointDelete(old_bp.second.bp.GetID());
1899         old_src_bp_pos->second.erase(old_bp.first);
1900       }
1901     }
1902   }
1903 
1904   llvm::json::Object body;
1905   body.try_emplace("breakpoints", std::move(response_breakpoints));
1906   response.try_emplace("body", std::move(body));
1907   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1908 }
1909 
1910 // "SetExceptionBreakpointsRequest": {
1911 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1912 //     "type": "object",
1913 //     "description": "SetExceptionBreakpoints request; value of command field
1914 //     is 'setExceptionBreakpoints'. The request configures the debuggers
1915 //     response to thrown exceptions. If an exception is configured to break, a
1916 //     StoppedEvent is fired (event type 'exception').", "properties": {
1917 //       "command": {
1918 //         "type": "string",
1919 //         "enum": [ "setExceptionBreakpoints" ]
1920 //       },
1921 //       "arguments": {
1922 //         "$ref": "#/definitions/SetExceptionBreakpointsArguments"
1923 //       }
1924 //     },
1925 //     "required": [ "command", "arguments"  ]
1926 //   }]
1927 // },
1928 // "SetExceptionBreakpointsArguments": {
1929 //   "type": "object",
1930 //   "description": "Arguments for 'setExceptionBreakpoints' request.",
1931 //   "properties": {
1932 //     "filters": {
1933 //       "type": "array",
1934 //       "items": {
1935 //         "type": "string"
1936 //       },
1937 //       "description": "IDs of checked exception options. The set of IDs is
1938 //       returned via the 'exceptionBreakpointFilters' capability."
1939 //     },
1940 //     "exceptionOptions": {
1941 //       "type": "array",
1942 //       "items": {
1943 //         "$ref": "#/definitions/ExceptionOptions"
1944 //       },
1945 //       "description": "Configuration options for selected exceptions."
1946 //     }
1947 //   },
1948 //   "required": [ "filters" ]
1949 // },
1950 // "SetExceptionBreakpointsResponse": {
1951 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1952 //     "type": "object",
1953 //     "description": "Response to 'setExceptionBreakpoints' request. This is
1954 //     just an acknowledgement, so no body field is required."
1955 //   }]
1956 // }
1957 void request_setExceptionBreakpoints(const llvm::json::Object &request) {
1958   llvm::json::Object response;
1959   lldb::SBError error;
1960   FillResponse(request, response);
1961   auto arguments = request.getObject("arguments");
1962   auto filters = arguments->getArray("filters");
1963   // Keep a list of any exception breakpoint filter names that weren't set
1964   // so we can clear any exception breakpoints if needed.
1965   std::set<std::string> unset_filters;
1966   for (const auto &bp : g_vsc.exception_breakpoints)
1967     unset_filters.insert(bp.filter);
1968 
1969   for (const auto &value : *filters) {
1970     const auto filter = GetAsString(value);
1971     auto exc_bp = g_vsc.GetExceptionBreakpoint(std::string(filter));
1972     if (exc_bp) {
1973       exc_bp->SetBreakpoint();
1974       unset_filters.erase(std::string(filter));
1975     }
1976   }
1977   for (const auto &filter : unset_filters) {
1978     auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
1979     if (exc_bp)
1980       exc_bp->ClearBreakpoint();
1981   }
1982   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1983 }
1984 
1985 // "SetFunctionBreakpointsRequest": {
1986 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1987 //     "type": "object",
1988 //     "description": "SetFunctionBreakpoints request; value of command field is
1989 //     'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
1990 //     all previous function breakpoints. To clear all function breakpoint,
1991 //     specify an empty array. When a function breakpoint is hit, a StoppedEvent
1992 //     (event type 'function breakpoint') is generated.", "properties": {
1993 //       "command": {
1994 //         "type": "string",
1995 //         "enum": [ "setFunctionBreakpoints" ]
1996 //       },
1997 //       "arguments": {
1998 //         "$ref": "#/definitions/SetFunctionBreakpointsArguments"
1999 //       }
2000 //     },
2001 //     "required": [ "command", "arguments"  ]
2002 //   }]
2003 // },
2004 // "SetFunctionBreakpointsArguments": {
2005 //   "type": "object",
2006 //   "description": "Arguments for 'setFunctionBreakpoints' request.",
2007 //   "properties": {
2008 //     "breakpoints": {
2009 //       "type": "array",
2010 //       "items": {
2011 //         "$ref": "#/definitions/FunctionBreakpoint"
2012 //       },
2013 //       "description": "The function names of the breakpoints."
2014 //     }
2015 //   },
2016 //   "required": [ "breakpoints" ]
2017 // },
2018 // "FunctionBreakpoint": {
2019 //   "type": "object",
2020 //   "description": "Properties of a breakpoint passed to the
2021 //   setFunctionBreakpoints request.", "properties": {
2022 //     "name": {
2023 //       "type": "string",
2024 //       "description": "The name of the function."
2025 //     },
2026 //     "condition": {
2027 //       "type": "string",
2028 //       "description": "An optional expression for conditional breakpoints."
2029 //     },
2030 //     "hitCondition": {
2031 //       "type": "string",
2032 //       "description": "An optional expression that controls how many hits of
2033 //       the breakpoint are ignored. The backend is expected to interpret the
2034 //       expression as needed."
2035 //     }
2036 //   },
2037 //   "required": [ "name" ]
2038 // },
2039 // "SetFunctionBreakpointsResponse": {
2040 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2041 //     "type": "object",
2042 //     "description": "Response to 'setFunctionBreakpoints' request. Returned is
2043 //     information about each breakpoint created by this request.",
2044 //     "properties": {
2045 //       "body": {
2046 //         "type": "object",
2047 //         "properties": {
2048 //           "breakpoints": {
2049 //             "type": "array",
2050 //             "items": {
2051 //               "$ref": "#/definitions/Breakpoint"
2052 //             },
2053 //             "description": "Information about the breakpoints. The array
2054 //             elements correspond to the elements of the 'breakpoints' array."
2055 //           }
2056 //         },
2057 //         "required": [ "breakpoints" ]
2058 //       }
2059 //     },
2060 //     "required": [ "body" ]
2061 //   }]
2062 // }
2063 void request_setFunctionBreakpoints(const llvm::json::Object &request) {
2064   llvm::json::Object response;
2065   lldb::SBError error;
2066   FillResponse(request, response);
2067   auto arguments = request.getObject("arguments");
2068   auto breakpoints = arguments->getArray("breakpoints");
2069   FunctionBreakpointMap request_bps;
2070   llvm::json::Array response_breakpoints;
2071   for (const auto &value : *breakpoints) {
2072     auto bp_obj = value.getAsObject();
2073     if (bp_obj == nullptr)
2074       continue;
2075     FunctionBreakpoint func_bp(*bp_obj);
2076     request_bps[func_bp.functionName] = std::move(func_bp);
2077   }
2078 
2079   std::vector<llvm::StringRef> remove_names;
2080   // Disable any function breakpoints that aren't in the request_bps.
2081   // There is no call to remove function breakpoints other than calling this
2082   // function with a smaller or empty "breakpoints" list.
2083   for (auto &pair: g_vsc.function_breakpoints) {
2084     auto request_pos = request_bps.find(pair.first());
2085     if (request_pos == request_bps.end()) {
2086       // This function breakpoint no longer exists delete it from LLDB
2087       g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
2088       remove_names.push_back(pair.first());
2089     } else {
2090       // Update the existing breakpoint as any setting withing the function
2091       // breakpoint might have changed.
2092       pair.second.UpdateBreakpoint(request_pos->second);
2093       // Remove this breakpoint from the request breakpoints since we have
2094       // handled it here and we don't need to set a new breakpoint below.
2095       request_bps.erase(request_pos);
2096       // Add this breakpoint info to the response
2097       AppendBreakpoint(pair.second.bp, response_breakpoints);
2098     }
2099   }
2100   // Remove any breakpoints that are no longer in our list
2101   for (const auto &name: remove_names)
2102     g_vsc.function_breakpoints.erase(name);
2103 
2104   // Any breakpoints that are left in "request_bps" are breakpoints that
2105   // need to be set.
2106   for (auto &pair : request_bps) {
2107     pair.second.SetBreakpoint();
2108     // Add this breakpoint info to the response
2109     AppendBreakpoint(pair.second.bp, response_breakpoints);
2110     g_vsc.function_breakpoints[pair.first()] = std::move(pair.second);
2111   }
2112 
2113   llvm::json::Object body;
2114   body.try_emplace("breakpoints", std::move(response_breakpoints));
2115   response.try_emplace("body", std::move(body));
2116   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2117 }
2118 
2119 // "SourceRequest": {
2120 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2121 //     "type": "object",
2122 //     "description": "Source request; value of command field is 'source'. The
2123 //     request retrieves the source code for a given source reference.",
2124 //     "properties": {
2125 //       "command": {
2126 //         "type": "string",
2127 //         "enum": [ "source" ]
2128 //       },
2129 //       "arguments": {
2130 //         "$ref": "#/definitions/SourceArguments"
2131 //       }
2132 //     },
2133 //     "required": [ "command", "arguments"  ]
2134 //   }]
2135 // },
2136 // "SourceArguments": {
2137 //   "type": "object",
2138 //   "description": "Arguments for 'source' request.",
2139 //   "properties": {
2140 //     "source": {
2141 //       "$ref": "#/definitions/Source",
2142 //       "description": "Specifies the source content to load. Either
2143 //       source.path or source.sourceReference must be specified."
2144 //     },
2145 //     "sourceReference": {
2146 //       "type": "integer",
2147 //       "description": "The reference to the source. This is the same as
2148 //       source.sourceReference. This is provided for backward compatibility
2149 //       since old backends do not understand the 'source' attribute."
2150 //     }
2151 //   },
2152 //   "required": [ "sourceReference" ]
2153 // },
2154 // "SourceResponse": {
2155 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2156 //     "type": "object",
2157 //     "description": "Response to 'source' request.",
2158 //     "properties": {
2159 //       "body": {
2160 //         "type": "object",
2161 //         "properties": {
2162 //           "content": {
2163 //             "type": "string",
2164 //             "description": "Content of the source reference."
2165 //           },
2166 //           "mimeType": {
2167 //             "type": "string",
2168 //             "description": "Optional content type (mime type) of the source."
2169 //           }
2170 //         },
2171 //         "required": [ "content" ]
2172 //       }
2173 //     },
2174 //     "required": [ "body" ]
2175 //   }]
2176 // }
2177 void request_source(const llvm::json::Object &request) {
2178   llvm::json::Object response;
2179   FillResponse(request, response);
2180   llvm::json::Object body;
2181 
2182   auto arguments = request.getObject("arguments");
2183   auto source = arguments->getObject("source");
2184   auto sourceReference = GetSigned(source, "sourceReference", -1);
2185   auto pos = g_vsc.source_map.find((lldb::addr_t)sourceReference);
2186   if (pos != g_vsc.source_map.end()) {
2187     EmplaceSafeString(body, "content", pos->second.content);
2188   } else {
2189     response["success"] = llvm::json::Value(false);
2190   }
2191   response.try_emplace("body", std::move(body));
2192   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2193 }
2194 
2195 // "StackTraceRequest": {
2196 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2197 //     "type": "object",
2198 //     "description": "StackTrace request; value of command field is
2199 //     'stackTrace'. The request returns a stacktrace from the current execution
2200 //     state.", "properties": {
2201 //       "command": {
2202 //         "type": "string",
2203 //         "enum": [ "stackTrace" ]
2204 //       },
2205 //       "arguments": {
2206 //         "$ref": "#/definitions/StackTraceArguments"
2207 //       }
2208 //     },
2209 //     "required": [ "command", "arguments"  ]
2210 //   }]
2211 // },
2212 // "StackTraceArguments": {
2213 //   "type": "object",
2214 //   "description": "Arguments for 'stackTrace' request.",
2215 //   "properties": {
2216 //     "threadId": {
2217 //       "type": "integer",
2218 //       "description": "Retrieve the stacktrace for this thread."
2219 //     },
2220 //     "startFrame": {
2221 //       "type": "integer",
2222 //       "description": "The index of the first frame to return; if omitted
2223 //       frames start at 0."
2224 //     },
2225 //     "levels": {
2226 //       "type": "integer",
2227 //       "description": "The maximum number of frames to return. If levels is
2228 //       not specified or 0, all frames are returned."
2229 //     },
2230 //     "format": {
2231 //       "$ref": "#/definitions/StackFrameFormat",
2232 //       "description": "Specifies details on how to format the stack frames."
2233 //     }
2234 //  },
2235 //   "required": [ "threadId" ]
2236 // },
2237 // "StackTraceResponse": {
2238 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2239 //     "type": "object",
2240 //     "description": "Response to 'stackTrace' request.",
2241 //     "properties": {
2242 //       "body": {
2243 //         "type": "object",
2244 //         "properties": {
2245 //           "stackFrames": {
2246 //             "type": "array",
2247 //             "items": {
2248 //               "$ref": "#/definitions/StackFrame"
2249 //             },
2250 //             "description": "The frames of the stackframe. If the array has
2251 //             length zero, there are no stackframes available. This means that
2252 //             there is no location information available."
2253 //           },
2254 //           "totalFrames": {
2255 //             "type": "integer",
2256 //             "description": "The total number of frames available."
2257 //           }
2258 //         },
2259 //         "required": [ "stackFrames" ]
2260 //       }
2261 //     },
2262 //     "required": [ "body" ]
2263 //   }]
2264 // }
2265 void request_stackTrace(const llvm::json::Object &request) {
2266   llvm::json::Object response;
2267   FillResponse(request, response);
2268   lldb::SBError error;
2269   auto arguments = request.getObject("arguments");
2270   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2271   llvm::json::Array stackFrames;
2272   llvm::json::Object body;
2273 
2274   if (thread.IsValid()) {
2275     const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
2276     const auto levels = GetUnsigned(arguments, "levels", 0);
2277     const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
2278     for (uint32_t i = startFrame; i < endFrame; ++i) {
2279       auto frame = thread.GetFrameAtIndex(i);
2280       if (!frame.IsValid())
2281         break;
2282       stackFrames.emplace_back(CreateStackFrame(frame));
2283     }
2284     const auto totalFrames = thread.GetNumFrames();
2285     body.try_emplace("totalFrames", totalFrames);
2286   }
2287   body.try_emplace("stackFrames", std::move(stackFrames));
2288   response.try_emplace("body", std::move(body));
2289   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2290 }
2291 
2292 // "StepInRequest": {
2293 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2294 //     "type": "object",
2295 //     "description": "StepIn request; value of command field is 'stepIn'. The
2296 //     request starts the debuggee to step into a function/method if possible.
2297 //     If it cannot step into a target, 'stepIn' behaves like 'next'. The debug
2298 //     adapter first sends the StepInResponse and then a StoppedEvent (event
2299 //     type 'step') after the step has completed. If there are multiple
2300 //     function/method calls (or other targets) on the source line, the optional
2301 //     argument 'targetId' can be used to control into which target the 'stepIn'
2302 //     should occur. The list of possible targets for a given source line can be
2303 //     retrieved via the 'stepInTargets' request.", "properties": {
2304 //       "command": {
2305 //         "type": "string",
2306 //         "enum": [ "stepIn" ]
2307 //       },
2308 //       "arguments": {
2309 //         "$ref": "#/definitions/StepInArguments"
2310 //       }
2311 //     },
2312 //     "required": [ "command", "arguments"  ]
2313 //   }]
2314 // },
2315 // "StepInArguments": {
2316 //   "type": "object",
2317 //   "description": "Arguments for 'stepIn' request.",
2318 //   "properties": {
2319 //     "threadId": {
2320 //       "type": "integer",
2321 //       "description": "Execute 'stepIn' for this thread."
2322 //     },
2323 //     "targetId": {
2324 //       "type": "integer",
2325 //       "description": "Optional id of the target to step into."
2326 //     }
2327 //   },
2328 //   "required": [ "threadId" ]
2329 // },
2330 // "StepInResponse": {
2331 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2332 //     "type": "object",
2333 //     "description": "Response to 'stepIn' request. This is just an
2334 //     acknowledgement, so no body field is required."
2335 //   }]
2336 // }
2337 void request_stepIn(const llvm::json::Object &request) {
2338   llvm::json::Object response;
2339   FillResponse(request, response);
2340   auto arguments = request.getObject("arguments");
2341   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2342   if (thread.IsValid()) {
2343     // Remember the thread ID that caused the resume so we can set the
2344     // "threadCausedFocus" boolean value in the "stopped" events.
2345     g_vsc.focus_tid = thread.GetThreadID();
2346     thread.StepInto();
2347   } else {
2348     response["success"] = llvm::json::Value(false);
2349   }
2350   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2351 }
2352 
2353 // "StepOutRequest": {
2354 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2355 //     "type": "object",
2356 //     "description": "StepOut request; value of command field is 'stepOut'. The
2357 //     request starts the debuggee to run again for one step. The debug adapter
2358 //     first sends the StepOutResponse and then a StoppedEvent (event type
2359 //     'step') after the step has completed.", "properties": {
2360 //       "command": {
2361 //         "type": "string",
2362 //         "enum": [ "stepOut" ]
2363 //       },
2364 //       "arguments": {
2365 //         "$ref": "#/definitions/StepOutArguments"
2366 //       }
2367 //     },
2368 //     "required": [ "command", "arguments"  ]
2369 //   }]
2370 // },
2371 // "StepOutArguments": {
2372 //   "type": "object",
2373 //   "description": "Arguments for 'stepOut' request.",
2374 //   "properties": {
2375 //     "threadId": {
2376 //       "type": "integer",
2377 //       "description": "Execute 'stepOut' for this thread."
2378 //     }
2379 //   },
2380 //   "required": [ "threadId" ]
2381 // },
2382 // "StepOutResponse": {
2383 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2384 //     "type": "object",
2385 //     "description": "Response to 'stepOut' request. This is just an
2386 //     acknowledgement, so no body field is required."
2387 //   }]
2388 // }
2389 void request_stepOut(const llvm::json::Object &request) {
2390   llvm::json::Object response;
2391   FillResponse(request, response);
2392   auto arguments = request.getObject("arguments");
2393   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2394   if (thread.IsValid()) {
2395     // Remember the thread ID that caused the resume so we can set the
2396     // "threadCausedFocus" boolean value in the "stopped" events.
2397     g_vsc.focus_tid = thread.GetThreadID();
2398     thread.StepOut();
2399   } else {
2400     response["success"] = llvm::json::Value(false);
2401   }
2402   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2403 }
2404 
2405 // "ThreadsRequest": {
2406 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2407 //     "type": "object",
2408 //     "description": "Thread request; value of command field is 'threads'. The
2409 //     request retrieves a list of all threads.", "properties": {
2410 //       "command": {
2411 //         "type": "string",
2412 //         "enum": [ "threads" ]
2413 //       }
2414 //     },
2415 //     "required": [ "command" ]
2416 //   }]
2417 // },
2418 // "ThreadsResponse": {
2419 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2420 //     "type": "object",
2421 //     "description": "Response to 'threads' request.",
2422 //     "properties": {
2423 //       "body": {
2424 //         "type": "object",
2425 //         "properties": {
2426 //           "threads": {
2427 //             "type": "array",
2428 //             "items": {
2429 //               "$ref": "#/definitions/Thread"
2430 //             },
2431 //             "description": "All threads."
2432 //           }
2433 //         },
2434 //         "required": [ "threads" ]
2435 //       }
2436 //     },
2437 //     "required": [ "body" ]
2438 //   }]
2439 // }
2440 void request_threads(const llvm::json::Object &request) {
2441 
2442   lldb::SBProcess process = g_vsc.target.GetProcess();
2443   llvm::json::Object response;
2444   FillResponse(request, response);
2445 
2446   const uint32_t num_threads = process.GetNumThreads();
2447   llvm::json::Array threads;
2448   for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
2449     lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
2450     threads.emplace_back(CreateThread(thread));
2451   }
2452   if (threads.size() == 0) {
2453     response["success"] = llvm::json::Value(false);
2454   }
2455   llvm::json::Object body;
2456   body.try_emplace("threads", std::move(threads));
2457   response.try_emplace("body", std::move(body));
2458   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2459 }
2460 
2461 // "SetVariableRequest": {
2462 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2463 //     "type": "object",
2464 //     "description": "setVariable request; value of command field is
2465 //     'setVariable'. Set the variable with the given name in the variable
2466 //     container to a new value.", "properties": {
2467 //       "command": {
2468 //         "type": "string",
2469 //         "enum": [ "setVariable" ]
2470 //       },
2471 //       "arguments": {
2472 //         "$ref": "#/definitions/SetVariableArguments"
2473 //       }
2474 //     },
2475 //     "required": [ "command", "arguments"  ]
2476 //   }]
2477 // },
2478 // "SetVariableArguments": {
2479 //   "type": "object",
2480 //   "description": "Arguments for 'setVariable' request.",
2481 //   "properties": {
2482 //     "variablesReference": {
2483 //       "type": "integer",
2484 //       "description": "The reference of the variable container."
2485 //     },
2486 //     "name": {
2487 //       "type": "string",
2488 //       "description": "The name of the variable."
2489 //     },
2490 //     "value": {
2491 //       "type": "string",
2492 //       "description": "The value of the variable."
2493 //     },
2494 //     "format": {
2495 //       "$ref": "#/definitions/ValueFormat",
2496 //       "description": "Specifies details on how to format the response value."
2497 //     }
2498 //   },
2499 //   "required": [ "variablesReference", "name", "value" ]
2500 // },
2501 // "SetVariableResponse": {
2502 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2503 //     "type": "object",
2504 //     "description": "Response to 'setVariable' request.",
2505 //     "properties": {
2506 //       "body": {
2507 //         "type": "object",
2508 //         "properties": {
2509 //           "value": {
2510 //             "type": "string",
2511 //             "description": "The new value of the variable."
2512 //           },
2513 //           "type": {
2514 //             "type": "string",
2515 //             "description": "The type of the new value. Typically shown in the
2516 //             UI when hovering over the value."
2517 //           },
2518 //           "variablesReference": {
2519 //             "type": "number",
2520 //             "description": "If variablesReference is > 0, the new value is
2521 //             structured and its children can be retrieved by passing
2522 //             variablesReference to the VariablesRequest."
2523 //           },
2524 //           "namedVariables": {
2525 //             "type": "number",
2526 //             "description": "The number of named child variables. The client
2527 //             can use this optional information to present the variables in a
2528 //             paged UI and fetch them in chunks."
2529 //           },
2530 //           "indexedVariables": {
2531 //             "type": "number",
2532 //             "description": "The number of indexed child variables. The client
2533 //             can use this optional information to present the variables in a
2534 //             paged UI and fetch them in chunks."
2535 //           }
2536 //         },
2537 //         "required": [ "value" ]
2538 //       }
2539 //     },
2540 //     "required": [ "body" ]
2541 //   }]
2542 // }
2543 void request_setVariable(const llvm::json::Object &request) {
2544   llvm::json::Object response;
2545   FillResponse(request, response);
2546   llvm::json::Array variables;
2547   llvm::json::Object body;
2548   auto arguments = request.getObject("arguments");
2549   // This is a reference to the containing variable/scope
2550   const auto variablesReference =
2551       GetUnsigned(arguments, "variablesReference", 0);
2552   const auto name = GetString(arguments, "name");
2553   const auto value = GetString(arguments, "value");
2554   // Set success to false just in case we don't find the variable by name
2555   response.try_emplace("success", false);
2556 
2557   lldb::SBValue variable;
2558   int64_t newVariablesReference = 0;
2559 
2560   // The "id" is the unique integer ID that is unique within the enclosing
2561   // variablesReference. It is optionally added to any "interface Variable"
2562   // objects to uniquely identify a variable within an enclosing
2563   // variablesReference. It helps to disambiguate between two variables that
2564   // have the same name within the same scope since the "setVariables" request
2565   // only specifies the variable reference of the enclosing scope/variable, and
2566   // the name of the variable. We could have two shadowed variables with the
2567   // same name in "Locals" or "Globals". In our case the "id" absolute index
2568   // of the variable within the g_vsc.variables list.
2569   const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
2570   if (id_value != UINT64_MAX) {
2571     variable = g_vsc.variables.GetValueAtIndex(id_value);
2572   } else if (VARREF_IS_SCOPE(variablesReference)) {
2573     // variablesReference is one of our scopes, not an actual variable it is
2574     // asking for a variable in locals or globals or registers
2575     int64_t start_idx = 0;
2576     int64_t end_idx = 0;
2577     switch (variablesReference) {
2578     case VARREF_LOCALS:
2579       start_idx = 0;
2580       end_idx = start_idx + g_vsc.num_locals;
2581       break;
2582     case VARREF_GLOBALS:
2583       start_idx = g_vsc.num_locals;
2584       end_idx = start_idx + g_vsc.num_globals;
2585       break;
2586     case VARREF_REGS:
2587       start_idx = g_vsc.num_locals + g_vsc.num_globals;
2588       end_idx = start_idx + g_vsc.num_regs;
2589       break;
2590     default:
2591       break;
2592     }
2593 
2594     // Find the variable by name in the correct scope and hope we don't have
2595     // multiple variables with the same name. We search backwards because
2596     // the list of variables has the top most variables first and variables
2597     // in deeper scopes are last. This means we will catch the deepest
2598     // variable whose name matches which is probably what the user wants.
2599     for (int64_t i = end_idx - 1; i >= start_idx; --i) {
2600       auto curr_variable = g_vsc.variables.GetValueAtIndex(i);
2601       llvm::StringRef variable_name(curr_variable.GetName());
2602       if (variable_name == name) {
2603         variable = curr_variable;
2604         if (curr_variable.MightHaveChildren())
2605           newVariablesReference = i;
2606         break;
2607       }
2608     }
2609   } else {
2610     // We have a named item within an actual variable so we need to find it
2611     // withing the container variable by name.
2612     const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
2613     lldb::SBValue container = g_vsc.variables.GetValueAtIndex(var_idx);
2614     variable = container.GetChildMemberWithName(name.data());
2615     if (!variable.IsValid()) {
2616       if (name.startswith("[")) {
2617         llvm::StringRef index_str(name.drop_front(1));
2618         uint64_t index = 0;
2619         if (!index_str.consumeInteger(0, index)) {
2620           if (index_str == "]")
2621             variable = container.GetChildAtIndex(index);
2622         }
2623       }
2624     }
2625 
2626     // We don't know the index of the variable in our g_vsc.variables
2627     if (variable.IsValid()) {
2628       if (variable.MightHaveChildren()) {
2629         newVariablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
2630         g_vsc.variables.Append(variable);
2631       }
2632     }
2633   }
2634 
2635   if (variable.IsValid()) {
2636     lldb::SBError error;
2637     bool success = variable.SetValueFromCString(value.data(), error);
2638     if (success) {
2639       SetValueForKey(variable, body, "value");
2640       EmplaceSafeString(body, "type", variable.GetType().GetDisplayTypeName());
2641       body.try_emplace("variablesReference", newVariablesReference);
2642     } else {
2643       EmplaceSafeString(body, "message", std::string(error.GetCString()));
2644     }
2645     response["success"] = llvm::json::Value(success);
2646   }
2647 
2648   response.try_emplace("body", std::move(body));
2649   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2650 }
2651 
2652 // "VariablesRequest": {
2653 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2654 //     "type": "object",
2655 //     "description": "Variables request; value of command field is 'variables'.
2656 //     Retrieves all child variables for the given variable reference. An
2657 //     optional filter can be used to limit the fetched children to either named
2658 //     or indexed children.", "properties": {
2659 //       "command": {
2660 //         "type": "string",
2661 //         "enum": [ "variables" ]
2662 //       },
2663 //       "arguments": {
2664 //         "$ref": "#/definitions/VariablesArguments"
2665 //       }
2666 //     },
2667 //     "required": [ "command", "arguments"  ]
2668 //   }]
2669 // },
2670 // "VariablesArguments": {
2671 //   "type": "object",
2672 //   "description": "Arguments for 'variables' request.",
2673 //   "properties": {
2674 //     "variablesReference": {
2675 //       "type": "integer",
2676 //       "description": "The Variable reference."
2677 //     },
2678 //     "filter": {
2679 //       "type": "string",
2680 //       "enum": [ "indexed", "named" ],
2681 //       "description": "Optional filter to limit the child variables to either
2682 //       named or indexed. If ommited, both types are fetched."
2683 //     },
2684 //     "start": {
2685 //       "type": "integer",
2686 //       "description": "The index of the first variable to return; if omitted
2687 //       children start at 0."
2688 //     },
2689 //     "count": {
2690 //       "type": "integer",
2691 //       "description": "The number of variables to return. If count is missing
2692 //       or 0, all variables are returned."
2693 //     },
2694 //     "format": {
2695 //       "$ref": "#/definitions/ValueFormat",
2696 //       "description": "Specifies details on how to format the Variable
2697 //       values."
2698 //     }
2699 //   },
2700 //   "required": [ "variablesReference" ]
2701 // },
2702 // "VariablesResponse": {
2703 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2704 //     "type": "object",
2705 //     "description": "Response to 'variables' request.",
2706 //     "properties": {
2707 //       "body": {
2708 //         "type": "object",
2709 //         "properties": {
2710 //           "variables": {
2711 //             "type": "array",
2712 //             "items": {
2713 //               "$ref": "#/definitions/Variable"
2714 //             },
2715 //             "description": "All (or a range) of variables for the given
2716 //             variable reference."
2717 //           }
2718 //         },
2719 //         "required": [ "variables" ]
2720 //       }
2721 //     },
2722 //     "required": [ "body" ]
2723 //   }]
2724 // }
2725 void request_variables(const llvm::json::Object &request) {
2726   llvm::json::Object response;
2727   FillResponse(request, response);
2728   llvm::json::Array variables;
2729   auto arguments = request.getObject("arguments");
2730   const auto variablesReference =
2731       GetUnsigned(arguments, "variablesReference", 0);
2732   const int64_t start = GetSigned(arguments, "start", 0);
2733   const int64_t count = GetSigned(arguments, "count", 0);
2734   bool hex = false;
2735   auto format = arguments->getObject("format");
2736   if (format)
2737     hex = GetBoolean(format, "hex", false);
2738 
2739   if (VARREF_IS_SCOPE(variablesReference)) {
2740     // variablesReference is one of our scopes, not an actual variable it is
2741     // asking for the list of args, locals or globals.
2742     int64_t start_idx = 0;
2743     int64_t num_children = 0;
2744     switch (variablesReference) {
2745     case VARREF_LOCALS:
2746       start_idx = start;
2747       num_children = g_vsc.num_locals;
2748       break;
2749     case VARREF_GLOBALS:
2750       start_idx = start + g_vsc.num_locals + start;
2751       num_children = g_vsc.num_globals;
2752       break;
2753     case VARREF_REGS:
2754       start_idx = start + g_vsc.num_locals + g_vsc.num_globals;
2755       num_children = g_vsc.num_regs;
2756       break;
2757     default:
2758       break;
2759     }
2760     const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
2761     for (auto i = start_idx; i < end_idx; ++i) {
2762       lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
2763       if (!variable.IsValid())
2764         break;
2765       variables.emplace_back(
2766           CreateVariable(variable, VARIDX_TO_VARREF(i), i, hex));
2767     }
2768   } else {
2769     // We are expanding a variable that has children, so we will return its
2770     // children.
2771     const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
2772     lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(var_idx);
2773     if (variable.IsValid()) {
2774       const auto num_children = variable.GetNumChildren();
2775       const int64_t end_idx = start + ((count == 0) ? num_children : count);
2776       for (auto i = start; i < end_idx; ++i) {
2777         lldb::SBValue child = variable.GetChildAtIndex(i);
2778         if (!child.IsValid())
2779           break;
2780         if (child.MightHaveChildren()) {
2781           const int64_t var_idx = g_vsc.variables.GetSize();
2782           auto childVariablesReferences = VARIDX_TO_VARREF(var_idx);
2783           variables.emplace_back(
2784               CreateVariable(child, childVariablesReferences, var_idx, hex));
2785           g_vsc.variables.Append(child);
2786         } else {
2787           variables.emplace_back(CreateVariable(child, 0, INT64_MAX, hex));
2788         }
2789       }
2790     }
2791   }
2792   llvm::json::Object body;
2793   body.try_emplace("variables", std::move(variables));
2794   response.try_emplace("body", std::move(body));
2795   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2796 }
2797 
2798 // A request used in testing to get the details on all breakpoints that are
2799 // currently set in the target. This helps us to test "setBreakpoints" and
2800 // "setFunctionBreakpoints" requests to verify we have the correct set of
2801 // breakpoints currently set in LLDB.
2802 void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
2803   llvm::json::Object response;
2804   FillResponse(request, response);
2805   llvm::json::Array response_breakpoints;
2806   for (uint32_t i = 0; g_vsc.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
2807     auto bp = g_vsc.target.GetBreakpointAtIndex(i);
2808     AppendBreakpoint(bp, response_breakpoints);
2809   }
2810   llvm::json::Object body;
2811   body.try_emplace("breakpoints", std::move(response_breakpoints));
2812   response.try_emplace("body", std::move(body));
2813   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2814 }
2815 
2816 const std::map<std::string, RequestCallback> &GetRequestHandlers() {
2817 #define REQUEST_CALLBACK(name)                                                 \
2818   { #name, request_##name }
2819   static std::map<std::string, RequestCallback> g_request_handlers = {
2820       // VSCode Debug Adaptor requests
2821       REQUEST_CALLBACK(attach),
2822       REQUEST_CALLBACK(completions),
2823       REQUEST_CALLBACK(continue),
2824       REQUEST_CALLBACK(configurationDone),
2825       REQUEST_CALLBACK(disconnect),
2826       REQUEST_CALLBACK(evaluate),
2827       REQUEST_CALLBACK(exceptionInfo),
2828       REQUEST_CALLBACK(getCompileUnits),
2829       REQUEST_CALLBACK(initialize),
2830       REQUEST_CALLBACK(launch),
2831       REQUEST_CALLBACK(next),
2832       REQUEST_CALLBACK(pause),
2833       REQUEST_CALLBACK(scopes),
2834       REQUEST_CALLBACK(setBreakpoints),
2835       REQUEST_CALLBACK(setExceptionBreakpoints),
2836       REQUEST_CALLBACK(setFunctionBreakpoints),
2837       REQUEST_CALLBACK(setVariable),
2838       REQUEST_CALLBACK(source),
2839       REQUEST_CALLBACK(stackTrace),
2840       REQUEST_CALLBACK(stepIn),
2841       REQUEST_CALLBACK(stepOut),
2842       REQUEST_CALLBACK(threads),
2843       REQUEST_CALLBACK(variables),
2844       // Testing requests
2845       REQUEST_CALLBACK(_testGetTargetBreakpoints),
2846   };
2847 #undef REQUEST_CALLBACK
2848   return g_request_handlers;
2849 }
2850 
2851 } // anonymous namespace
2852 
2853 static void printHelp(LLDBVSCodeOptTable &table, llvm::StringRef tool_name) {
2854   std::string usage_str = tool_name.str() + "options";
2855   table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB VSCode", false);
2856 
2857   std::string examples = R"___(
2858 EXAMPLES:
2859   The debug adapter can be started in two modes.
2860 
2861   Running lldb-vscode without any arguments will start communicating with the
2862   parent over stdio. Passing a port number causes lldb-vscode to start listening
2863   for connections on that port.
2864 
2865     lldb-vscode -p <port>
2866 
2867   Passing --wait-for-debugger will pause the process at startup and wait for a
2868   debugger to attach to the process.
2869 
2870     lldb-vscode -g
2871   )___";
2872   llvm::outs() << examples;
2873 }
2874 
2875 int main(int argc, char *argv[]) {
2876 
2877   // Initialize LLDB first before we do anything.
2878   lldb::SBDebugger::Initialize();
2879 
2880   int portno = -1;
2881 
2882   LLDBVSCodeOptTable T;
2883   unsigned MAI, MAC;
2884   llvm::ArrayRef<const char *> ArgsArr = llvm::makeArrayRef(argv + 1, argc);
2885   llvm::opt::InputArgList input_args = T.ParseArgs(ArgsArr, MAI, MAC);
2886 
2887   if (input_args.hasArg(OPT_help)) {
2888     printHelp(T, llvm::sys::path::filename(argv[0]));
2889     return 0;
2890   }
2891 
2892   if (auto *arg = input_args.getLastArg(OPT_port)) {
2893     auto optarg = arg->getValue();
2894     char *remainder;
2895     portno = strtol(optarg, &remainder, 0);
2896     if (remainder == optarg || *remainder != '\0') {
2897       fprintf(stderr, "'%s' is not a valid port number.\n", optarg);
2898       exit(1);
2899     }
2900   }
2901 
2902 #if !defined(_WIN32)
2903   if (input_args.hasArg(OPT_wait_for_debugger)) {
2904     printf("Paused waiting for debugger to attach (pid = %i)...\n", getpid());
2905     pause();
2906   }
2907 #endif
2908   if (portno != -1) {
2909     printf("Listening on port %i...\n", portno);
2910     SOCKET socket_fd = AcceptConnection(portno);
2911     if (socket_fd >= 0) {
2912       g_vsc.input.descriptor = StreamDescriptor::from_socket(socket_fd, true);
2913       g_vsc.output.descriptor = StreamDescriptor::from_socket(socket_fd, false);
2914     } else {
2915       exit(1);
2916     }
2917   } else {
2918     g_vsc.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false);
2919     g_vsc.output.descriptor =
2920         StreamDescriptor::from_file(fileno(stdout), false);
2921   }
2922   auto request_handlers = GetRequestHandlers();
2923   uint32_t packet_idx = 0;
2924   while (!g_vsc.sent_terminated_event) {
2925     std::string json = g_vsc.ReadJSON();
2926     if (json.empty())
2927       break;
2928 
2929     llvm::StringRef json_sref(json);
2930     llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
2931     if (!json_value) {
2932       auto error = json_value.takeError();
2933       if (g_vsc.log) {
2934         std::string error_str;
2935         llvm::raw_string_ostream strm(error_str);
2936         strm << error;
2937         strm.flush();
2938 
2939         *g_vsc.log << "error: failed to parse JSON: " << error_str << std::endl
2940                    << json << std::endl;
2941       }
2942       return 1;
2943     }
2944 
2945     auto object = json_value->getAsObject();
2946     if (!object) {
2947       if (g_vsc.log)
2948         *g_vsc.log << "error: json packet isn't a object" << std::endl;
2949       return 1;
2950     }
2951 
2952     const auto packet_type = GetString(object, "type");
2953     if (packet_type == "request") {
2954       const auto command = GetString(object, "command");
2955       auto handler_pos = request_handlers.find(std::string(command));
2956       if (handler_pos != request_handlers.end()) {
2957         handler_pos->second(*object);
2958       } else {
2959         if (g_vsc.log)
2960           *g_vsc.log << "error: unhandled command \"" << command.data() << std::endl;
2961         return 1;
2962       }
2963     }
2964     ++packet_idx;
2965   }
2966 
2967   // We must terminate the debugger in a thread before the C++ destructor
2968   // chain messes everything up.
2969   lldb::SBDebugger::Terminate();
2970   return 0;
2971 }
2972