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