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