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   // As the user selects different stack frames in the GUI, a "scopes" request
1599   // will be sent to the DAP. This is the only way we know that the user has
1600   // selected a frame in a thread. There are no other notifications that are
1601   // sent and VS code doesn't allow multiple frames to show variables
1602   // concurrently. If we select the thread and frame as the "scopes" requests
1603   // are sent, this allows users to type commands in the debugger console
1604   // with a backtick character to run lldb commands and these lldb commands
1605   // will now have the right context selected as they are run. If the user
1606   // types "`bt" into the debugger console and we had another thread selected
1607   // in the LLDB library, we would show the wrong thing to the user. If the
1608   // users switches threads with a lldb command like "`thread select 14", the
1609   // GUI will not update as there are no "event" notification packets that
1610   // allow us to change the currently selected thread or frame in the GUI that
1611   // I am aware of.
1612   if (frame.IsValid()) {
1613     frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
1614     frame.GetThread().SetSelectedFrame(frame.GetFrameID());
1615   }
1616   g_vsc.variables.Clear();
1617   g_vsc.variables.Append(frame.GetVariables(true,   // arguments
1618                                             true,   // locals
1619                                             false,  // statics
1620                                             true)); // in_scope_only
1621   g_vsc.num_locals = g_vsc.variables.GetSize();
1622   g_vsc.variables.Append(frame.GetVariables(false,  // arguments
1623                                             false,  // locals
1624                                             true,   // statics
1625                                             true)); // in_scope_only
1626   g_vsc.num_globals = g_vsc.variables.GetSize() - (g_vsc.num_locals);
1627   g_vsc.variables.Append(frame.GetRegisters());
1628   g_vsc.num_regs =
1629       g_vsc.variables.GetSize() - (g_vsc.num_locals + g_vsc.num_globals);
1630   body.try_emplace("scopes", g_vsc.CreateTopLevelScopes());
1631   response.try_emplace("body", std::move(body));
1632   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1633 }
1634 
1635 // "SetBreakpointsRequest": {
1636 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1637 //     "type": "object",
1638 //     "description": "SetBreakpoints request; value of command field is
1639 //     'setBreakpoints'. Sets multiple breakpoints for a single source and
1640 //     clears all previous breakpoints in that source. To clear all breakpoint
1641 //     for a source, specify an empty array. When a breakpoint is hit, a
1642 //     StoppedEvent (event type 'breakpoint') is generated.", "properties": {
1643 //       "command": {
1644 //         "type": "string",
1645 //         "enum": [ "setBreakpoints" ]
1646 //       },
1647 //       "arguments": {
1648 //         "$ref": "#/definitions/SetBreakpointsArguments"
1649 //       }
1650 //     },
1651 //     "required": [ "command", "arguments"  ]
1652 //   }]
1653 // },
1654 // "SetBreakpointsArguments": {
1655 //   "type": "object",
1656 //   "description": "Arguments for 'setBreakpoints' request.",
1657 //   "properties": {
1658 //     "source": {
1659 //       "$ref": "#/definitions/Source",
1660 //       "description": "The source location of the breakpoints; either
1661 //       source.path or source.reference must be specified."
1662 //     },
1663 //     "breakpoints": {
1664 //       "type": "array",
1665 //       "items": {
1666 //         "$ref": "#/definitions/SourceBreakpoint"
1667 //       },
1668 //       "description": "The code locations of the breakpoints."
1669 //     },
1670 //     "lines": {
1671 //       "type": "array",
1672 //       "items": {
1673 //         "type": "integer"
1674 //       },
1675 //       "description": "Deprecated: The code locations of the breakpoints."
1676 //     },
1677 //     "sourceModified": {
1678 //       "type": "boolean",
1679 //       "description": "A value of true indicates that the underlying source
1680 //       has been modified which results in new breakpoint locations."
1681 //     }
1682 //   },
1683 //   "required": [ "source" ]
1684 // },
1685 // "SetBreakpointsResponse": {
1686 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1687 //     "type": "object",
1688 //     "description": "Response to 'setBreakpoints' request. Returned is
1689 //     information about each breakpoint created by this request. This includes
1690 //     the actual code location and whether the breakpoint could be verified.
1691 //     The breakpoints returned are in the same order as the elements of the
1692 //     'breakpoints' (or the deprecated 'lines') in the
1693 //     SetBreakpointsArguments.", "properties": {
1694 //       "body": {
1695 //         "type": "object",
1696 //         "properties": {
1697 //           "breakpoints": {
1698 //             "type": "array",
1699 //             "items": {
1700 //               "$ref": "#/definitions/Breakpoint"
1701 //             },
1702 //             "description": "Information about the breakpoints. The array
1703 //             elements are in the same order as the elements of the
1704 //             'breakpoints' (or the deprecated 'lines') in the
1705 //             SetBreakpointsArguments."
1706 //           }
1707 //         },
1708 //         "required": [ "breakpoints" ]
1709 //       }
1710 //     },
1711 //     "required": [ "body" ]
1712 //   }]
1713 // },
1714 // "SourceBreakpoint": {
1715 //   "type": "object",
1716 //   "description": "Properties of a breakpoint or logpoint passed to the
1717 //   setBreakpoints request.", "properties": {
1718 //     "line": {
1719 //       "type": "integer",
1720 //       "description": "The source line of the breakpoint or logpoint."
1721 //     },
1722 //     "column": {
1723 //       "type": "integer",
1724 //       "description": "An optional source column of the breakpoint."
1725 //     },
1726 //     "condition": {
1727 //       "type": "string",
1728 //       "description": "An optional expression for conditional breakpoints."
1729 //     },
1730 //     "hitCondition": {
1731 //       "type": "string",
1732 //       "description": "An optional expression that controls how many hits of
1733 //       the breakpoint are ignored. The backend is expected to interpret the
1734 //       expression as needed."
1735 //     },
1736 //     "logMessage": {
1737 //       "type": "string",
1738 //       "description": "If this attribute exists and is non-empty, the backend
1739 //       must not 'break' (stop) but log the message instead. Expressions within
1740 //       {} are interpolated."
1741 //     }
1742 //   },
1743 //   "required": [ "line" ]
1744 // }
1745 void request_setBreakpoints(const llvm::json::Object &request) {
1746   llvm::json::Object response;
1747   lldb::SBError error;
1748   FillResponse(request, response);
1749   auto arguments = request.getObject("arguments");
1750   auto source = arguments->getObject("source");
1751   const auto path = GetString(source, "path");
1752   auto breakpoints = arguments->getArray("breakpoints");
1753   llvm::json::Array response_breakpoints;
1754 
1755   // Decode the source breakpoint infos for this "setBreakpoints" request
1756   SourceBreakpointMap request_bps;
1757   for (const auto &bp : *breakpoints) {
1758     auto bp_obj = bp.getAsObject();
1759     if (bp_obj) {
1760       SourceBreakpoint src_bp(*bp_obj);
1761       request_bps[src_bp.line] = src_bp;
1762 
1763       // We check if this breakpoint already exists to update it
1764       auto existing_source_bps = g_vsc.source_breakpoints.find(path);
1765       if (existing_source_bps != g_vsc.source_breakpoints.end()) {
1766         const auto &existing_bp = existing_source_bps->second.find(src_bp.line);
1767         if (existing_bp != existing_source_bps->second.end()) {
1768           existing_bp->second.UpdateBreakpoint(src_bp);
1769           AppendBreakpoint(existing_bp->second.bp, response_breakpoints);
1770           continue;
1771         }
1772       }
1773       // At this point the breakpoint is new
1774       src_bp.SetBreakpoint(path.data());
1775       AppendBreakpoint(src_bp.bp, response_breakpoints);
1776       g_vsc.source_breakpoints[path][src_bp.line] = std::move(src_bp);
1777     }
1778   }
1779 
1780   // Delete any breakpoints in this source file that aren't in the
1781   // request_bps set. There is no call to remove breakpoints other than
1782   // calling this function with a smaller or empty "breakpoints" list.
1783   auto old_src_bp_pos = g_vsc.source_breakpoints.find(path);
1784   if (old_src_bp_pos != g_vsc.source_breakpoints.end()) {
1785     for (auto &old_bp : old_src_bp_pos->second) {
1786       auto request_pos = request_bps.find(old_bp.first);
1787       if (request_pos == request_bps.end()) {
1788         // This breakpoint no longer exists in this source file, delete it
1789         g_vsc.target.BreakpointDelete(old_bp.second.bp.GetID());
1790         old_src_bp_pos->second.erase(old_bp.first);
1791       }
1792     }
1793   }
1794 
1795   llvm::json::Object body;
1796   body.try_emplace("breakpoints", std::move(response_breakpoints));
1797   response.try_emplace("body", std::move(body));
1798   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1799 }
1800 
1801 // "SetExceptionBreakpointsRequest": {
1802 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1803 //     "type": "object",
1804 //     "description": "SetExceptionBreakpoints request; value of command field
1805 //     is 'setExceptionBreakpoints'. The request configures the debuggers
1806 //     response to thrown exceptions. If an exception is configured to break, a
1807 //     StoppedEvent is fired (event type 'exception').", "properties": {
1808 //       "command": {
1809 //         "type": "string",
1810 //         "enum": [ "setExceptionBreakpoints" ]
1811 //       },
1812 //       "arguments": {
1813 //         "$ref": "#/definitions/SetExceptionBreakpointsArguments"
1814 //       }
1815 //     },
1816 //     "required": [ "command", "arguments"  ]
1817 //   }]
1818 // },
1819 // "SetExceptionBreakpointsArguments": {
1820 //   "type": "object",
1821 //   "description": "Arguments for 'setExceptionBreakpoints' request.",
1822 //   "properties": {
1823 //     "filters": {
1824 //       "type": "array",
1825 //       "items": {
1826 //         "type": "string"
1827 //       },
1828 //       "description": "IDs of checked exception options. The set of IDs is
1829 //       returned via the 'exceptionBreakpointFilters' capability."
1830 //     },
1831 //     "exceptionOptions": {
1832 //       "type": "array",
1833 //       "items": {
1834 //         "$ref": "#/definitions/ExceptionOptions"
1835 //       },
1836 //       "description": "Configuration options for selected exceptions."
1837 //     }
1838 //   },
1839 //   "required": [ "filters" ]
1840 // },
1841 // "SetExceptionBreakpointsResponse": {
1842 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1843 //     "type": "object",
1844 //     "description": "Response to 'setExceptionBreakpoints' request. This is
1845 //     just an acknowledgement, so no body field is required."
1846 //   }]
1847 // }
1848 void request_setExceptionBreakpoints(const llvm::json::Object &request) {
1849   llvm::json::Object response;
1850   lldb::SBError error;
1851   FillResponse(request, response);
1852   auto arguments = request.getObject("arguments");
1853   auto filters = arguments->getArray("filters");
1854   // Keep a list of any exception breakpoint filter names that weren't set
1855   // so we can clear any exception breakpoints if needed.
1856   std::set<std::string> unset_filters;
1857   for (const auto &bp : g_vsc.exception_breakpoints)
1858     unset_filters.insert(bp.filter);
1859 
1860   for (const auto &value : *filters) {
1861     const auto filter = GetAsString(value);
1862     auto exc_bp = g_vsc.GetExceptionBreakpoint(std::string(filter));
1863     if (exc_bp) {
1864       exc_bp->SetBreakpoint();
1865       unset_filters.erase(std::string(filter));
1866     }
1867   }
1868   for (const auto &filter : unset_filters) {
1869     auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
1870     if (exc_bp)
1871       exc_bp->ClearBreakpoint();
1872   }
1873   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1874 }
1875 
1876 // "SetFunctionBreakpointsRequest": {
1877 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1878 //     "type": "object",
1879 //     "description": "SetFunctionBreakpoints request; value of command field is
1880 //     'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
1881 //     all previous function breakpoints. To clear all function breakpoint,
1882 //     specify an empty array. When a function breakpoint is hit, a StoppedEvent
1883 //     (event type 'function breakpoint') is generated.", "properties": {
1884 //       "command": {
1885 //         "type": "string",
1886 //         "enum": [ "setFunctionBreakpoints" ]
1887 //       },
1888 //       "arguments": {
1889 //         "$ref": "#/definitions/SetFunctionBreakpointsArguments"
1890 //       }
1891 //     },
1892 //     "required": [ "command", "arguments"  ]
1893 //   }]
1894 // },
1895 // "SetFunctionBreakpointsArguments": {
1896 //   "type": "object",
1897 //   "description": "Arguments for 'setFunctionBreakpoints' request.",
1898 //   "properties": {
1899 //     "breakpoints": {
1900 //       "type": "array",
1901 //       "items": {
1902 //         "$ref": "#/definitions/FunctionBreakpoint"
1903 //       },
1904 //       "description": "The function names of the breakpoints."
1905 //     }
1906 //   },
1907 //   "required": [ "breakpoints" ]
1908 // },
1909 // "FunctionBreakpoint": {
1910 //   "type": "object",
1911 //   "description": "Properties of a breakpoint passed to the
1912 //   setFunctionBreakpoints request.", "properties": {
1913 //     "name": {
1914 //       "type": "string",
1915 //       "description": "The name of the function."
1916 //     },
1917 //     "condition": {
1918 //       "type": "string",
1919 //       "description": "An optional expression for conditional breakpoints."
1920 //     },
1921 //     "hitCondition": {
1922 //       "type": "string",
1923 //       "description": "An optional expression that controls how many hits of
1924 //       the breakpoint are ignored. The backend is expected to interpret the
1925 //       expression as needed."
1926 //     }
1927 //   },
1928 //   "required": [ "name" ]
1929 // },
1930 // "SetFunctionBreakpointsResponse": {
1931 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1932 //     "type": "object",
1933 //     "description": "Response to 'setFunctionBreakpoints' request. Returned is
1934 //     information about each breakpoint created by this request.",
1935 //     "properties": {
1936 //       "body": {
1937 //         "type": "object",
1938 //         "properties": {
1939 //           "breakpoints": {
1940 //             "type": "array",
1941 //             "items": {
1942 //               "$ref": "#/definitions/Breakpoint"
1943 //             },
1944 //             "description": "Information about the breakpoints. The array
1945 //             elements correspond to the elements of the 'breakpoints' array."
1946 //           }
1947 //         },
1948 //         "required": [ "breakpoints" ]
1949 //       }
1950 //     },
1951 //     "required": [ "body" ]
1952 //   }]
1953 // }
1954 void request_setFunctionBreakpoints(const llvm::json::Object &request) {
1955   llvm::json::Object response;
1956   lldb::SBError error;
1957   FillResponse(request, response);
1958   auto arguments = request.getObject("arguments");
1959   auto breakpoints = arguments->getArray("breakpoints");
1960   FunctionBreakpointMap request_bps;
1961   llvm::json::Array response_breakpoints;
1962   for (const auto &value : *breakpoints) {
1963     auto bp_obj = value.getAsObject();
1964     if (bp_obj == nullptr)
1965       continue;
1966     FunctionBreakpoint func_bp(*bp_obj);
1967     request_bps[func_bp.functionName] = std::move(func_bp);
1968   }
1969 
1970   std::vector<llvm::StringRef> remove_names;
1971   // Disable any function breakpoints that aren't in the request_bps.
1972   // There is no call to remove function breakpoints other than calling this
1973   // function with a smaller or empty "breakpoints" list.
1974   for (auto &pair: g_vsc.function_breakpoints) {
1975     auto request_pos = request_bps.find(pair.first());
1976     if (request_pos == request_bps.end()) {
1977       // This function breakpoint no longer exists delete it from LLDB
1978       g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
1979       remove_names.push_back(pair.first());
1980     } else {
1981       // Update the existing breakpoint as any setting withing the function
1982       // breakpoint might have changed.
1983       pair.second.UpdateBreakpoint(request_pos->second);
1984       // Remove this breakpoint from the request breakpoints since we have
1985       // handled it here and we don't need to set a new breakpoint below.
1986       request_bps.erase(request_pos);
1987       // Add this breakpoint info to the response
1988       AppendBreakpoint(pair.second.bp, response_breakpoints);
1989     }
1990   }
1991   // Remove any breakpoints that are no longer in our list
1992   for (const auto &name: remove_names)
1993     g_vsc.function_breakpoints.erase(name);
1994 
1995   // Any breakpoints that are left in "request_bps" are breakpoints that
1996   // need to be set.
1997   for (auto &pair : request_bps) {
1998     pair.second.SetBreakpoint();
1999     // Add this breakpoint info to the response
2000     AppendBreakpoint(pair.second.bp, response_breakpoints);
2001     g_vsc.function_breakpoints[pair.first()] = std::move(pair.second);
2002   }
2003 
2004   llvm::json::Object body;
2005   body.try_emplace("breakpoints", std::move(response_breakpoints));
2006   response.try_emplace("body", std::move(body));
2007   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2008 }
2009 
2010 // "SourceRequest": {
2011 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2012 //     "type": "object",
2013 //     "description": "Source request; value of command field is 'source'. The
2014 //     request retrieves the source code for a given source reference.",
2015 //     "properties": {
2016 //       "command": {
2017 //         "type": "string",
2018 //         "enum": [ "source" ]
2019 //       },
2020 //       "arguments": {
2021 //         "$ref": "#/definitions/SourceArguments"
2022 //       }
2023 //     },
2024 //     "required": [ "command", "arguments"  ]
2025 //   }]
2026 // },
2027 // "SourceArguments": {
2028 //   "type": "object",
2029 //   "description": "Arguments for 'source' request.",
2030 //   "properties": {
2031 //     "source": {
2032 //       "$ref": "#/definitions/Source",
2033 //       "description": "Specifies the source content to load. Either
2034 //       source.path or source.sourceReference must be specified."
2035 //     },
2036 //     "sourceReference": {
2037 //       "type": "integer",
2038 //       "description": "The reference to the source. This is the same as
2039 //       source.sourceReference. This is provided for backward compatibility
2040 //       since old backends do not understand the 'source' attribute."
2041 //     }
2042 //   },
2043 //   "required": [ "sourceReference" ]
2044 // },
2045 // "SourceResponse": {
2046 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2047 //     "type": "object",
2048 //     "description": "Response to 'source' request.",
2049 //     "properties": {
2050 //       "body": {
2051 //         "type": "object",
2052 //         "properties": {
2053 //           "content": {
2054 //             "type": "string",
2055 //             "description": "Content of the source reference."
2056 //           },
2057 //           "mimeType": {
2058 //             "type": "string",
2059 //             "description": "Optional content type (mime type) of the source."
2060 //           }
2061 //         },
2062 //         "required": [ "content" ]
2063 //       }
2064 //     },
2065 //     "required": [ "body" ]
2066 //   }]
2067 // }
2068 void request_source(const llvm::json::Object &request) {
2069   llvm::json::Object response;
2070   FillResponse(request, response);
2071   llvm::json::Object body;
2072 
2073   auto arguments = request.getObject("arguments");
2074   auto source = arguments->getObject("source");
2075   auto sourceReference = GetSigned(source, "sourceReference", -1);
2076   auto pos = g_vsc.source_map.find((lldb::addr_t)sourceReference);
2077   if (pos != g_vsc.source_map.end()) {
2078     EmplaceSafeString(body, "content", pos->second.content);
2079   } else {
2080     response["success"] = llvm::json::Value(false);
2081   }
2082   response.try_emplace("body", std::move(body));
2083   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2084 }
2085 
2086 // "StackTraceRequest": {
2087 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2088 //     "type": "object",
2089 //     "description": "StackTrace request; value of command field is
2090 //     'stackTrace'. The request returns a stacktrace from the current execution
2091 //     state.", "properties": {
2092 //       "command": {
2093 //         "type": "string",
2094 //         "enum": [ "stackTrace" ]
2095 //       },
2096 //       "arguments": {
2097 //         "$ref": "#/definitions/StackTraceArguments"
2098 //       }
2099 //     },
2100 //     "required": [ "command", "arguments"  ]
2101 //   }]
2102 // },
2103 // "StackTraceArguments": {
2104 //   "type": "object",
2105 //   "description": "Arguments for 'stackTrace' request.",
2106 //   "properties": {
2107 //     "threadId": {
2108 //       "type": "integer",
2109 //       "description": "Retrieve the stacktrace for this thread."
2110 //     },
2111 //     "startFrame": {
2112 //       "type": "integer",
2113 //       "description": "The index of the first frame to return; if omitted
2114 //       frames start at 0."
2115 //     },
2116 //     "levels": {
2117 //       "type": "integer",
2118 //       "description": "The maximum number of frames to return. If levels is
2119 //       not specified or 0, all frames are returned."
2120 //     },
2121 //     "format": {
2122 //       "$ref": "#/definitions/StackFrameFormat",
2123 //       "description": "Specifies details on how to format the stack frames."
2124 //     }
2125 //  },
2126 //   "required": [ "threadId" ]
2127 // },
2128 // "StackTraceResponse": {
2129 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2130 //     "type": "object",
2131 //     "description": "Response to 'stackTrace' request.",
2132 //     "properties": {
2133 //       "body": {
2134 //         "type": "object",
2135 //         "properties": {
2136 //           "stackFrames": {
2137 //             "type": "array",
2138 //             "items": {
2139 //               "$ref": "#/definitions/StackFrame"
2140 //             },
2141 //             "description": "The frames of the stackframe. If the array has
2142 //             length zero, there are no stackframes available. This means that
2143 //             there is no location information available."
2144 //           },
2145 //           "totalFrames": {
2146 //             "type": "integer",
2147 //             "description": "The total number of frames available."
2148 //           }
2149 //         },
2150 //         "required": [ "stackFrames" ]
2151 //       }
2152 //     },
2153 //     "required": [ "body" ]
2154 //   }]
2155 // }
2156 void request_stackTrace(const llvm::json::Object &request) {
2157   llvm::json::Object response;
2158   FillResponse(request, response);
2159   lldb::SBError error;
2160   auto arguments = request.getObject("arguments");
2161   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2162   llvm::json::Array stackFrames;
2163   llvm::json::Object body;
2164 
2165   if (thread.IsValid()) {
2166     const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
2167     const auto levels = GetUnsigned(arguments, "levels", 0);
2168     const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
2169     for (uint32_t i = startFrame; i < endFrame; ++i) {
2170       auto frame = thread.GetFrameAtIndex(i);
2171       if (!frame.IsValid())
2172         break;
2173       stackFrames.emplace_back(CreateStackFrame(frame));
2174     }
2175     const auto totalFrames = thread.GetNumFrames();
2176     body.try_emplace("totalFrames", totalFrames);
2177   }
2178   body.try_emplace("stackFrames", std::move(stackFrames));
2179   response.try_emplace("body", std::move(body));
2180   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2181 }
2182 
2183 // "StepInRequest": {
2184 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2185 //     "type": "object",
2186 //     "description": "StepIn request; value of command field is 'stepIn'. The
2187 //     request starts the debuggee to step into a function/method if possible.
2188 //     If it cannot step into a target, 'stepIn' behaves like 'next'. The debug
2189 //     adapter first sends the StepInResponse and then a StoppedEvent (event
2190 //     type 'step') after the step has completed. If there are multiple
2191 //     function/method calls (or other targets) on the source line, the optional
2192 //     argument 'targetId' can be used to control into which target the 'stepIn'
2193 //     should occur. The list of possible targets for a given source line can be
2194 //     retrieved via the 'stepInTargets' request.", "properties": {
2195 //       "command": {
2196 //         "type": "string",
2197 //         "enum": [ "stepIn" ]
2198 //       },
2199 //       "arguments": {
2200 //         "$ref": "#/definitions/StepInArguments"
2201 //       }
2202 //     },
2203 //     "required": [ "command", "arguments"  ]
2204 //   }]
2205 // },
2206 // "StepInArguments": {
2207 //   "type": "object",
2208 //   "description": "Arguments for 'stepIn' request.",
2209 //   "properties": {
2210 //     "threadId": {
2211 //       "type": "integer",
2212 //       "description": "Execute 'stepIn' for this thread."
2213 //     },
2214 //     "targetId": {
2215 //       "type": "integer",
2216 //       "description": "Optional id of the target to step into."
2217 //     }
2218 //   },
2219 //   "required": [ "threadId" ]
2220 // },
2221 // "StepInResponse": {
2222 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2223 //     "type": "object",
2224 //     "description": "Response to 'stepIn' request. This is just an
2225 //     acknowledgement, so no body field is required."
2226 //   }]
2227 // }
2228 void request_stepIn(const llvm::json::Object &request) {
2229   llvm::json::Object response;
2230   FillResponse(request, response);
2231   auto arguments = request.getObject("arguments");
2232   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2233   if (thread.IsValid()) {
2234     // Remember the thread ID that caused the resume so we can set the
2235     // "threadCausedFocus" boolean value in the "stopped" events.
2236     g_vsc.focus_tid = thread.GetThreadID();
2237     thread.StepInto();
2238   } else {
2239     response["success"] = llvm::json::Value(false);
2240   }
2241   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2242 }
2243 
2244 // "StepOutRequest": {
2245 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2246 //     "type": "object",
2247 //     "description": "StepOut request; value of command field is 'stepOut'. The
2248 //     request starts the debuggee to run again for one step. The debug adapter
2249 //     first sends the StepOutResponse and then a StoppedEvent (event type
2250 //     'step') after the step has completed.", "properties": {
2251 //       "command": {
2252 //         "type": "string",
2253 //         "enum": [ "stepOut" ]
2254 //       },
2255 //       "arguments": {
2256 //         "$ref": "#/definitions/StepOutArguments"
2257 //       }
2258 //     },
2259 //     "required": [ "command", "arguments"  ]
2260 //   }]
2261 // },
2262 // "StepOutArguments": {
2263 //   "type": "object",
2264 //   "description": "Arguments for 'stepOut' request.",
2265 //   "properties": {
2266 //     "threadId": {
2267 //       "type": "integer",
2268 //       "description": "Execute 'stepOut' for this thread."
2269 //     }
2270 //   },
2271 //   "required": [ "threadId" ]
2272 // },
2273 // "StepOutResponse": {
2274 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2275 //     "type": "object",
2276 //     "description": "Response to 'stepOut' request. This is just an
2277 //     acknowledgement, so no body field is required."
2278 //   }]
2279 // }
2280 void request_stepOut(const llvm::json::Object &request) {
2281   llvm::json::Object response;
2282   FillResponse(request, response);
2283   auto arguments = request.getObject("arguments");
2284   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2285   if (thread.IsValid()) {
2286     // Remember the thread ID that caused the resume so we can set the
2287     // "threadCausedFocus" boolean value in the "stopped" events.
2288     g_vsc.focus_tid = thread.GetThreadID();
2289     thread.StepOut();
2290   } else {
2291     response["success"] = llvm::json::Value(false);
2292   }
2293   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2294 }
2295 
2296 // "ThreadsRequest": {
2297 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2298 //     "type": "object",
2299 //     "description": "Thread request; value of command field is 'threads'. The
2300 //     request retrieves a list of all threads.", "properties": {
2301 //       "command": {
2302 //         "type": "string",
2303 //         "enum": [ "threads" ]
2304 //       }
2305 //     },
2306 //     "required": [ "command" ]
2307 //   }]
2308 // },
2309 // "ThreadsResponse": {
2310 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2311 //     "type": "object",
2312 //     "description": "Response to 'threads' request.",
2313 //     "properties": {
2314 //       "body": {
2315 //         "type": "object",
2316 //         "properties": {
2317 //           "threads": {
2318 //             "type": "array",
2319 //             "items": {
2320 //               "$ref": "#/definitions/Thread"
2321 //             },
2322 //             "description": "All threads."
2323 //           }
2324 //         },
2325 //         "required": [ "threads" ]
2326 //       }
2327 //     },
2328 //     "required": [ "body" ]
2329 //   }]
2330 // }
2331 void request_threads(const llvm::json::Object &request) {
2332 
2333   lldb::SBProcess process = g_vsc.target.GetProcess();
2334   llvm::json::Object response;
2335   FillResponse(request, response);
2336 
2337   const uint32_t num_threads = process.GetNumThreads();
2338   llvm::json::Array threads;
2339   for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
2340     lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
2341     threads.emplace_back(CreateThread(thread));
2342   }
2343   if (threads.size() == 0) {
2344     response["success"] = llvm::json::Value(false);
2345   }
2346   llvm::json::Object body;
2347   body.try_emplace("threads", std::move(threads));
2348   response.try_emplace("body", std::move(body));
2349   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2350 }
2351 
2352 // "SetVariableRequest": {
2353 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2354 //     "type": "object",
2355 //     "description": "setVariable request; value of command field is
2356 //     'setVariable'. Set the variable with the given name in the variable
2357 //     container to a new value.", "properties": {
2358 //       "command": {
2359 //         "type": "string",
2360 //         "enum": [ "setVariable" ]
2361 //       },
2362 //       "arguments": {
2363 //         "$ref": "#/definitions/SetVariableArguments"
2364 //       }
2365 //     },
2366 //     "required": [ "command", "arguments"  ]
2367 //   }]
2368 // },
2369 // "SetVariableArguments": {
2370 //   "type": "object",
2371 //   "description": "Arguments for 'setVariable' request.",
2372 //   "properties": {
2373 //     "variablesReference": {
2374 //       "type": "integer",
2375 //       "description": "The reference of the variable container."
2376 //     },
2377 //     "name": {
2378 //       "type": "string",
2379 //       "description": "The name of the variable."
2380 //     },
2381 //     "value": {
2382 //       "type": "string",
2383 //       "description": "The value of the variable."
2384 //     },
2385 //     "format": {
2386 //       "$ref": "#/definitions/ValueFormat",
2387 //       "description": "Specifies details on how to format the response value."
2388 //     }
2389 //   },
2390 //   "required": [ "variablesReference", "name", "value" ]
2391 // },
2392 // "SetVariableResponse": {
2393 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2394 //     "type": "object",
2395 //     "description": "Response to 'setVariable' request.",
2396 //     "properties": {
2397 //       "body": {
2398 //         "type": "object",
2399 //         "properties": {
2400 //           "value": {
2401 //             "type": "string",
2402 //             "description": "The new value of the variable."
2403 //           },
2404 //           "type": {
2405 //             "type": "string",
2406 //             "description": "The type of the new value. Typically shown in the
2407 //             UI when hovering over the value."
2408 //           },
2409 //           "variablesReference": {
2410 //             "type": "number",
2411 //             "description": "If variablesReference is > 0, the new value is
2412 //             structured and its children can be retrieved by passing
2413 //             variablesReference to the VariablesRequest."
2414 //           },
2415 //           "namedVariables": {
2416 //             "type": "number",
2417 //             "description": "The number of named child variables. The client
2418 //             can use this optional information to present the variables in a
2419 //             paged UI and fetch them in chunks."
2420 //           },
2421 //           "indexedVariables": {
2422 //             "type": "number",
2423 //             "description": "The number of indexed child variables. The client
2424 //             can use this optional information to present the variables in a
2425 //             paged UI and fetch them in chunks."
2426 //           }
2427 //         },
2428 //         "required": [ "value" ]
2429 //       }
2430 //     },
2431 //     "required": [ "body" ]
2432 //   }]
2433 // }
2434 void request_setVariable(const llvm::json::Object &request) {
2435   llvm::json::Object response;
2436   FillResponse(request, response);
2437   llvm::json::Array variables;
2438   llvm::json::Object body;
2439   auto arguments = request.getObject("arguments");
2440   // This is a reference to the containing variable/scope
2441   const auto variablesReference =
2442       GetUnsigned(arguments, "variablesReference", 0);
2443   const auto name = GetString(arguments, "name");
2444   const auto value = GetString(arguments, "value");
2445   // Set success to false just in case we don't find the variable by name
2446   response.try_emplace("success", false);
2447 
2448   lldb::SBValue variable;
2449   int64_t newVariablesReference = 0;
2450 
2451   // The "id" is the unique integer ID that is unique within the enclosing
2452   // variablesReference. It is optionally added to any "interface Variable"
2453   // objects to uniquely identify a variable within an enclosing
2454   // variablesReference. It helps to disambiguate between two variables that
2455   // have the same name within the same scope since the "setVariables" request
2456   // only specifies the variable reference of the enclosing scope/variable, and
2457   // the name of the variable. We could have two shadowed variables with the
2458   // same name in "Locals" or "Globals". In our case the "id" absolute index
2459   // of the variable within the g_vsc.variables list.
2460   const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
2461   if (id_value != UINT64_MAX) {
2462     variable = g_vsc.variables.GetValueAtIndex(id_value);
2463   } else if (VARREF_IS_SCOPE(variablesReference)) {
2464     // variablesReference is one of our scopes, not an actual variable it is
2465     // asking for a variable in locals or globals or registers
2466     int64_t start_idx = 0;
2467     int64_t end_idx = 0;
2468     switch (variablesReference) {
2469     case VARREF_LOCALS:
2470       start_idx = 0;
2471       end_idx = start_idx + g_vsc.num_locals;
2472       break;
2473     case VARREF_GLOBALS:
2474       start_idx = g_vsc.num_locals;
2475       end_idx = start_idx + g_vsc.num_globals;
2476       break;
2477     case VARREF_REGS:
2478       start_idx = g_vsc.num_locals + g_vsc.num_globals;
2479       end_idx = start_idx + g_vsc.num_regs;
2480       break;
2481     default:
2482       break;
2483     }
2484 
2485     // Find the variable by name in the correct scope and hope we don't have
2486     // multiple variables with the same name. We search backwards because
2487     // the list of variables has the top most variables first and variables
2488     // in deeper scopes are last. This means we will catch the deepest
2489     // variable whose name matches which is probably what the user wants.
2490     for (int64_t i = end_idx - 1; i >= start_idx; --i) {
2491       auto curr_variable = g_vsc.variables.GetValueAtIndex(i);
2492       llvm::StringRef variable_name(curr_variable.GetName());
2493       if (variable_name == name) {
2494         variable = curr_variable;
2495         if (curr_variable.MightHaveChildren())
2496           newVariablesReference = i;
2497         break;
2498       }
2499     }
2500   } else {
2501     // We have a named item within an actual variable so we need to find it
2502     // withing the container variable by name.
2503     const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
2504     lldb::SBValue container = g_vsc.variables.GetValueAtIndex(var_idx);
2505     variable = container.GetChildMemberWithName(name.data());
2506     if (!variable.IsValid()) {
2507       if (name.startswith("[")) {
2508         llvm::StringRef index_str(name.drop_front(1));
2509         uint64_t index = 0;
2510         if (!index_str.consumeInteger(0, index)) {
2511           if (index_str == "]")
2512             variable = container.GetChildAtIndex(index);
2513         }
2514       }
2515     }
2516 
2517     // We don't know the index of the variable in our g_vsc.variables
2518     if (variable.IsValid()) {
2519       if (variable.MightHaveChildren()) {
2520         newVariablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
2521         g_vsc.variables.Append(variable);
2522       }
2523     }
2524   }
2525 
2526   if (variable.IsValid()) {
2527     lldb::SBError error;
2528     bool success = variable.SetValueFromCString(value.data(), error);
2529     if (success) {
2530       SetValueForKey(variable, body, "value");
2531       EmplaceSafeString(body, "type", variable.GetType().GetDisplayTypeName());
2532       body.try_emplace("variablesReference", newVariablesReference);
2533     } else {
2534       EmplaceSafeString(body, "message", std::string(error.GetCString()));
2535     }
2536     response["success"] = llvm::json::Value(success);
2537   }
2538 
2539   response.try_emplace("body", std::move(body));
2540   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2541 }
2542 
2543 // "VariablesRequest": {
2544 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2545 //     "type": "object",
2546 //     "description": "Variables request; value of command field is 'variables'.
2547 //     Retrieves all child variables for the given variable reference. An
2548 //     optional filter can be used to limit the fetched children to either named
2549 //     or indexed children.", "properties": {
2550 //       "command": {
2551 //         "type": "string",
2552 //         "enum": [ "variables" ]
2553 //       },
2554 //       "arguments": {
2555 //         "$ref": "#/definitions/VariablesArguments"
2556 //       }
2557 //     },
2558 //     "required": [ "command", "arguments"  ]
2559 //   }]
2560 // },
2561 // "VariablesArguments": {
2562 //   "type": "object",
2563 //   "description": "Arguments for 'variables' request.",
2564 //   "properties": {
2565 //     "variablesReference": {
2566 //       "type": "integer",
2567 //       "description": "The Variable reference."
2568 //     },
2569 //     "filter": {
2570 //       "type": "string",
2571 //       "enum": [ "indexed", "named" ],
2572 //       "description": "Optional filter to limit the child variables to either
2573 //       named or indexed. If ommited, both types are fetched."
2574 //     },
2575 //     "start": {
2576 //       "type": "integer",
2577 //       "description": "The index of the first variable to return; if omitted
2578 //       children start at 0."
2579 //     },
2580 //     "count": {
2581 //       "type": "integer",
2582 //       "description": "The number of variables to return. If count is missing
2583 //       or 0, all variables are returned."
2584 //     },
2585 //     "format": {
2586 //       "$ref": "#/definitions/ValueFormat",
2587 //       "description": "Specifies details on how to format the Variable
2588 //       values."
2589 //     }
2590 //   },
2591 //   "required": [ "variablesReference" ]
2592 // },
2593 // "VariablesResponse": {
2594 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2595 //     "type": "object",
2596 //     "description": "Response to 'variables' request.",
2597 //     "properties": {
2598 //       "body": {
2599 //         "type": "object",
2600 //         "properties": {
2601 //           "variables": {
2602 //             "type": "array",
2603 //             "items": {
2604 //               "$ref": "#/definitions/Variable"
2605 //             },
2606 //             "description": "All (or a range) of variables for the given
2607 //             variable reference."
2608 //           }
2609 //         },
2610 //         "required": [ "variables" ]
2611 //       }
2612 //     },
2613 //     "required": [ "body" ]
2614 //   }]
2615 // }
2616 void request_variables(const llvm::json::Object &request) {
2617   llvm::json::Object response;
2618   FillResponse(request, response);
2619   llvm::json::Array variables;
2620   auto arguments = request.getObject("arguments");
2621   const auto variablesReference =
2622       GetUnsigned(arguments, "variablesReference", 0);
2623   const int64_t start = GetSigned(arguments, "start", 0);
2624   const int64_t count = GetSigned(arguments, "count", 0);
2625   bool hex = false;
2626   auto format = arguments->getObject("format");
2627   if (format)
2628     hex = GetBoolean(format, "hex", false);
2629 
2630   if (VARREF_IS_SCOPE(variablesReference)) {
2631     // variablesReference is one of our scopes, not an actual variable it is
2632     // asking for the list of args, locals or globals.
2633     int64_t start_idx = 0;
2634     int64_t num_children = 0;
2635     switch (variablesReference) {
2636     case VARREF_LOCALS:
2637       start_idx = start;
2638       num_children = g_vsc.num_locals;
2639       break;
2640     case VARREF_GLOBALS:
2641       start_idx = start + g_vsc.num_locals + start;
2642       num_children = g_vsc.num_globals;
2643       break;
2644     case VARREF_REGS:
2645       start_idx = start + g_vsc.num_locals + g_vsc.num_globals;
2646       num_children = g_vsc.num_regs;
2647       break;
2648     default:
2649       break;
2650     }
2651     const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
2652     for (auto i = start_idx; i < end_idx; ++i) {
2653       lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
2654       if (!variable.IsValid())
2655         break;
2656       variables.emplace_back(
2657           CreateVariable(variable, VARIDX_TO_VARREF(i), i, hex));
2658     }
2659   } else {
2660     // We are expanding a variable that has children, so we will return its
2661     // children.
2662     const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
2663     lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(var_idx);
2664     if (variable.IsValid()) {
2665       const auto num_children = variable.GetNumChildren();
2666       const int64_t end_idx = start + ((count == 0) ? num_children : count);
2667       for (auto i = start; i < end_idx; ++i) {
2668         lldb::SBValue child = variable.GetChildAtIndex(i);
2669         if (!child.IsValid())
2670           break;
2671         if (child.MightHaveChildren()) {
2672           const int64_t var_idx = g_vsc.variables.GetSize();
2673           auto childVariablesReferences = VARIDX_TO_VARREF(var_idx);
2674           variables.emplace_back(
2675               CreateVariable(child, childVariablesReferences, var_idx, hex));
2676           g_vsc.variables.Append(child);
2677         } else {
2678           variables.emplace_back(CreateVariable(child, 0, INT64_MAX, hex));
2679         }
2680       }
2681     }
2682   }
2683   llvm::json::Object body;
2684   body.try_emplace("variables", std::move(variables));
2685   response.try_emplace("body", std::move(body));
2686   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2687 }
2688 
2689 // A request used in testing to get the details on all breakpoints that are
2690 // currently set in the target. This helps us to test "setBreakpoints" and
2691 // "setFunctionBreakpoints" requests to verify we have the correct set of
2692 // breakpoints currently set in LLDB.
2693 void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
2694   llvm::json::Object response;
2695   FillResponse(request, response);
2696   llvm::json::Array response_breakpoints;
2697   for (uint32_t i = 0; g_vsc.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
2698     auto bp = g_vsc.target.GetBreakpointAtIndex(i);
2699     AppendBreakpoint(bp, response_breakpoints);
2700   }
2701   llvm::json::Object body;
2702   body.try_emplace("breakpoints", std::move(response_breakpoints));
2703   response.try_emplace("body", std::move(body));
2704   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2705 }
2706 
2707 const std::map<std::string, RequestCallback> &GetRequestHandlers() {
2708 #define REQUEST_CALLBACK(name)                                                 \
2709   { #name, request_##name }
2710   static std::map<std::string, RequestCallback> g_request_handlers = {
2711       // VSCode Debug Adaptor requests
2712       REQUEST_CALLBACK(attach),
2713       REQUEST_CALLBACK(completions),
2714       REQUEST_CALLBACK(continue),
2715       REQUEST_CALLBACK(configurationDone),
2716       REQUEST_CALLBACK(disconnect),
2717       REQUEST_CALLBACK(evaluate),
2718       REQUEST_CALLBACK(exceptionInfo),
2719       REQUEST_CALLBACK(initialize),
2720       REQUEST_CALLBACK(launch),
2721       REQUEST_CALLBACK(next),
2722       REQUEST_CALLBACK(pause),
2723       REQUEST_CALLBACK(scopes),
2724       REQUEST_CALLBACK(setBreakpoints),
2725       REQUEST_CALLBACK(setExceptionBreakpoints),
2726       REQUEST_CALLBACK(setFunctionBreakpoints),
2727       REQUEST_CALLBACK(setVariable),
2728       REQUEST_CALLBACK(source),
2729       REQUEST_CALLBACK(stackTrace),
2730       REQUEST_CALLBACK(stepIn),
2731       REQUEST_CALLBACK(stepOut),
2732       REQUEST_CALLBACK(threads),
2733       REQUEST_CALLBACK(variables),
2734       // Testing requests
2735       REQUEST_CALLBACK(_testGetTargetBreakpoints),
2736   };
2737 #undef REQUEST_CALLBACK
2738   return g_request_handlers;
2739 }
2740 
2741 } // anonymous namespace
2742 
2743 static void printHelp(LLDBVSCodeOptTable &table, llvm::StringRef tool_name) {
2744   std::string usage_str = tool_name.str() + "options";
2745   table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB VSCode", false);
2746 
2747   std::string examples = R"___(
2748 EXAMPLES:
2749   The debug adapter can be started in two modes.
2750 
2751   Running lldb-vscode without any arguments will start communicating with the
2752   parent over stdio. Passing a port number causes lldb-vscode to start listening
2753   for connections on that port.
2754 
2755     lldb-vscode -p <port>
2756 
2757   Passing --wait-for-debugger will pause the process at startup and wait for a
2758   debugger to attach to the process.
2759 
2760     lldb-vscode -g
2761   )___";
2762   llvm::outs() << examples;
2763 }
2764 
2765 int main(int argc, char *argv[]) {
2766 
2767   // Initialize LLDB first before we do anything.
2768   lldb::SBDebugger::Initialize();
2769 
2770   int portno = -1;
2771 
2772   LLDBVSCodeOptTable T;
2773   unsigned MAI, MAC;
2774   llvm::ArrayRef<const char *> ArgsArr = llvm::makeArrayRef(argv + 1, argc);
2775   llvm::opt::InputArgList input_args = T.ParseArgs(ArgsArr, MAI, MAC);
2776 
2777   if (input_args.hasArg(OPT_help)) {
2778     printHelp(T, llvm::sys::path::filename(argv[0]));
2779     return 0;
2780   }
2781 
2782   if (auto *arg = input_args.getLastArg(OPT_port)) {
2783     auto optarg = arg->getValue();
2784     char *remainder;
2785     portno = strtol(optarg, &remainder, 0);
2786     if (remainder == optarg || *remainder != '\0') {
2787       fprintf(stderr, "'%s' is not a valid port number.\n", optarg);
2788       exit(1);
2789     }
2790   }
2791 
2792 #if !defined(_WIN32)
2793   if (input_args.hasArg(OPT_wait_for_debugger)) {
2794     printf("Paused waiting for debugger to attach (pid = %i)...\n", getpid());
2795     pause();
2796   }
2797 #endif
2798   if (portno != -1) {
2799     printf("Listening on port %i...\n", portno);
2800     SOCKET socket_fd = AcceptConnection(portno);
2801     if (socket_fd >= 0) {
2802       g_vsc.input.descriptor = StreamDescriptor::from_socket(socket_fd, true);
2803       g_vsc.output.descriptor = StreamDescriptor::from_socket(socket_fd, false);
2804     } else {
2805       exit(1);
2806     }
2807   } else {
2808     g_vsc.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false);
2809     g_vsc.output.descriptor =
2810         StreamDescriptor::from_file(fileno(stdout), false);
2811   }
2812   auto request_handlers = GetRequestHandlers();
2813   uint32_t packet_idx = 0;
2814   while (!g_vsc.sent_terminated_event) {
2815     std::string json = g_vsc.ReadJSON();
2816     if (json.empty())
2817       break;
2818 
2819     llvm::StringRef json_sref(json);
2820     llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
2821     if (!json_value) {
2822       auto error = json_value.takeError();
2823       if (g_vsc.log) {
2824         std::string error_str;
2825         llvm::raw_string_ostream strm(error_str);
2826         strm << error;
2827         strm.flush();
2828 
2829         *g_vsc.log << "error: failed to parse JSON: " << error_str << std::endl
2830                    << json << std::endl;
2831       }
2832       return 1;
2833     }
2834 
2835     auto object = json_value->getAsObject();
2836     if (!object) {
2837       if (g_vsc.log)
2838         *g_vsc.log << "error: json packet isn't a object" << std::endl;
2839       return 1;
2840     }
2841 
2842     const auto packet_type = GetString(object, "type");
2843     if (packet_type == "request") {
2844       const auto command = GetString(object, "command");
2845       auto handler_pos = request_handlers.find(std::string(command));
2846       if (handler_pos != request_handlers.end()) {
2847         handler_pos->second(*object);
2848       } else {
2849         if (g_vsc.log)
2850           *g_vsc.log << "error: unhandled command \"" << command.data() << std::endl;
2851         return 1;
2852       }
2853     }
2854     ++packet_idx;
2855   }
2856 
2857   // We must terminate the debugger in a thread before the C++ destructor
2858   // chain messes everything up.
2859   lldb::SBDebugger::Terminate();
2860   return 0;
2861 }
2862