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