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