xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-vscode/lldb-vscode.cpp (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
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 = 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     EmplaceSafeString(item, "text", match);
957     if (description.empty())
958       EmplaceSafeString(item, "label", match);
959     else
960       EmplaceSafeString(item, "label", match + " -- " + description);
961 
962     targets.emplace_back(std::move(item));
963   }
964 
965   body.try_emplace("targets", std::move(targets));
966   response.try_emplace("body", std::move(body));
967   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
968 }
969 
970 //  "EvaluateRequest": {
971 //    "allOf": [ { "$ref": "#/definitions/Request" }, {
972 //      "type": "object",
973 //      "description": "Evaluate request; value of command field is 'evaluate'.
974 //                      Evaluates the given expression in the context of the
975 //                      top most stack frame. The expression has access to any
976 //                      variables and arguments that are in scope.",
977 //      "properties": {
978 //        "command": {
979 //          "type": "string",
980 //          "enum": [ "evaluate" ]
981 //        },
982 //        "arguments": {
983 //          "$ref": "#/definitions/EvaluateArguments"
984 //        }
985 //      },
986 //      "required": [ "command", "arguments"  ]
987 //    }]
988 //  },
989 //  "EvaluateArguments": {
990 //    "type": "object",
991 //    "description": "Arguments for 'evaluate' request.",
992 //    "properties": {
993 //      "expression": {
994 //        "type": "string",
995 //        "description": "The expression to evaluate."
996 //      },
997 //      "frameId": {
998 //        "type": "integer",
999 //        "description": "Evaluate the expression in the scope of this stack
1000 //                        frame. If not specified, the expression is evaluated
1001 //                        in the global scope."
1002 //      },
1003 //      "context": {
1004 //        "type": "string",
1005 //        "_enum": [ "watch", "repl", "hover" ],
1006 //        "enumDescriptions": [
1007 //          "evaluate is run in a watch.",
1008 //          "evaluate is run from REPL console.",
1009 //          "evaluate is run from a data hover."
1010 //        ],
1011 //        "description": "The context in which the evaluate request is run."
1012 //      },
1013 //      "format": {
1014 //        "$ref": "#/definitions/ValueFormat",
1015 //        "description": "Specifies details on how to format the Evaluate
1016 //                        result."
1017 //      }
1018 //    },
1019 //    "required": [ "expression" ]
1020 //  },
1021 //  "EvaluateResponse": {
1022 //    "allOf": [ { "$ref": "#/definitions/Response" }, {
1023 //      "type": "object",
1024 //      "description": "Response to 'evaluate' request.",
1025 //      "properties": {
1026 //        "body": {
1027 //          "type": "object",
1028 //          "properties": {
1029 //            "result": {
1030 //              "type": "string",
1031 //              "description": "The result of the evaluate request."
1032 //            },
1033 //            "type": {
1034 //              "type": "string",
1035 //              "description": "The optional type of the evaluate result."
1036 //            },
1037 //            "presentationHint": {
1038 //              "$ref": "#/definitions/VariablePresentationHint",
1039 //              "description": "Properties of a evaluate result that can be
1040 //                              used to determine how to render the result in
1041 //                              the UI."
1042 //            },
1043 //            "variablesReference": {
1044 //              "type": "number",
1045 //              "description": "If variablesReference is > 0, the evaluate
1046 //                              result is structured and its children can be
1047 //                              retrieved by passing variablesReference to the
1048 //                              VariablesRequest."
1049 //            },
1050 //            "namedVariables": {
1051 //              "type": "number",
1052 //              "description": "The number of named child variables. The
1053 //                              client can use this optional information to
1054 //                              present the variables in a paged UI and fetch
1055 //                              them in chunks."
1056 //            },
1057 //            "indexedVariables": {
1058 //              "type": "number",
1059 //              "description": "The number of indexed child variables. The
1060 //                              client can use this optional information to
1061 //                              present the variables in a paged UI and fetch
1062 //                              them in chunks."
1063 //            }
1064 //          },
1065 //          "required": [ "result", "variablesReference" ]
1066 //        }
1067 //      },
1068 //      "required": [ "body" ]
1069 //    }]
1070 //  }
1071 void request_evaluate(const llvm::json::Object &request) {
1072   llvm::json::Object response;
1073   FillResponse(request, response);
1074   llvm::json::Object body;
1075   auto arguments = request.getObject("arguments");
1076   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
1077   const auto expression = GetString(arguments, "expression");
1078 
1079   if (!expression.empty() && expression[0] == '`') {
1080     auto result = RunLLDBCommands(llvm::StringRef(),
1081                                      {expression.substr(1)});
1082     EmplaceSafeString(body, "result", result);
1083     body.try_emplace("variablesReference", (int64_t)0);
1084   } else {
1085     // Always try to get the answer from the local variables if possible. If
1086     // this fails, then actually evaluate an expression using the expression
1087     // parser. "frame variable" is more reliable than the expression parser in
1088     // many cases and it is faster.
1089     lldb::SBValue value = frame.GetValueForVariablePath(
1090         expression.data(), lldb::eDynamicDontRunTarget);
1091     if (value.GetError().Fail())
1092       value = frame.EvaluateExpression(expression.data());
1093     if (value.GetError().Fail()) {
1094       response["success"] = llvm::json::Value(false);
1095       // This error object must live until we're done with the pointer returned
1096       // by GetCString().
1097       lldb::SBError error = value.GetError();
1098       const char *error_cstr = error.GetCString();
1099       if (error_cstr && error_cstr[0])
1100         EmplaceSafeString(response, "message", std::string(error_cstr));
1101       else
1102         EmplaceSafeString(response, "message", "evaluate failed");
1103     } else {
1104       SetValueForKey(value, body, "result");
1105       auto value_typename = value.GetType().GetDisplayTypeName();
1106       EmplaceSafeString(body, "type", value_typename ? value_typename : NO_TYPENAME);
1107       if (value.MightHaveChildren()) {
1108         auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
1109         g_vsc.variables.Append(value);
1110         body.try_emplace("variablesReference", variablesReference);
1111       } else {
1112         body.try_emplace("variablesReference", (int64_t)0);
1113       }
1114     }
1115   }
1116   response.try_emplace("body", std::move(body));
1117   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1118 }
1119 
1120 // "InitializeRequest": {
1121 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1122 //     "type": "object",
1123 //     "description": "Initialize request; value of command field is
1124 //                     'initialize'.",
1125 //     "properties": {
1126 //       "command": {
1127 //         "type": "string",
1128 //         "enum": [ "initialize" ]
1129 //       },
1130 //       "arguments": {
1131 //         "$ref": "#/definitions/InitializeRequestArguments"
1132 //       }
1133 //     },
1134 //     "required": [ "command", "arguments" ]
1135 //   }]
1136 // },
1137 // "InitializeRequestArguments": {
1138 //   "type": "object",
1139 //   "description": "Arguments for 'initialize' request.",
1140 //   "properties": {
1141 //     "clientID": {
1142 //       "type": "string",
1143 //       "description": "The ID of the (frontend) client using this adapter."
1144 //     },
1145 //     "adapterID": {
1146 //       "type": "string",
1147 //       "description": "The ID of the debug adapter."
1148 //     },
1149 //     "locale": {
1150 //       "type": "string",
1151 //       "description": "The ISO-639 locale of the (frontend) client using
1152 //                       this adapter, e.g. en-US or de-CH."
1153 //     },
1154 //     "linesStartAt1": {
1155 //       "type": "boolean",
1156 //       "description": "If true all line numbers are 1-based (default)."
1157 //     },
1158 //     "columnsStartAt1": {
1159 //       "type": "boolean",
1160 //       "description": "If true all column numbers are 1-based (default)."
1161 //     },
1162 //     "pathFormat": {
1163 //       "type": "string",
1164 //       "_enum": [ "path", "uri" ],
1165 //       "description": "Determines in what format paths are specified. The
1166 //                       default is 'path', which is the native format."
1167 //     },
1168 //     "supportsVariableType": {
1169 //       "type": "boolean",
1170 //       "description": "Client supports the optional type attribute for
1171 //                       variables."
1172 //     },
1173 //     "supportsVariablePaging": {
1174 //       "type": "boolean",
1175 //       "description": "Client supports the paging of variables."
1176 //     },
1177 //     "supportsRunInTerminalRequest": {
1178 //       "type": "boolean",
1179 //       "description": "Client supports the runInTerminal request."
1180 //     }
1181 //   },
1182 //   "required": [ "adapterID" ]
1183 // },
1184 // "InitializeResponse": {
1185 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1186 //     "type": "object",
1187 //     "description": "Response to 'initialize' request.",
1188 //     "properties": {
1189 //       "body": {
1190 //         "$ref": "#/definitions/Capabilities",
1191 //         "description": "The capabilities of this debug adapter."
1192 //       }
1193 //     }
1194 //   }]
1195 // }
1196 void request_initialize(const llvm::json::Object &request) {
1197   g_vsc.debugger = lldb::SBDebugger::Create(true /*source_init_files*/);
1198   // Create an empty target right away since we might get breakpoint requests
1199   // before we are given an executable to launch in a "launch" request, or a
1200   // executable when attaching to a process by process ID in a "attach"
1201   // request.
1202   FILE *out = llvm::sys::RetryAfterSignal(nullptr, fopen, dev_null_path, "w");
1203   if (out) {
1204     // Set the output and error file handles to redirect into nothing otherwise
1205     // if any code in LLDB prints to the debugger file handles, the output and
1206     // error file handles are initialized to STDOUT and STDERR and any output
1207     // will kill our debug session.
1208     g_vsc.debugger.SetOutputFileHandle(out, true);
1209     g_vsc.debugger.SetErrorFileHandle(out, false);
1210   }
1211 
1212   g_vsc.target = g_vsc.debugger.CreateTarget(nullptr);
1213   lldb::SBListener listener = g_vsc.debugger.GetListener();
1214   listener.StartListeningForEvents(
1215       g_vsc.target.GetBroadcaster(),
1216       lldb::SBTarget::eBroadcastBitBreakpointChanged);
1217   listener.StartListeningForEvents(g_vsc.broadcaster,
1218                                    eBroadcastBitStopEventThread);
1219   // Start our event thread so we can receive events from the debugger, target,
1220   // process and more.
1221   g_vsc.event_thread = std::thread(EventThreadFunction);
1222 
1223   llvm::json::Object response;
1224   FillResponse(request, response);
1225   llvm::json::Object body;
1226   // The debug adapter supports the configurationDoneRequest.
1227   body.try_emplace("supportsConfigurationDoneRequest", true);
1228   // The debug adapter supports function breakpoints.
1229   body.try_emplace("supportsFunctionBreakpoints", true);
1230   // The debug adapter supports conditional breakpoints.
1231   body.try_emplace("supportsConditionalBreakpoints", true);
1232   // The debug adapter supports breakpoints that break execution after a
1233   // specified number of hits.
1234   body.try_emplace("supportsHitConditionalBreakpoints", true);
1235   // The debug adapter supports a (side effect free) evaluate request for
1236   // data hovers.
1237   body.try_emplace("supportsEvaluateForHovers", true);
1238   // Available filters or options for the setExceptionBreakpoints request.
1239   llvm::json::Array filters;
1240   for (const auto &exc_bp : g_vsc.exception_breakpoints) {
1241     filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
1242   }
1243   body.try_emplace("exceptionBreakpointFilters", std::move(filters));
1244   // The debug adapter supports stepping back via the stepBack and
1245   // reverseContinue requests.
1246   body.try_emplace("supportsStepBack", false);
1247   // The debug adapter supports setting a variable to a value.
1248   body.try_emplace("supportsSetVariable", true);
1249   // The debug adapter supports restarting a frame.
1250   body.try_emplace("supportsRestartFrame", false);
1251   // The debug adapter supports the gotoTargetsRequest.
1252   body.try_emplace("supportsGotoTargetsRequest", false);
1253   // The debug adapter supports the stepInTargetsRequest.
1254   body.try_emplace("supportsStepInTargetsRequest", false);
1255   // The debug adapter supports the completionsRequest.
1256   body.try_emplace("supportsCompletionsRequest", true);
1257   // The debug adapter supports the modules request.
1258   body.try_emplace("supportsModulesRequest", false);
1259   // The set of additional module information exposed by the debug adapter.
1260   //   body.try_emplace("additionalModuleColumns"] = ColumnDescriptor
1261   // Checksum algorithms supported by the debug adapter.
1262   //   body.try_emplace("supportedChecksumAlgorithms"] = ChecksumAlgorithm
1263   // The debug adapter supports the RestartRequest. In this case a client
1264   // should not implement 'restart' by terminating and relaunching the adapter
1265   // but by calling the RestartRequest.
1266   body.try_emplace("supportsRestartRequest", false);
1267   // The debug adapter supports 'exceptionOptions' on the
1268   // setExceptionBreakpoints request.
1269   body.try_emplace("supportsExceptionOptions", true);
1270   // The debug adapter supports a 'format' attribute on the stackTraceRequest,
1271   // variablesRequest, and evaluateRequest.
1272   body.try_emplace("supportsValueFormattingOptions", true);
1273   // The debug adapter supports the exceptionInfo request.
1274   body.try_emplace("supportsExceptionInfoRequest", true);
1275   // The debug adapter supports the 'terminateDebuggee' attribute on the
1276   // 'disconnect' request.
1277   body.try_emplace("supportTerminateDebuggee", true);
1278   // The debug adapter supports the delayed loading of parts of the stack,
1279   // which requires that both the 'startFrame' and 'levels' arguments and the
1280   // 'totalFrames' result of the 'StackTrace' request are supported.
1281   body.try_emplace("supportsDelayedStackTraceLoading", true);
1282   // The debug adapter supports the 'loadedSources' request.
1283   body.try_emplace("supportsLoadedSourcesRequest", false);
1284 
1285   response.try_emplace("body", std::move(body));
1286   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1287 }
1288 
1289 // "LaunchRequest": {
1290 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1291 //     "type": "object",
1292 //     "description": "Launch request; value of command field is 'launch'.",
1293 //     "properties": {
1294 //       "command": {
1295 //         "type": "string",
1296 //         "enum": [ "launch" ]
1297 //       },
1298 //       "arguments": {
1299 //         "$ref": "#/definitions/LaunchRequestArguments"
1300 //       }
1301 //     },
1302 //     "required": [ "command", "arguments"  ]
1303 //   }]
1304 // },
1305 // "LaunchRequestArguments": {
1306 //   "type": "object",
1307 //   "description": "Arguments for 'launch' request.",
1308 //   "properties": {
1309 //     "noDebug": {
1310 //       "type": "boolean",
1311 //       "description": "If noDebug is true the launch request should launch
1312 //                       the program without enabling debugging."
1313 //     }
1314 //   }
1315 // },
1316 // "LaunchResponse": {
1317 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1318 //     "type": "object",
1319 //     "description": "Response to 'launch' request. This is just an
1320 //                     acknowledgement, so no body field is required."
1321 //   }]
1322 // }
1323 void request_launch(const llvm::json::Object &request) {
1324   llvm::json::Object response;
1325   lldb::SBError error;
1326   FillResponse(request, response);
1327   auto arguments = request.getObject("arguments");
1328   g_vsc.init_commands = GetStrings(arguments, "initCommands");
1329   g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
1330   g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
1331   g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
1332   auto launchCommands = GetStrings(arguments, "launchCommands");
1333   g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
1334   const auto debuggerRoot = GetString(arguments, "debuggerRoot");
1335 
1336   // This is a hack for loading DWARF in .o files on Mac where the .o files
1337   // in the debug map of the main executable have relative paths which require
1338   // the lldb-vscode binary to have its working directory set to that relative
1339   // root for the .o files in order to be able to load debug info.
1340   if (!debuggerRoot.empty()) {
1341     llvm::sys::fs::set_current_path(debuggerRoot.data());
1342   }
1343 
1344   SetSourceMapFromArguments(*arguments);
1345 
1346   // Run any initialize LLDB commands the user specified in the launch.json
1347   g_vsc.RunInitCommands();
1348 
1349   // Grab the current working directory if there is one and set it in the
1350   // launch info.
1351   const auto cwd = GetString(arguments, "cwd");
1352   if (!cwd.empty())
1353     g_vsc.launch_info.SetWorkingDirectory(cwd.data());
1354 
1355   // Grab the name of the program we need to debug and set it as the first
1356   // argument that will be passed to the program we will debug.
1357   llvm::StringRef program = GetString(arguments, "program");
1358   if (!program.empty()) {
1359     lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
1360     g_vsc.launch_info.SetExecutableFile(program_fspec,
1361                                         true /*add_as_first_arg*/);
1362     const char *target_triple = nullptr;
1363     const char *uuid_cstr = nullptr;
1364     // Stand alone debug info file if different from executable
1365     const char *symfile = nullptr;
1366     lldb::SBModule module = g_vsc.target.AddModule(
1367         program.data(), target_triple, uuid_cstr, symfile);
1368     if (!module.IsValid()) {
1369       response["success"] = llvm::json::Value(false);
1370 
1371       EmplaceSafeString(
1372           response, "message",
1373           llvm::formatv("Could not load program '{0}'.", program).str());
1374       g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1375       return;
1376     }
1377   }
1378 
1379   // Extract any extra arguments and append them to our program arguments for
1380   // when we launch
1381   auto args = GetStrings(arguments, "args");
1382   if (!args.empty())
1383     g_vsc.launch_info.SetArguments(MakeArgv(args).data(), true);
1384 
1385   // Pass any environment variables along that the user specified.
1386   auto envs = GetStrings(arguments, "env");
1387   if (!envs.empty())
1388     g_vsc.launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
1389 
1390   auto flags = g_vsc.launch_info.GetLaunchFlags();
1391 
1392   if (GetBoolean(arguments, "disableASLR", true))
1393     flags |= lldb::eLaunchFlagDisableASLR;
1394   if (GetBoolean(arguments, "disableSTDIO", false))
1395     flags |= lldb::eLaunchFlagDisableSTDIO;
1396   if (GetBoolean(arguments, "shellExpandArguments", false))
1397     flags |= lldb::eLaunchFlagShellExpandArguments;
1398   const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
1399   g_vsc.launch_info.SetDetachOnError(detatchOnError);
1400   g_vsc.launch_info.SetLaunchFlags(flags | lldb::eLaunchFlagDebug |
1401                                    lldb::eLaunchFlagStopAtEntry);
1402 
1403   // Run any pre run LLDB commands the user specified in the launch.json
1404   g_vsc.RunPreRunCommands();
1405   if (launchCommands.empty()) {
1406     // Disable async events so the launch will be successful when we return from
1407     // the launch call and the launch will happen synchronously
1408     g_vsc.debugger.SetAsync(false);
1409     g_vsc.target.Launch(g_vsc.launch_info, error);
1410     g_vsc.debugger.SetAsync(true);
1411   } else {
1412     g_vsc.RunLLDBCommands("Running launchCommands:", launchCommands);
1413     // The custom commands might have created a new target so we should use the
1414     // selected target after these commands are run.
1415     g_vsc.target = g_vsc.debugger.GetSelectedTarget();
1416   }
1417 
1418   if (error.Fail()) {
1419     response["success"] = llvm::json::Value(false);
1420     EmplaceSafeString(response, "message", std::string(error.GetCString()));
1421   }
1422   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1423 
1424   SendProcessEvent(Launch);
1425   g_vsc.SendJSON(llvm::json::Value(CreateEventObject("initialized")));
1426   // Reenable async events and start the event thread to catch async events.
1427   // g_vsc.debugger.SetAsync(true);
1428 }
1429 
1430 // "NextRequest": {
1431 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1432 //     "type": "object",
1433 //     "description": "Next request; value of command field is 'next'. The
1434 //                     request starts the debuggee to run again for one step.
1435 //                     The debug adapter first sends the NextResponse and then
1436 //                     a StoppedEvent (event type 'step') after the step has
1437 //                     completed.",
1438 //     "properties": {
1439 //       "command": {
1440 //         "type": "string",
1441 //         "enum": [ "next" ]
1442 //       },
1443 //       "arguments": {
1444 //         "$ref": "#/definitions/NextArguments"
1445 //       }
1446 //     },
1447 //     "required": [ "command", "arguments"  ]
1448 //   }]
1449 // },
1450 // "NextArguments": {
1451 //   "type": "object",
1452 //   "description": "Arguments for 'next' request.",
1453 //   "properties": {
1454 //     "threadId": {
1455 //       "type": "integer",
1456 //       "description": "Execute 'next' for this thread."
1457 //     }
1458 //   },
1459 //   "required": [ "threadId" ]
1460 // },
1461 // "NextResponse": {
1462 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1463 //     "type": "object",
1464 //     "description": "Response to 'next' request. This is just an
1465 //                     acknowledgement, so no body field is required."
1466 //   }]
1467 // }
1468 void request_next(const llvm::json::Object &request) {
1469   llvm::json::Object response;
1470   FillResponse(request, response);
1471   auto arguments = request.getObject("arguments");
1472   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
1473   if (thread.IsValid()) {
1474     // Remember the thread ID that caused the resume so we can set the
1475     // "threadCausedFocus" boolean value in the "stopped" events.
1476     g_vsc.focus_tid = thread.GetThreadID();
1477     thread.StepOver();
1478   } else {
1479     response["success"] = llvm::json::Value(false);
1480   }
1481   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1482 }
1483 
1484 // "PauseRequest": {
1485 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1486 //     "type": "object",
1487 //     "description": "Pause request; value of command field is 'pause'. The
1488 //     request suspenses the debuggee. The debug adapter first sends the
1489 //     PauseResponse and then a StoppedEvent (event type 'pause') after the
1490 //     thread has been paused successfully.", "properties": {
1491 //       "command": {
1492 //         "type": "string",
1493 //         "enum": [ "pause" ]
1494 //       },
1495 //       "arguments": {
1496 //         "$ref": "#/definitions/PauseArguments"
1497 //       }
1498 //     },
1499 //     "required": [ "command", "arguments"  ]
1500 //   }]
1501 // },
1502 // "PauseArguments": {
1503 //   "type": "object",
1504 //   "description": "Arguments for 'pause' request.",
1505 //   "properties": {
1506 //     "threadId": {
1507 //       "type": "integer",
1508 //       "description": "Pause execution for this thread."
1509 //     }
1510 //   },
1511 //   "required": [ "threadId" ]
1512 // },
1513 // "PauseResponse": {
1514 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1515 //     "type": "object",
1516 //     "description": "Response to 'pause' request. This is just an
1517 //     acknowledgement, so no body field is required."
1518 //   }]
1519 // }
1520 void request_pause(const llvm::json::Object &request) {
1521   llvm::json::Object response;
1522   FillResponse(request, response);
1523   lldb::SBProcess process = g_vsc.target.GetProcess();
1524   lldb::SBError error = process.Stop();
1525   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1526 }
1527 
1528 // "ScopesRequest": {
1529 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1530 //     "type": "object",
1531 //     "description": "Scopes request; value of command field is 'scopes'. The
1532 //     request returns the variable scopes for a given stackframe ID.",
1533 //     "properties": {
1534 //       "command": {
1535 //         "type": "string",
1536 //         "enum": [ "scopes" ]
1537 //       },
1538 //       "arguments": {
1539 //         "$ref": "#/definitions/ScopesArguments"
1540 //       }
1541 //     },
1542 //     "required": [ "command", "arguments"  ]
1543 //   }]
1544 // },
1545 // "ScopesArguments": {
1546 //   "type": "object",
1547 //   "description": "Arguments for 'scopes' request.",
1548 //   "properties": {
1549 //     "frameId": {
1550 //       "type": "integer",
1551 //       "description": "Retrieve the scopes for this stackframe."
1552 //     }
1553 //   },
1554 //   "required": [ "frameId" ]
1555 // },
1556 // "ScopesResponse": {
1557 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1558 //     "type": "object",
1559 //     "description": "Response to 'scopes' request.",
1560 //     "properties": {
1561 //       "body": {
1562 //         "type": "object",
1563 //         "properties": {
1564 //           "scopes": {
1565 //             "type": "array",
1566 //             "items": {
1567 //               "$ref": "#/definitions/Scope"
1568 //             },
1569 //             "description": "The scopes of the stackframe. If the array has
1570 //             length zero, there are no scopes available."
1571 //           }
1572 //         },
1573 //         "required": [ "scopes" ]
1574 //       }
1575 //     },
1576 //     "required": [ "body" ]
1577 //   }]
1578 // }
1579 void request_scopes(const llvm::json::Object &request) {
1580   llvm::json::Object response;
1581   FillResponse(request, response);
1582   llvm::json::Object body;
1583   auto arguments = request.getObject("arguments");
1584   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
1585   g_vsc.variables.Clear();
1586   g_vsc.variables.Append(frame.GetVariables(true,   // arguments
1587                                             true,   // locals
1588                                             false,  // statics
1589                                             true)); // in_scope_only
1590   g_vsc.num_locals = g_vsc.variables.GetSize();
1591   g_vsc.variables.Append(frame.GetVariables(false,  // arguments
1592                                             false,  // locals
1593                                             true,   // statics
1594                                             true)); // in_scope_only
1595   g_vsc.num_globals = g_vsc.variables.GetSize() - (g_vsc.num_locals);
1596   g_vsc.variables.Append(frame.GetRegisters());
1597   g_vsc.num_regs =
1598       g_vsc.variables.GetSize() - (g_vsc.num_locals + g_vsc.num_globals);
1599   body.try_emplace("scopes", g_vsc.CreateTopLevelScopes());
1600   response.try_emplace("body", std::move(body));
1601   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1602 }
1603 
1604 // "SetBreakpointsRequest": {
1605 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1606 //     "type": "object",
1607 //     "description": "SetBreakpoints request; value of command field is
1608 //     'setBreakpoints'. Sets multiple breakpoints for a single source and
1609 //     clears all previous breakpoints in that source. To clear all breakpoint
1610 //     for a source, specify an empty array. When a breakpoint is hit, a
1611 //     StoppedEvent (event type 'breakpoint') is generated.", "properties": {
1612 //       "command": {
1613 //         "type": "string",
1614 //         "enum": [ "setBreakpoints" ]
1615 //       },
1616 //       "arguments": {
1617 //         "$ref": "#/definitions/SetBreakpointsArguments"
1618 //       }
1619 //     },
1620 //     "required": [ "command", "arguments"  ]
1621 //   }]
1622 // },
1623 // "SetBreakpointsArguments": {
1624 //   "type": "object",
1625 //   "description": "Arguments for 'setBreakpoints' request.",
1626 //   "properties": {
1627 //     "source": {
1628 //       "$ref": "#/definitions/Source",
1629 //       "description": "The source location of the breakpoints; either
1630 //       source.path or source.reference must be specified."
1631 //     },
1632 //     "breakpoints": {
1633 //       "type": "array",
1634 //       "items": {
1635 //         "$ref": "#/definitions/SourceBreakpoint"
1636 //       },
1637 //       "description": "The code locations of the breakpoints."
1638 //     },
1639 //     "lines": {
1640 //       "type": "array",
1641 //       "items": {
1642 //         "type": "integer"
1643 //       },
1644 //       "description": "Deprecated: The code locations of the breakpoints."
1645 //     },
1646 //     "sourceModified": {
1647 //       "type": "boolean",
1648 //       "description": "A value of true indicates that the underlying source
1649 //       has been modified which results in new breakpoint locations."
1650 //     }
1651 //   },
1652 //   "required": [ "source" ]
1653 // },
1654 // "SetBreakpointsResponse": {
1655 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1656 //     "type": "object",
1657 //     "description": "Response to 'setBreakpoints' request. Returned is
1658 //     information about each breakpoint created by this request. This includes
1659 //     the actual code location and whether the breakpoint could be verified.
1660 //     The breakpoints returned are in the same order as the elements of the
1661 //     'breakpoints' (or the deprecated 'lines') in the
1662 //     SetBreakpointsArguments.", "properties": {
1663 //       "body": {
1664 //         "type": "object",
1665 //         "properties": {
1666 //           "breakpoints": {
1667 //             "type": "array",
1668 //             "items": {
1669 //               "$ref": "#/definitions/Breakpoint"
1670 //             },
1671 //             "description": "Information about the breakpoints. The array
1672 //             elements are in the same order as the elements of the
1673 //             'breakpoints' (or the deprecated 'lines') in the
1674 //             SetBreakpointsArguments."
1675 //           }
1676 //         },
1677 //         "required": [ "breakpoints" ]
1678 //       }
1679 //     },
1680 //     "required": [ "body" ]
1681 //   }]
1682 // },
1683 // "SourceBreakpoint": {
1684 //   "type": "object",
1685 //   "description": "Properties of a breakpoint or logpoint passed to the
1686 //   setBreakpoints request.", "properties": {
1687 //     "line": {
1688 //       "type": "integer",
1689 //       "description": "The source line of the breakpoint or logpoint."
1690 //     },
1691 //     "column": {
1692 //       "type": "integer",
1693 //       "description": "An optional source column of the breakpoint."
1694 //     },
1695 //     "condition": {
1696 //       "type": "string",
1697 //       "description": "An optional expression for conditional breakpoints."
1698 //     },
1699 //     "hitCondition": {
1700 //       "type": "string",
1701 //       "description": "An optional expression that controls how many hits of
1702 //       the breakpoint are ignored. The backend is expected to interpret the
1703 //       expression as needed."
1704 //     },
1705 //     "logMessage": {
1706 //       "type": "string",
1707 //       "description": "If this attribute exists and is non-empty, the backend
1708 //       must not 'break' (stop) but log the message instead. Expressions within
1709 //       {} are interpolated."
1710 //     }
1711 //   },
1712 //   "required": [ "line" ]
1713 // }
1714 void request_setBreakpoints(const llvm::json::Object &request) {
1715   llvm::json::Object response;
1716   lldb::SBError error;
1717   FillResponse(request, response);
1718   auto arguments = request.getObject("arguments");
1719   auto source = arguments->getObject("source");
1720   const auto path = GetString(source, "path");
1721   auto breakpoints = arguments->getArray("breakpoints");
1722   llvm::json::Array response_breakpoints;
1723   // Decode the source breakpoint infos for this "setBreakpoints" request
1724   SourceBreakpointMap request_bps;
1725   for (const auto &bp : *breakpoints) {
1726     auto bp_obj = bp.getAsObject();
1727     if (bp_obj) {
1728       SourceBreakpoint src_bp(*bp_obj);
1729       request_bps[src_bp.line] = std::move(src_bp);
1730     }
1731   }
1732 
1733   // See if we already have breakpoints set for this source file from a
1734   // previous "setBreakpoints" request
1735   auto old_src_bp_pos = g_vsc.source_breakpoints.find(path);
1736   if (old_src_bp_pos != g_vsc.source_breakpoints.end()) {
1737 
1738     // We have already set breakpoints in this source file and they are giving
1739     // use a new list of lines to set breakpoints on. Some breakpoints might
1740     // already be set, and some might not. We need to remove any breakpoints
1741     // whose lines are not contained in the any breakpoints lines in in the
1742     // "breakpoints" array.
1743 
1744     // Delete any breakpoints in this source file that aren't in the
1745     // request_bps set. There is no call to remove breakpoints other than
1746     // calling this function with a smaller or empty "breakpoints" list.
1747     std::vector<uint32_t> remove_lines;
1748     for (auto &pair: old_src_bp_pos->second) {
1749       auto request_pos = request_bps.find(pair.first);
1750       if (request_pos == request_bps.end()) {
1751         // This breakpoint no longer exists in this source file, delete it
1752         g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
1753         remove_lines.push_back(pair.first);
1754       } else {
1755         pair.second.UpdateBreakpoint(request_pos->second);
1756         // Remove this breakpoint from the request breakpoints since we have
1757         // handled it here and we don't need to set a new breakpoint below.
1758         request_bps.erase(request_pos);
1759         // Add this breakpoint info to the response
1760         AppendBreakpoint(pair.second.bp, response_breakpoints);
1761       }
1762     }
1763     // Remove any lines from this existing source breakpoint map
1764     for (auto line: remove_lines)
1765      old_src_bp_pos->second.erase(line);
1766 
1767     // Now add any breakpoint infos left over in request_bps are the
1768     // breakpoints that weren't set in this source file yet. We need to update
1769     // thread source breakpoint info for the source file in the variable
1770     // "old_src_bp_pos->second" so the info for this source file is up to date.
1771     for (auto &pair : request_bps) {
1772       pair.second.SetBreakpoint(path.data());
1773       // Add this breakpoint info to the response
1774       AppendBreakpoint(pair.second.bp, response_breakpoints);
1775       old_src_bp_pos->second[pair.first] = std::move(pair.second);
1776     }
1777   } else {
1778     // No breakpoints were set for this source file yet. Set all breakpoints
1779     // for each line and add them to the response and create an entry in
1780     // g_vsc.source_breakpoints for this source file.
1781     for (auto &pair : request_bps) {
1782       pair.second.SetBreakpoint(path.data());
1783       // Add this breakpoint info to the response
1784       AppendBreakpoint(pair.second.bp, response_breakpoints);
1785     }
1786     g_vsc.source_breakpoints[path] = std::move(request_bps);
1787   }
1788 
1789   llvm::json::Object body;
1790   body.try_emplace("breakpoints", std::move(response_breakpoints));
1791   response.try_emplace("body", std::move(body));
1792   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1793 }
1794 
1795 // "SetExceptionBreakpointsRequest": {
1796 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1797 //     "type": "object",
1798 //     "description": "SetExceptionBreakpoints request; value of command field
1799 //     is 'setExceptionBreakpoints'. The request configures the debuggers
1800 //     response to thrown exceptions. If an exception is configured to break, a
1801 //     StoppedEvent is fired (event type 'exception').", "properties": {
1802 //       "command": {
1803 //         "type": "string",
1804 //         "enum": [ "setExceptionBreakpoints" ]
1805 //       },
1806 //       "arguments": {
1807 //         "$ref": "#/definitions/SetExceptionBreakpointsArguments"
1808 //       }
1809 //     },
1810 //     "required": [ "command", "arguments"  ]
1811 //   }]
1812 // },
1813 // "SetExceptionBreakpointsArguments": {
1814 //   "type": "object",
1815 //   "description": "Arguments for 'setExceptionBreakpoints' request.",
1816 //   "properties": {
1817 //     "filters": {
1818 //       "type": "array",
1819 //       "items": {
1820 //         "type": "string"
1821 //       },
1822 //       "description": "IDs of checked exception options. The set of IDs is
1823 //       returned via the 'exceptionBreakpointFilters' capability."
1824 //     },
1825 //     "exceptionOptions": {
1826 //       "type": "array",
1827 //       "items": {
1828 //         "$ref": "#/definitions/ExceptionOptions"
1829 //       },
1830 //       "description": "Configuration options for selected exceptions."
1831 //     }
1832 //   },
1833 //   "required": [ "filters" ]
1834 // },
1835 // "SetExceptionBreakpointsResponse": {
1836 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1837 //     "type": "object",
1838 //     "description": "Response to 'setExceptionBreakpoints' request. This is
1839 //     just an acknowledgement, so no body field is required."
1840 //   }]
1841 // }
1842 void request_setExceptionBreakpoints(const llvm::json::Object &request) {
1843   llvm::json::Object response;
1844   lldb::SBError error;
1845   FillResponse(request, response);
1846   auto arguments = request.getObject("arguments");
1847   auto filters = arguments->getArray("filters");
1848   // Keep a list of any exception breakpoint filter names that weren't set
1849   // so we can clear any exception breakpoints if needed.
1850   std::set<std::string> unset_filters;
1851   for (const auto &bp : g_vsc.exception_breakpoints)
1852     unset_filters.insert(bp.filter);
1853 
1854   for (const auto &value : *filters) {
1855     const auto filter = GetAsString(value);
1856     auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
1857     if (exc_bp) {
1858       exc_bp->SetBreakpoint();
1859       unset_filters.erase(filter);
1860     }
1861   }
1862   for (const auto &filter : unset_filters) {
1863     auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
1864     if (exc_bp)
1865       exc_bp->ClearBreakpoint();
1866   }
1867   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
1868 }
1869 
1870 // "SetFunctionBreakpointsRequest": {
1871 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
1872 //     "type": "object",
1873 //     "description": "SetFunctionBreakpoints request; value of command field is
1874 //     'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
1875 //     all previous function breakpoints. To clear all function breakpoint,
1876 //     specify an empty array. When a function breakpoint is hit, a StoppedEvent
1877 //     (event type 'function breakpoint') is generated.", "properties": {
1878 //       "command": {
1879 //         "type": "string",
1880 //         "enum": [ "setFunctionBreakpoints" ]
1881 //       },
1882 //       "arguments": {
1883 //         "$ref": "#/definitions/SetFunctionBreakpointsArguments"
1884 //       }
1885 //     },
1886 //     "required": [ "command", "arguments"  ]
1887 //   }]
1888 // },
1889 // "SetFunctionBreakpointsArguments": {
1890 //   "type": "object",
1891 //   "description": "Arguments for 'setFunctionBreakpoints' request.",
1892 //   "properties": {
1893 //     "breakpoints": {
1894 //       "type": "array",
1895 //       "items": {
1896 //         "$ref": "#/definitions/FunctionBreakpoint"
1897 //       },
1898 //       "description": "The function names of the breakpoints."
1899 //     }
1900 //   },
1901 //   "required": [ "breakpoints" ]
1902 // },
1903 // "FunctionBreakpoint": {
1904 //   "type": "object",
1905 //   "description": "Properties of a breakpoint passed to the
1906 //   setFunctionBreakpoints request.", "properties": {
1907 //     "name": {
1908 //       "type": "string",
1909 //       "description": "The name of the function."
1910 //     },
1911 //     "condition": {
1912 //       "type": "string",
1913 //       "description": "An optional expression for conditional breakpoints."
1914 //     },
1915 //     "hitCondition": {
1916 //       "type": "string",
1917 //       "description": "An optional expression that controls how many hits of
1918 //       the breakpoint are ignored. The backend is expected to interpret the
1919 //       expression as needed."
1920 //     }
1921 //   },
1922 //   "required": [ "name" ]
1923 // },
1924 // "SetFunctionBreakpointsResponse": {
1925 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
1926 //     "type": "object",
1927 //     "description": "Response to 'setFunctionBreakpoints' request. Returned is
1928 //     information about each breakpoint created by this request.",
1929 //     "properties": {
1930 //       "body": {
1931 //         "type": "object",
1932 //         "properties": {
1933 //           "breakpoints": {
1934 //             "type": "array",
1935 //             "items": {
1936 //               "$ref": "#/definitions/Breakpoint"
1937 //             },
1938 //             "description": "Information about the breakpoints. The array
1939 //             elements correspond to the elements of the 'breakpoints' array."
1940 //           }
1941 //         },
1942 //         "required": [ "breakpoints" ]
1943 //       }
1944 //     },
1945 //     "required": [ "body" ]
1946 //   }]
1947 // }
1948 void request_setFunctionBreakpoints(const llvm::json::Object &request) {
1949   llvm::json::Object response;
1950   lldb::SBError error;
1951   FillResponse(request, response);
1952   auto arguments = request.getObject("arguments");
1953   auto breakpoints = arguments->getArray("breakpoints");
1954   FunctionBreakpointMap request_bps;
1955   llvm::json::Array response_breakpoints;
1956   for (const auto &value : *breakpoints) {
1957     auto bp_obj = value.getAsObject();
1958     if (bp_obj == nullptr)
1959       continue;
1960     FunctionBreakpoint func_bp(*bp_obj);
1961     request_bps[func_bp.functionName] = std::move(func_bp);
1962   }
1963 
1964   std::vector<llvm::StringRef> remove_names;
1965   // Disable any function breakpoints that aren't in the request_bps.
1966   // There is no call to remove function breakpoints other than calling this
1967   // function with a smaller or empty "breakpoints" list.
1968   for (auto &pair: g_vsc.function_breakpoints) {
1969     auto request_pos = request_bps.find(pair.first());
1970     if (request_pos == request_bps.end()) {
1971       // This function breakpoint no longer exists delete it from LLDB
1972       g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
1973       remove_names.push_back(pair.first());
1974     } else {
1975       // Update the existing breakpoint as any setting withing the function
1976       // breakpoint might have changed.
1977       pair.second.UpdateBreakpoint(request_pos->second);
1978       // Remove this breakpoint from the request breakpoints since we have
1979       // handled it here and we don't need to set a new breakpoint below.
1980       request_bps.erase(request_pos);
1981       // Add this breakpoint info to the response
1982       AppendBreakpoint(pair.second.bp, response_breakpoints);
1983     }
1984   }
1985   // Remove any breakpoints that are no longer in our list
1986   for (const auto &name: remove_names)
1987     g_vsc.function_breakpoints.erase(name);
1988 
1989   // Any breakpoints that are left in "request_bps" are breakpoints that
1990   // need to be set.
1991   for (auto &pair : request_bps) {
1992     pair.second.SetBreakpoint();
1993     // Add this breakpoint info to the response
1994     AppendBreakpoint(pair.second.bp, response_breakpoints);
1995     g_vsc.function_breakpoints[pair.first()] = std::move(pair.second);
1996   }
1997 
1998   llvm::json::Object body;
1999   body.try_emplace("breakpoints", std::move(response_breakpoints));
2000   response.try_emplace("body", std::move(body));
2001   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2002 }
2003 
2004 // "SourceRequest": {
2005 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2006 //     "type": "object",
2007 //     "description": "Source request; value of command field is 'source'. The
2008 //     request retrieves the source code for a given source reference.",
2009 //     "properties": {
2010 //       "command": {
2011 //         "type": "string",
2012 //         "enum": [ "source" ]
2013 //       },
2014 //       "arguments": {
2015 //         "$ref": "#/definitions/SourceArguments"
2016 //       }
2017 //     },
2018 //     "required": [ "command", "arguments"  ]
2019 //   }]
2020 // },
2021 // "SourceArguments": {
2022 //   "type": "object",
2023 //   "description": "Arguments for 'source' request.",
2024 //   "properties": {
2025 //     "source": {
2026 //       "$ref": "#/definitions/Source",
2027 //       "description": "Specifies the source content to load. Either
2028 //       source.path or source.sourceReference must be specified."
2029 //     },
2030 //     "sourceReference": {
2031 //       "type": "integer",
2032 //       "description": "The reference to the source. This is the same as
2033 //       source.sourceReference. This is provided for backward compatibility
2034 //       since old backends do not understand the 'source' attribute."
2035 //     }
2036 //   },
2037 //   "required": [ "sourceReference" ]
2038 // },
2039 // "SourceResponse": {
2040 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2041 //     "type": "object",
2042 //     "description": "Response to 'source' request.",
2043 //     "properties": {
2044 //       "body": {
2045 //         "type": "object",
2046 //         "properties": {
2047 //           "content": {
2048 //             "type": "string",
2049 //             "description": "Content of the source reference."
2050 //           },
2051 //           "mimeType": {
2052 //             "type": "string",
2053 //             "description": "Optional content type (mime type) of the source."
2054 //           }
2055 //         },
2056 //         "required": [ "content" ]
2057 //       }
2058 //     },
2059 //     "required": [ "body" ]
2060 //   }]
2061 // }
2062 void request_source(const llvm::json::Object &request) {
2063   llvm::json::Object response;
2064   FillResponse(request, response);
2065   llvm::json::Object body;
2066 
2067   auto arguments = request.getObject("arguments");
2068   auto source = arguments->getObject("source");
2069   auto sourceReference = GetSigned(source, "sourceReference", -1);
2070   auto pos = g_vsc.source_map.find((lldb::addr_t)sourceReference);
2071   if (pos != g_vsc.source_map.end()) {
2072     EmplaceSafeString(body, "content", pos->second.content);
2073   } else {
2074     response["success"] = llvm::json::Value(false);
2075   }
2076   response.try_emplace("body", std::move(body));
2077   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2078 }
2079 
2080 // "StackTraceRequest": {
2081 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2082 //     "type": "object",
2083 //     "description": "StackTrace request; value of command field is
2084 //     'stackTrace'. The request returns a stacktrace from the current execution
2085 //     state.", "properties": {
2086 //       "command": {
2087 //         "type": "string",
2088 //         "enum": [ "stackTrace" ]
2089 //       },
2090 //       "arguments": {
2091 //         "$ref": "#/definitions/StackTraceArguments"
2092 //       }
2093 //     },
2094 //     "required": [ "command", "arguments"  ]
2095 //   }]
2096 // },
2097 // "StackTraceArguments": {
2098 //   "type": "object",
2099 //   "description": "Arguments for 'stackTrace' request.",
2100 //   "properties": {
2101 //     "threadId": {
2102 //       "type": "integer",
2103 //       "description": "Retrieve the stacktrace for this thread."
2104 //     },
2105 //     "startFrame": {
2106 //       "type": "integer",
2107 //       "description": "The index of the first frame to return; if omitted
2108 //       frames start at 0."
2109 //     },
2110 //     "levels": {
2111 //       "type": "integer",
2112 //       "description": "The maximum number of frames to return. If levels is
2113 //       not specified or 0, all frames are returned."
2114 //     },
2115 //     "format": {
2116 //       "$ref": "#/definitions/StackFrameFormat",
2117 //       "description": "Specifies details on how to format the stack frames."
2118 //     }
2119 //  },
2120 //   "required": [ "threadId" ]
2121 // },
2122 // "StackTraceResponse": {
2123 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2124 //     "type": "object",
2125 //     "description": "Response to 'stackTrace' request.",
2126 //     "properties": {
2127 //       "body": {
2128 //         "type": "object",
2129 //         "properties": {
2130 //           "stackFrames": {
2131 //             "type": "array",
2132 //             "items": {
2133 //               "$ref": "#/definitions/StackFrame"
2134 //             },
2135 //             "description": "The frames of the stackframe. If the array has
2136 //             length zero, there are no stackframes available. This means that
2137 //             there is no location information available."
2138 //           },
2139 //           "totalFrames": {
2140 //             "type": "integer",
2141 //             "description": "The total number of frames available."
2142 //           }
2143 //         },
2144 //         "required": [ "stackFrames" ]
2145 //       }
2146 //     },
2147 //     "required": [ "body" ]
2148 //   }]
2149 // }
2150 void request_stackTrace(const llvm::json::Object &request) {
2151   llvm::json::Object response;
2152   FillResponse(request, response);
2153   lldb::SBError error;
2154   auto arguments = request.getObject("arguments");
2155   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2156   llvm::json::Array stackFrames;
2157   llvm::json::Object body;
2158 
2159   if (thread.IsValid()) {
2160     const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
2161     const auto levels = GetUnsigned(arguments, "levels", 0);
2162     const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
2163     for (uint32_t i = startFrame; i < endFrame; ++i) {
2164       auto frame = thread.GetFrameAtIndex(i);
2165       if (!frame.IsValid())
2166         break;
2167       stackFrames.emplace_back(CreateStackFrame(frame));
2168     }
2169     const auto totalFrames = thread.GetNumFrames();
2170     body.try_emplace("totalFrames", totalFrames);
2171   }
2172   body.try_emplace("stackFrames", std::move(stackFrames));
2173   response.try_emplace("body", std::move(body));
2174   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2175 }
2176 
2177 // "StepInRequest": {
2178 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2179 //     "type": "object",
2180 //     "description": "StepIn request; value of command field is 'stepIn'. The
2181 //     request starts the debuggee to step into a function/method if possible.
2182 //     If it cannot step into a target, 'stepIn' behaves like 'next'. The debug
2183 //     adapter first sends the StepInResponse and then a StoppedEvent (event
2184 //     type 'step') after the step has completed. If there are multiple
2185 //     function/method calls (or other targets) on the source line, the optional
2186 //     argument 'targetId' can be used to control into which target the 'stepIn'
2187 //     should occur. The list of possible targets for a given source line can be
2188 //     retrieved via the 'stepInTargets' request.", "properties": {
2189 //       "command": {
2190 //         "type": "string",
2191 //         "enum": [ "stepIn" ]
2192 //       },
2193 //       "arguments": {
2194 //         "$ref": "#/definitions/StepInArguments"
2195 //       }
2196 //     },
2197 //     "required": [ "command", "arguments"  ]
2198 //   }]
2199 // },
2200 // "StepInArguments": {
2201 //   "type": "object",
2202 //   "description": "Arguments for 'stepIn' request.",
2203 //   "properties": {
2204 //     "threadId": {
2205 //       "type": "integer",
2206 //       "description": "Execute 'stepIn' for this thread."
2207 //     },
2208 //     "targetId": {
2209 //       "type": "integer",
2210 //       "description": "Optional id of the target to step into."
2211 //     }
2212 //   },
2213 //   "required": [ "threadId" ]
2214 // },
2215 // "StepInResponse": {
2216 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2217 //     "type": "object",
2218 //     "description": "Response to 'stepIn' request. This is just an
2219 //     acknowledgement, so no body field is required."
2220 //   }]
2221 // }
2222 void request_stepIn(const llvm::json::Object &request) {
2223   llvm::json::Object response;
2224   FillResponse(request, response);
2225   auto arguments = request.getObject("arguments");
2226   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2227   if (thread.IsValid()) {
2228     // Remember the thread ID that caused the resume so we can set the
2229     // "threadCausedFocus" boolean value in the "stopped" events.
2230     g_vsc.focus_tid = thread.GetThreadID();
2231     thread.StepInto();
2232   } else {
2233     response["success"] = llvm::json::Value(false);
2234   }
2235   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2236 }
2237 
2238 // "StepOutRequest": {
2239 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2240 //     "type": "object",
2241 //     "description": "StepOut request; value of command field is 'stepOut'. The
2242 //     request starts the debuggee to run again for one step. The debug adapter
2243 //     first sends the StepOutResponse and then a StoppedEvent (event type
2244 //     'step') after the step has completed.", "properties": {
2245 //       "command": {
2246 //         "type": "string",
2247 //         "enum": [ "stepOut" ]
2248 //       },
2249 //       "arguments": {
2250 //         "$ref": "#/definitions/StepOutArguments"
2251 //       }
2252 //     },
2253 //     "required": [ "command", "arguments"  ]
2254 //   }]
2255 // },
2256 // "StepOutArguments": {
2257 //   "type": "object",
2258 //   "description": "Arguments for 'stepOut' request.",
2259 //   "properties": {
2260 //     "threadId": {
2261 //       "type": "integer",
2262 //       "description": "Execute 'stepOut' for this thread."
2263 //     }
2264 //   },
2265 //   "required": [ "threadId" ]
2266 // },
2267 // "StepOutResponse": {
2268 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2269 //     "type": "object",
2270 //     "description": "Response to 'stepOut' request. This is just an
2271 //     acknowledgement, so no body field is required."
2272 //   }]
2273 // }
2274 void request_stepOut(const llvm::json::Object &request) {
2275   llvm::json::Object response;
2276   FillResponse(request, response);
2277   auto arguments = request.getObject("arguments");
2278   lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
2279   if (thread.IsValid()) {
2280     // Remember the thread ID that caused the resume so we can set the
2281     // "threadCausedFocus" boolean value in the "stopped" events.
2282     g_vsc.focus_tid = thread.GetThreadID();
2283     thread.StepOut();
2284   } else {
2285     response["success"] = llvm::json::Value(false);
2286   }
2287   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2288 }
2289 
2290 // "ThreadsRequest": {
2291 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2292 //     "type": "object",
2293 //     "description": "Thread request; value of command field is 'threads'. The
2294 //     request retrieves a list of all threads.", "properties": {
2295 //       "command": {
2296 //         "type": "string",
2297 //         "enum": [ "threads" ]
2298 //       }
2299 //     },
2300 //     "required": [ "command" ]
2301 //   }]
2302 // },
2303 // "ThreadsResponse": {
2304 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2305 //     "type": "object",
2306 //     "description": "Response to 'threads' request.",
2307 //     "properties": {
2308 //       "body": {
2309 //         "type": "object",
2310 //         "properties": {
2311 //           "threads": {
2312 //             "type": "array",
2313 //             "items": {
2314 //               "$ref": "#/definitions/Thread"
2315 //             },
2316 //             "description": "All threads."
2317 //           }
2318 //         },
2319 //         "required": [ "threads" ]
2320 //       }
2321 //     },
2322 //     "required": [ "body" ]
2323 //   }]
2324 // }
2325 void request_threads(const llvm::json::Object &request) {
2326 
2327   lldb::SBProcess process = g_vsc.target.GetProcess();
2328   llvm::json::Object response;
2329   FillResponse(request, response);
2330 
2331   const uint32_t num_threads = process.GetNumThreads();
2332   llvm::json::Array threads;
2333   for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
2334     lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
2335     threads.emplace_back(CreateThread(thread));
2336   }
2337   if (threads.size() == 0) {
2338     response["success"] = llvm::json::Value(false);
2339   }
2340   llvm::json::Object body;
2341   body.try_emplace("threads", std::move(threads));
2342   response.try_emplace("body", std::move(body));
2343   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2344 }
2345 
2346 // "SetVariableRequest": {
2347 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2348 //     "type": "object",
2349 //     "description": "setVariable request; value of command field is
2350 //     'setVariable'. Set the variable with the given name in the variable
2351 //     container to a new value.", "properties": {
2352 //       "command": {
2353 //         "type": "string",
2354 //         "enum": [ "setVariable" ]
2355 //       },
2356 //       "arguments": {
2357 //         "$ref": "#/definitions/SetVariableArguments"
2358 //       }
2359 //     },
2360 //     "required": [ "command", "arguments"  ]
2361 //   }]
2362 // },
2363 // "SetVariableArguments": {
2364 //   "type": "object",
2365 //   "description": "Arguments for 'setVariable' request.",
2366 //   "properties": {
2367 //     "variablesReference": {
2368 //       "type": "integer",
2369 //       "description": "The reference of the variable container."
2370 //     },
2371 //     "name": {
2372 //       "type": "string",
2373 //       "description": "The name of the variable."
2374 //     },
2375 //     "value": {
2376 //       "type": "string",
2377 //       "description": "The value of the variable."
2378 //     },
2379 //     "format": {
2380 //       "$ref": "#/definitions/ValueFormat",
2381 //       "description": "Specifies details on how to format the response value."
2382 //     }
2383 //   },
2384 //   "required": [ "variablesReference", "name", "value" ]
2385 // },
2386 // "SetVariableResponse": {
2387 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2388 //     "type": "object",
2389 //     "description": "Response to 'setVariable' request.",
2390 //     "properties": {
2391 //       "body": {
2392 //         "type": "object",
2393 //         "properties": {
2394 //           "value": {
2395 //             "type": "string",
2396 //             "description": "The new value of the variable."
2397 //           },
2398 //           "type": {
2399 //             "type": "string",
2400 //             "description": "The type of the new value. Typically shown in the
2401 //             UI when hovering over the value."
2402 //           },
2403 //           "variablesReference": {
2404 //             "type": "number",
2405 //             "description": "If variablesReference is > 0, the new value is
2406 //             structured and its children can be retrieved by passing
2407 //             variablesReference to the VariablesRequest."
2408 //           },
2409 //           "namedVariables": {
2410 //             "type": "number",
2411 //             "description": "The number of named child variables. The client
2412 //             can use this optional information to present the variables in a
2413 //             paged UI and fetch them in chunks."
2414 //           },
2415 //           "indexedVariables": {
2416 //             "type": "number",
2417 //             "description": "The number of indexed child variables. The client
2418 //             can use this optional information to present the variables in a
2419 //             paged UI and fetch them in chunks."
2420 //           }
2421 //         },
2422 //         "required": [ "value" ]
2423 //       }
2424 //     },
2425 //     "required": [ "body" ]
2426 //   }]
2427 // }
2428 void request_setVariable(const llvm::json::Object &request) {
2429   llvm::json::Object response;
2430   FillResponse(request, response);
2431   llvm::json::Array variables;
2432   llvm::json::Object body;
2433   auto arguments = request.getObject("arguments");
2434   // This is a reference to the containing variable/scope
2435   const auto variablesReference =
2436       GetUnsigned(arguments, "variablesReference", 0);
2437   const auto name = GetString(arguments, "name");
2438   const auto value = GetString(arguments, "value");
2439   // Set success to false just in case we don't find the variable by name
2440   response.try_emplace("success", false);
2441 
2442   lldb::SBValue variable;
2443   int64_t newVariablesReference = 0;
2444 
2445   // The "id" is the unique integer ID that is unique within the enclosing
2446   // variablesReference. It is optionally added to any "interface Variable"
2447   // objects to uniquely identify a variable within an enclosing
2448   // variablesReference. It helps to disambiguate between two variables that
2449   // have the same name within the same scope since the "setVariables" request
2450   // only specifies the variable reference of the enclosing scope/variable, and
2451   // the name of the variable. We could have two shadowed variables with the
2452   // same name in "Locals" or "Globals". In our case the "id" absolute index
2453   // of the variable within the g_vsc.variables list.
2454   const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
2455   if (id_value != UINT64_MAX) {
2456     variable = g_vsc.variables.GetValueAtIndex(id_value);
2457   } else if (VARREF_IS_SCOPE(variablesReference)) {
2458     // variablesReference is one of our scopes, not an actual variable it is
2459     // asking for a variable in locals or globals or registers
2460     int64_t start_idx = 0;
2461     int64_t end_idx = 0;
2462     switch (variablesReference) {
2463     case VARREF_LOCALS:
2464       start_idx = 0;
2465       end_idx = start_idx + g_vsc.num_locals;
2466       break;
2467     case VARREF_GLOBALS:
2468       start_idx = g_vsc.num_locals;
2469       end_idx = start_idx + g_vsc.num_globals;
2470       break;
2471     case VARREF_REGS:
2472       start_idx = g_vsc.num_locals + g_vsc.num_globals;
2473       end_idx = start_idx + g_vsc.num_regs;
2474       break;
2475     default:
2476       break;
2477     }
2478 
2479     // Find the variable by name in the correct scope and hope we don't have
2480     // multiple variables with the same name. We search backwards because
2481     // the list of variables has the top most variables first and variables
2482     // in deeper scopes are last. This means we will catch the deepest
2483     // variable whose name matches which is probably what the user wants.
2484     for (int64_t i = end_idx - 1; i >= start_idx; --i) {
2485       auto curr_variable = g_vsc.variables.GetValueAtIndex(i);
2486       llvm::StringRef variable_name(curr_variable.GetName());
2487       if (variable_name == name) {
2488         variable = curr_variable;
2489         if (curr_variable.MightHaveChildren())
2490           newVariablesReference = i;
2491         break;
2492       }
2493     }
2494   } else {
2495     // We have a named item within an actual variable so we need to find it
2496     // withing the container variable by name.
2497     const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
2498     lldb::SBValue container = g_vsc.variables.GetValueAtIndex(var_idx);
2499     variable = container.GetChildMemberWithName(name.data());
2500     if (!variable.IsValid()) {
2501       if (name.startswith("[")) {
2502         llvm::StringRef index_str(name.drop_front(1));
2503         uint64_t index = 0;
2504         if (!index_str.consumeInteger(0, index)) {
2505           if (index_str == "]")
2506             variable = container.GetChildAtIndex(index);
2507         }
2508       }
2509     }
2510 
2511     // We don't know the index of the variable in our g_vsc.variables
2512     if (variable.IsValid()) {
2513       if (variable.MightHaveChildren()) {
2514         newVariablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
2515         g_vsc.variables.Append(variable);
2516       }
2517     }
2518   }
2519 
2520   if (variable.IsValid()) {
2521     lldb::SBError error;
2522     bool success = variable.SetValueFromCString(value.data(), error);
2523     if (success) {
2524       SetValueForKey(variable, body, "value");
2525       EmplaceSafeString(body, "type", variable.GetType().GetDisplayTypeName());
2526       body.try_emplace("variablesReference", newVariablesReference);
2527     } else {
2528       EmplaceSafeString(body, "message", std::string(error.GetCString()));
2529     }
2530     response["success"] = llvm::json::Value(success);
2531   }
2532 
2533   response.try_emplace("body", std::move(body));
2534   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2535 }
2536 
2537 // "VariablesRequest": {
2538 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
2539 //     "type": "object",
2540 //     "description": "Variables request; value of command field is 'variables'.
2541 //     Retrieves all child variables for the given variable reference. An
2542 //     optional filter can be used to limit the fetched children to either named
2543 //     or indexed children.", "properties": {
2544 //       "command": {
2545 //         "type": "string",
2546 //         "enum": [ "variables" ]
2547 //       },
2548 //       "arguments": {
2549 //         "$ref": "#/definitions/VariablesArguments"
2550 //       }
2551 //     },
2552 //     "required": [ "command", "arguments"  ]
2553 //   }]
2554 // },
2555 // "VariablesArguments": {
2556 //   "type": "object",
2557 //   "description": "Arguments for 'variables' request.",
2558 //   "properties": {
2559 //     "variablesReference": {
2560 //       "type": "integer",
2561 //       "description": "The Variable reference."
2562 //     },
2563 //     "filter": {
2564 //       "type": "string",
2565 //       "enum": [ "indexed", "named" ],
2566 //       "description": "Optional filter to limit the child variables to either
2567 //       named or indexed. If ommited, both types are fetched."
2568 //     },
2569 //     "start": {
2570 //       "type": "integer",
2571 //       "description": "The index of the first variable to return; if omitted
2572 //       children start at 0."
2573 //     },
2574 //     "count": {
2575 //       "type": "integer",
2576 //       "description": "The number of variables to return. If count is missing
2577 //       or 0, all variables are returned."
2578 //     },
2579 //     "format": {
2580 //       "$ref": "#/definitions/ValueFormat",
2581 //       "description": "Specifies details on how to format the Variable
2582 //       values."
2583 //     }
2584 //   },
2585 //   "required": [ "variablesReference" ]
2586 // },
2587 // "VariablesResponse": {
2588 //   "allOf": [ { "$ref": "#/definitions/Response" }, {
2589 //     "type": "object",
2590 //     "description": "Response to 'variables' request.",
2591 //     "properties": {
2592 //       "body": {
2593 //         "type": "object",
2594 //         "properties": {
2595 //           "variables": {
2596 //             "type": "array",
2597 //             "items": {
2598 //               "$ref": "#/definitions/Variable"
2599 //             },
2600 //             "description": "All (or a range) of variables for the given
2601 //             variable reference."
2602 //           }
2603 //         },
2604 //         "required": [ "variables" ]
2605 //       }
2606 //     },
2607 //     "required": [ "body" ]
2608 //   }]
2609 // }
2610 void request_variables(const llvm::json::Object &request) {
2611   llvm::json::Object response;
2612   FillResponse(request, response);
2613   llvm::json::Array variables;
2614   auto arguments = request.getObject("arguments");
2615   const auto variablesReference =
2616       GetUnsigned(arguments, "variablesReference", 0);
2617   const int64_t start = GetSigned(arguments, "start", 0);
2618   const int64_t count = GetSigned(arguments, "count", 0);
2619   bool hex = false;
2620   auto format = arguments->getObject("format");
2621   if (format)
2622     hex = GetBoolean(format, "hex", false);
2623 
2624   if (VARREF_IS_SCOPE(variablesReference)) {
2625     // variablesReference is one of our scopes, not an actual variable it is
2626     // asking for the list of args, locals or globals.
2627     int64_t start_idx = 0;
2628     int64_t num_children = 0;
2629     switch (variablesReference) {
2630     case VARREF_LOCALS:
2631       start_idx = start;
2632       num_children = g_vsc.num_locals;
2633       break;
2634     case VARREF_GLOBALS:
2635       start_idx = start + g_vsc.num_locals + start;
2636       num_children = g_vsc.num_globals;
2637       break;
2638     case VARREF_REGS:
2639       start_idx = start + g_vsc.num_locals + g_vsc.num_globals;
2640       num_children = g_vsc.num_regs;
2641       break;
2642     default:
2643       break;
2644     }
2645     const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
2646     for (auto i = start_idx; i < end_idx; ++i) {
2647       lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
2648       if (!variable.IsValid())
2649         break;
2650       variables.emplace_back(
2651           CreateVariable(variable, VARIDX_TO_VARREF(i), i, hex));
2652     }
2653   } else {
2654     // We are expanding a variable that has children, so we will return its
2655     // children.
2656     const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
2657     lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(var_idx);
2658     if (variable.IsValid()) {
2659       const auto num_children = variable.GetNumChildren();
2660       const int64_t end_idx = start + ((count == 0) ? num_children : count);
2661       for (auto i = start; i < end_idx; ++i) {
2662         lldb::SBValue child = variable.GetChildAtIndex(i);
2663         if (!child.IsValid())
2664           break;
2665         if (child.MightHaveChildren()) {
2666           const int64_t var_idx = g_vsc.variables.GetSize();
2667           auto childVariablesReferences = VARIDX_TO_VARREF(var_idx);
2668           variables.emplace_back(
2669               CreateVariable(child, childVariablesReferences, var_idx, hex));
2670           g_vsc.variables.Append(child);
2671         } else {
2672           variables.emplace_back(CreateVariable(child, 0, INT64_MAX, hex));
2673         }
2674       }
2675     }
2676   }
2677   llvm::json::Object body;
2678   body.try_emplace("variables", std::move(variables));
2679   response.try_emplace("body", std::move(body));
2680   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2681 }
2682 
2683 // A request used in testing to get the details on all breakpoints that are
2684 // currently set in the target. This helps us to test "setBreakpoints" and
2685 // "setFunctionBreakpoints" requests to verify we have the correct set of
2686 // breakpoints currently set in LLDB.
2687 void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
2688   llvm::json::Object response;
2689   FillResponse(request, response);
2690   llvm::json::Array response_breakpoints;
2691   for (uint32_t i = 0; g_vsc.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
2692     auto bp = g_vsc.target.GetBreakpointAtIndex(i);
2693     AppendBreakpoint(bp, response_breakpoints);
2694   }
2695   llvm::json::Object body;
2696   body.try_emplace("breakpoints", std::move(response_breakpoints));
2697   response.try_emplace("body", std::move(body));
2698   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
2699 }
2700 
2701 const std::map<std::string, RequestCallback> &GetRequestHandlers() {
2702 #define REQUEST_CALLBACK(name)                                                 \
2703   { #name, request_##name }
2704   static std::map<std::string, RequestCallback> g_request_handlers = {
2705       // VSCode Debug Adaptor requests
2706       REQUEST_CALLBACK(attach),
2707       REQUEST_CALLBACK(completions),
2708       REQUEST_CALLBACK(continue),
2709       REQUEST_CALLBACK(configurationDone),
2710       REQUEST_CALLBACK(disconnect),
2711       REQUEST_CALLBACK(evaluate),
2712       REQUEST_CALLBACK(exceptionInfo),
2713       REQUEST_CALLBACK(initialize),
2714       REQUEST_CALLBACK(launch),
2715       REQUEST_CALLBACK(next),
2716       REQUEST_CALLBACK(pause),
2717       REQUEST_CALLBACK(scopes),
2718       REQUEST_CALLBACK(setBreakpoints),
2719       REQUEST_CALLBACK(setExceptionBreakpoints),
2720       REQUEST_CALLBACK(setFunctionBreakpoints),
2721       REQUEST_CALLBACK(setVariable),
2722       REQUEST_CALLBACK(source),
2723       REQUEST_CALLBACK(stackTrace),
2724       REQUEST_CALLBACK(stepIn),
2725       REQUEST_CALLBACK(stepOut),
2726       REQUEST_CALLBACK(threads),
2727       REQUEST_CALLBACK(variables),
2728       // Testing requests
2729       REQUEST_CALLBACK(_testGetTargetBreakpoints),
2730   };
2731 #undef REQUEST_CALLBACK
2732   return g_request_handlers;
2733 }
2734 
2735 } // anonymous namespace
2736 
2737 int main(int argc, char *argv[]) {
2738 
2739   // Initialize LLDB first before we do anything.
2740   lldb::SBDebugger::Initialize();
2741 
2742   if (argc == 2) {
2743     const char *arg = argv[1];
2744 #if !defined(_WIN32)
2745     if (strcmp(arg, "-g") == 0) {
2746       printf("Paused waiting for debugger to attach (pid = %i)...\n", getpid());
2747       pause();
2748     } else {
2749 #else
2750     {
2751 #endif
2752       int portno = atoi(arg);
2753       printf("Listening on port %i...\n", portno);
2754       SOCKET socket_fd = AcceptConnection(portno);
2755       if (socket_fd >= 0) {
2756         g_vsc.input.descriptor = StreamDescriptor::from_socket(socket_fd, true);
2757         g_vsc.output.descriptor =
2758             StreamDescriptor::from_socket(socket_fd, false);
2759       } else {
2760         exit(1);
2761       }
2762     }
2763   } else {
2764     g_vsc.input.descriptor = StreamDescriptor::from_file(fileno(stdin), false);
2765     g_vsc.output.descriptor =
2766         StreamDescriptor::from_file(fileno(stdout), false);
2767   }
2768   auto request_handlers = GetRequestHandlers();
2769   uint32_t packet_idx = 0;
2770   while (true) {
2771     std::string json = g_vsc.ReadJSON();
2772     if (json.empty())
2773       break;
2774 
2775     llvm::StringRef json_sref(json);
2776     llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
2777     if (!json_value) {
2778       auto error = json_value.takeError();
2779       if (g_vsc.log) {
2780         std::string error_str;
2781         llvm::raw_string_ostream strm(error_str);
2782         strm << error;
2783         strm.flush();
2784 
2785         *g_vsc.log << "error: failed to parse JSON: " << error_str << std::endl
2786                    << json << std::endl;
2787       }
2788       return 1;
2789     }
2790 
2791     auto object = json_value->getAsObject();
2792     if (!object) {
2793       if (g_vsc.log)
2794         *g_vsc.log << "error: json packet isn't a object" << std::endl;
2795       return 1;
2796     }
2797 
2798     const auto packet_type = GetString(object, "type");
2799     if (packet_type == "request") {
2800       const auto command = GetString(object, "command");
2801       auto handler_pos = request_handlers.find(command);
2802       if (handler_pos != request_handlers.end()) {
2803         handler_pos->second(*object);
2804       } else {
2805         if (g_vsc.log)
2806           *g_vsc.log << "error: unhandled command \"" << command.data() << std::endl;
2807         return 1;
2808       }
2809     }
2810     ++packet_idx;
2811   }
2812 
2813   // We must terminate the debugger in a thread before the C++ destructor
2814   // chain messes everything up.
2815   lldb::SBDebugger::Terminate();
2816   return 0;
2817 }
2818