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