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