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