[Lldb-commits] [PATCH] D156493: [lldb-vsocde] Adding support for the "disassemble" request.

2023-07-31 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGca71dc1b5404: [lldb-vscode] Adding support for the 
disassemble request. (authored by ashgti, committed by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156493/new/

https://reviews.llvm.org/D156493

Files:
  lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
  lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
  lldb/test/API/tools/lldb-vscode/coreFile/TestVSCode_coreFile.py
  lldb/test/API/tools/lldb-vscode/disassemble/Makefile
  lldb/test/API/tools/lldb-vscode/disassemble/TestVSCode_disassemble.py
  lldb/test/API/tools/lldb-vscode/disassemble/main.c
  lldb/tools/lldb-vscode/JSONUtils.cpp
  lldb/tools/lldb-vscode/JSONUtils.h
  lldb/tools/lldb-vscode/SourceReference.h
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/VSCodeForward.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -50,6 +50,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
@@ -1563,6 +1564,8 @@
   body.try_emplace("supportsStepInTargetsRequest", false);
   // The debug adapter supports the completions request.
   body.try_emplace("supportsCompletionsRequest", true);
+  // The debug adapter supports the disassembly request.
+  body.try_emplace("supportsDisassembleRequest", true);
 
   llvm::json::Array completion_characters;
   completion_characters.emplace_back(".");
@@ -2588,18 +2591,7 @@
 void request_source(const llvm::json::Object ) {
   llvm::json::Object response;
   FillResponse(request, response);
-  llvm::json::Object body;
-
-  auto arguments = request.getObject("arguments");
-  auto source = arguments->getObject("source");
-  auto sourceReference = GetSigned(source, "sourceReference", -1);
-  auto pos = g_vsc.source_map.find((lldb::addr_t)sourceReference);
-  if (pos != g_vsc.source_map.end()) {
-EmplaceSafeString(body, "content", pos->second.content);
-  } else {
-response["success"] = llvm::json::Value(false);
-  }
-  EmplaceSafeString(body, "mimeType", "text/x-lldb.disassembly");
+  llvm::json::Object body{{"content", ""}};
   response.try_emplace("body", std::move(body));
   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
 }
@@ -3301,6 +3293,211 @@
   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
 }
 
+// "DisassembleRequest": {
+//   "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Disassembles code stored at the provided
+// location.\nClients should only call this request if the corresponding
+// capability `supportsDisassembleRequest` is true.", "properties": {
+//   "command": {
+// "type": "string",
+// "enum": [ "disassemble" ]
+//   },
+//   "arguments": {
+// "$ref": "#/definitions/DisassembleArguments"
+//   }
+// },
+// "required": [ "command", "arguments" ]
+//   }]
+// },
+// "DisassembleArguments": {
+//   "type": "object",
+//   "description": "Arguments for `disassemble` request.",
+//   "properties": {
+// "memoryReference": {
+//   "type": "string",
+//   "description": "Memory reference to the base location containing the
+//   instructions to disassemble."
+// },
+// "offset": {
+//   "type": "integer",
+//   "description": "Offset (in bytes) to be applied to the reference
+//   location before disassembling. Can be negative."
+// },
+// "instructionOffset": {
+//   "type": "integer",
+//   "description": "Offset (in instructions) to be applied after the byte
+//   offset (if any) before disassembling. Can be negative."
+// },
+// "instructionCount": {
+//   "type": "integer",
+//   "description": "Number of instructions to disassemble starting at the
+//   specified location and offset.\nAn adapter must return exactly this
+//   number of instructions - any unavailable instructions should be
+//   replaced with an implementation-defined 'invalid instruction' value."
+// },
+// "resolveSymbols": {
+//   "type": "boolean",
+//   "description": "If true, the adapter should attempt to resolve memory
+//   addresses and other values to symbolic names."
+// }
+//   },
+//   "required": [ "memoryReference", "instructionCount" ]
+// },
+// "DisassembleResponse": {
+//   "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to `disassemble` request.",
+// "properties": {
+//   "body": {
+// "type": 

[Lldb-commits] [PATCH] D156465: [lldb-vscode] Adding support for displaying backtraces.

2023-07-28 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1bf6f55911ca: [lldb-vscode] Adding support for displaying 
backtraces. (authored by ashgti, committed by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156465/new/

https://reviews.llvm.org/D156465

Files:
  lldb/tools/lldb-vscode/JSONUtils.cpp
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -2687,13 +2687,72 @@
 const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
 const auto levels = GetUnsigned(arguments, "levels", 0);
 const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
+auto totalFrames = thread.GetNumFrames();
+
+// This will always return an invalid thread when
+// libBacktraceRecording.dylib is not loaded or if there is no extended
+// backtrace.
+lldb::SBThread queue_backtrace_thread =
+thread.GetExtendedBacktraceThread("libdispatch");
+if (queue_backtrace_thread.IsValid()) {
+  // One extra frame as a label to mark the enqueued thread.
+  totalFrames += queue_backtrace_thread.GetNumFrames() + 1;
+}
+
+// This will always return an invalid thread when there is no exception in
+// the current thread.
+lldb::SBThread exception_backtrace_thread =
+thread.GetCurrentExceptionBacktrace();
+if (exception_backtrace_thread.IsValid()) {
+  // One extra frame as a label to mark the exception thread.
+  totalFrames += exception_backtrace_thread.GetNumFrames() + 1;
+}
+
 for (uint32_t i = startFrame; i < endFrame; ++i) {
-  auto frame = thread.GetFrameAtIndex(i);
+  lldb::SBFrame frame;
+  std::string prefix;
+  if (i < thread.GetNumFrames()) {
+frame = thread.GetFrameAtIndex(i);
+  } else if (queue_backtrace_thread.IsValid() &&
+ i < (thread.GetNumFrames() +
+  queue_backtrace_thread.GetNumFrames() + 1)) {
+if (i == thread.GetNumFrames()) {
+  const uint32_t thread_idx =
+  queue_backtrace_thread.GetExtendedBacktraceOriginatingIndexID();
+  const char *queue_name = queue_backtrace_thread.GetQueueName();
+  auto name = llvm::formatv("Enqueued from {0} (Thread {1})",
+queue_name, thread_idx);
+  stackFrames.emplace_back(
+  llvm::json::Object{{"id", thread.GetThreadID() + 1},
+ {"name", name},
+ {"presentationHint", "label"}});
+  continue;
+}
+frame = queue_backtrace_thread.GetFrameAtIndex(
+i - thread.GetNumFrames() - 1);
+  } else if (exception_backtrace_thread.IsValid()) {
+if (i == thread.GetNumFrames() +
+ (queue_backtrace_thread.IsValid()
+  ? queue_backtrace_thread.GetNumFrames() + 1
+  : 0)) {
+  stackFrames.emplace_back(
+  llvm::json::Object{{"id", thread.GetThreadID() + 2},
+ {"name", "Original Exception Backtrace"},
+ {"presentationHint", "label"}});
+  continue;
+}
+
+frame = exception_backtrace_thread.GetFrameAtIndex(
+i - thread.GetNumFrames() -
+(queue_backtrace_thread.IsValid()
+ ? queue_backtrace_thread.GetNumFrames() + 1
+ : 0));
+  }
   if (!frame.IsValid())
 break;
   stackFrames.emplace_back(CreateStackFrame(frame));
 }
-const auto totalFrames = thread.GetNumFrames();
+
 body.try_emplace("totalFrames", totalFrames);
   }
   body.try_emplace("stackFrames", std::move(stackFrames));
Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -815,17 +815,30 @@
 llvm::json::Value CreateThread(lldb::SBThread ) {
   llvm::json::Object object;
   object.try_emplace("id", (int64_t)thread.GetThreadID());
-  char thread_str[64];
-  snprintf(thread_str, sizeof(thread_str), "Thread #%u", thread.GetIndexID());
-  const char *name = thread.GetName();
-  if (name) {
-std::string thread_with_name(thread_str);
-thread_with_name += ' ';
-thread_with_name += name;
-EmplaceSafeString(object, "name", thread_with_name);
+  const char *thread_name = thread.GetName();
+  const char *queue_name = thread.GetQueueName();
+
+  std::string thread_str;
+  if (thread_name) {
+thread_str = std::string(thread_name);
+  } else if (queue_name) {
+auto kind = thread.GetQueue().GetKind();
+std::string queue_kind_label = "";
+if (kind == lldb::eQueueKindSerial) 

[Lldb-commits] [PATCH] D154990: [lldb-vsocde] Cleaning up the usage of the Separate helper in Options.td.

2023-07-26 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG011cc6d8bfba: [lldb-vsocde] Cleaning up the usage of the 
Separate helper in Options.td. (authored by ashgti, committed by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154990/new/

https://reviews.llvm.org/D154990

Files:
  lldb/tools/lldb-vscode/Options.td


Index: lldb/tools/lldb-vscode/Options.td
===
--- lldb/tools/lldb-vscode/Options.td
+++ lldb/tools/lldb-vscode/Options.td
@@ -17,25 +17,25 @@
   Alias,
   HelpText<"Alias for --wait-for-debugger">;
 
-def port: Separate<["--", "-"], "port">,
+def port: S<"port">,
   MetaVarName<"">,
   HelpText<"Communicate with the lldb-vscode tool over the defined port.">;
 def: Separate<["-"], "p">,
   Alias,
   HelpText<"Alias for --port">;
 
-def launch_target: Separate<["--", "-"], "launch-target">,
+def launch_target: S<"launch-target">,
   MetaVarName<"">,
   HelpText<"Launch a target for the launchInTerminal request. Any argument "
 "provided after this one will be passed to the target. The parameter "
 "--comm-file must also be specified.">;
 
-def comm_file: Separate<["--", "-"], "comm-file">,
+def comm_file: S<"comm-file">,
   MetaVarName<"">,
   HelpText<"The fifo file used to communicate the with the debug adaptor "
 "when using --launch-target.">;
 
-def debugger_pid: Separate<["--", "-"], "debugger-pid">,
+def debugger_pid: S<"debugger-pid">,
   MetaVarName<"">,
   HelpText<"The PID of the lldb-vscode instance that sent the launchInTerminal 
"
 "request when using --launch-target.">;


Index: lldb/tools/lldb-vscode/Options.td
===
--- lldb/tools/lldb-vscode/Options.td
+++ lldb/tools/lldb-vscode/Options.td
@@ -17,25 +17,25 @@
   Alias,
   HelpText<"Alias for --wait-for-debugger">;
 
-def port: Separate<["--", "-"], "port">,
+def port: S<"port">,
   MetaVarName<"">,
   HelpText<"Communicate with the lldb-vscode tool over the defined port.">;
 def: Separate<["-"], "p">,
   Alias,
   HelpText<"Alias for --port">;
 
-def launch_target: Separate<["--", "-"], "launch-target">,
+def launch_target: S<"launch-target">,
   MetaVarName<"">,
   HelpText<"Launch a target for the launchInTerminal request. Any argument "
 "provided after this one will be passed to the target. The parameter "
 "--comm-file must also be specified.">;
 
-def comm_file: Separate<["--", "-"], "comm-file">,
+def comm_file: S<"comm-file">,
   MetaVarName<"">,
   HelpText<"The fifo file used to communicate the with the debug adaptor "
 "when using --launch-target.">;
 
-def debugger_pid: Separate<["--", "-"], "debugger-pid">,
+def debugger_pid: S<"debugger-pid">,
   MetaVarName<"">,
   HelpText<"The PID of the lldb-vscode instance that sent the launchInTerminal "
 "request when using --launch-target.">;
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D154989: [lldb-vsocde] Add a 'continued' event for programmatic continue events.

2023-07-25 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3ab73a398422: [lldb-vsocde] Add a continued 
event for programmatic continue events. (authored by ashgti, committed by 
dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154989/new/

https://reviews.llvm.org/D154989

Files:
  lldb/tools/lldb-vscode/JSONUtils.cpp
  lldb/tools/lldb-vscode/lldb-vscode.cpp


Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -191,6 +191,28 @@
   g_vsc.SendJSON(llvm::json::Value(std::move(event)));
 }
 
+// Send a "continued" event to indicate the process is in the running state.
+void SendContinuedEvent() {
+  lldb::SBProcess process = g_vsc.target.GetProcess();
+  if (!process.IsValid()) {
+return;
+  }
+
+  // If the focus thread is not set then we haven't reported any thread status
+  // to the client, so nothing to report.
+  if (!g_vsc.configuration_done_sent ||
+  g_vsc.focus_tid == LLDB_INVALID_THREAD_ID) {
+return;
+  }
+
+  llvm::json::Object event(CreateEventObject("continued"));
+  llvm::json::Object body;
+  body.try_emplace("threadId", (int64_t)g_vsc.focus_tid);
+  body.try_emplace("allThreadsContinued", true);
+  event.try_emplace("body", std::move(body));
+  g_vsc.SendJSON(llvm::json::Value(std::move(event)));
+}
+
 // Send a "terminated" event to indicate the process is done being
 // debugged.
 void SendTerminatedEvent() {
@@ -252,7 +274,7 @@
 }
   }
 
-  // We will have cleared g_vsc.focus_tid if he focus thread doesn't have
+  // We will have cleared g_vsc.focus_tid if the focus thread doesn't have
   // a stop reason, so if it was cleared, or wasn't set, or doesn't exist,
   // then set the focus thread to the first thread with a stop reason.
   if (!focus_thread_exists || g_vsc.focus_tid == LLDB_INVALID_THREAD_ID)
@@ -262,6 +284,7 @@
   // we at least let the UI know we stopped.
   if (num_threads_with_reason == 0) {
 lldb::SBThread thread = process.GetThreadAtIndex(0);
+g_vsc.focus_tid = thread.GetThreadID();
 g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
   } else {
 for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
@@ -468,6 +491,7 @@
 break;
   case lldb::eStateRunning:
 g_vsc.WillContinue();
+SendContinuedEvent();
 break;
   case lldb::eStateExited:
 // When restarting, we can get an "exited" event for the process we
@@ -766,10 +790,6 @@
   llvm::json::Object response;
   FillResponse(request, response);
   lldb::SBProcess process = g_vsc.target.GetProcess();
-  auto arguments = request.getObject("arguments");
-  // Remember the thread ID that caused the resume so we can set the
-  // "threadCausedFocus" boolean value in the "stopped" events.
-  g_vsc.focus_tid = GetUnsigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
   lldb::SBError error = process.Continue();
   llvm::json::Object body;
   body.try_emplace("allThreadsContinued", true);
Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -907,6 +907,8 @@
   uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1);
   snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64,
bp_id, bp_loc_id);
+  body.try_emplace("hitBreakpointIds",
+   llvm::json::Array{llvm::json::Value(bp_id)});
   EmplaceSafeString(body, "description", desc_str);
 }
   } break;
@@ -951,6 +953,7 @@
   EmplaceSafeString(body, "description", std::string(description));
 }
   }
+  // "threadCausedFocus" is used in tests to validate breaking behavior.
   if (tid == g_vsc.focus_tid) {
 body.try_emplace("threadCausedFocus", true);
   }


Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -191,6 +191,28 @@
   g_vsc.SendJSON(llvm::json::Value(std::move(event)));
 }
 
+// Send a "continued" event to indicate the process is in the running state.
+void SendContinuedEvent() {
+  lldb::SBProcess process = g_vsc.target.GetProcess();
+  if (!process.IsValid()) {
+return;
+  }
+
+  // If the focus thread is not set then we haven't reported any thread status
+  // to the client, so nothing to report.
+  if (!g_vsc.configuration_done_sent ||
+  g_vsc.focus_tid == LLDB_INVALID_THREAD_ID) {
+return;
+  }
+
+  llvm::json::Object event(CreateEventObject("continued"));
+  llvm::json::Object body;
+  body.try_emplace("threadId", (int64_t)g_vsc.focus_tid);
+  

[Lldb-commits] [PATCH] D155248: [lldb-vscode] Creating a new flag for adjusting the behavior of evaluation repl expressions to allow users to more easily invoke lldb commands.

2023-07-19 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3d1f89c2e37c: [lldb-vscode] Creating a new flag for 
adjusting the behavior of evaluation repl… (authored by ashgti, committed by 
dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D155248/new/

https://reviews.llvm.org/D155248

Files:
  lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
  lldb/test/API/tools/lldb-vscode/completions/TestVSCode_completions.py
  lldb/test/API/tools/lldb-vscode/console/TestVSCode_console.py
  lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py
  lldb/test/API/tools/lldb-vscode/startDebugging/TestVSCode_startDebugging.py
  lldb/tools/lldb-vscode/Options.td
  lldb/tools/lldb-vscode/README.md
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -1065,50 +1065,62 @@
   FillResponse(request, response);
   llvm::json::Object body;
   auto arguments = request.getObject("arguments");
-  std::string text = std::string(GetString(arguments, "text"));
+
+  // If we have a frame, try to set the context for variable completions.
+  lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
+  if (frame.IsValid()) {
+frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
+frame.GetThread().SetSelectedFrame(frame.GetFrameID());
+  }
+
+  std::string text = GetString(arguments, "text").str();
   auto original_column = GetSigned(arguments, "column", text.size());
-  auto actual_column = original_column - 1;
+  auto original_line = GetSigned(arguments, "line", 1);
+  auto offset = original_column - 1;
+  if (original_line > 1) {
+llvm::SmallVector<::llvm::StringRef, 2> lines;
+llvm::StringRef(text).split(lines, '\n');
+for (int i = 0; i < original_line - 1; i++) {
+  offset += lines[i].size();
+}
+  }
   llvm::json::Array targets;
-  // NOTE: the 'line' argument is not needed, as multiline expressions
-  // work well already
-  // TODO: support frameID. Currently
-  // g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions
-  // is frame-unaware.
-
-  if (!text.empty() && text[0] == '`') {
-text = text.substr(1);
-actual_column--;
-  } else {
+
+  if (g_vsc.DetectExpressionContext(frame, text) ==
+  ExpressionContext::Variable) {
 char command[] = "expression -- ";
 text = command + text;
-actual_column += strlen(command);
+offset += strlen(command);
   }
   lldb::SBStringList matches;
   lldb::SBStringList descriptions;
-  g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
-  text.c_str(), actual_column, 0, -1, matches, descriptions);
-  size_t count = std::min((uint32_t)100, matches.GetSize());
-  targets.reserve(count);
-  for (size_t i = 0; i < count; i++) {
-std::string match = matches.GetStringAtIndex(i);
-std::string description = descriptions.GetStringAtIndex(i);
-
-llvm::json::Object item;
-
-llvm::StringRef match_ref = match;
-for (llvm::StringRef commit_point : {".", "->"}) {
-  if (match_ref.contains(commit_point)) {
-match_ref = match_ref.rsplit(commit_point).second;
+
+  if (g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
+  text.c_str(), offset, 0, 100, matches, descriptions)) {
+// The first element is the common substring after the cursor position for
+// all the matches. The rest of the elements are the matches so ignore the
+// first result.
+targets.reserve(matches.GetSize() - 1);
+for (size_t i = 1; i < matches.GetSize(); i++) {
+  std::string match = matches.GetStringAtIndex(i);
+  std::string description = descriptions.GetStringAtIndex(i);
+
+  llvm::json::Object item;
+  llvm::StringRef match_ref = match;
+  for (llvm::StringRef commit_point : {".", "->"}) {
+if (match_ref.contains(commit_point)) {
+  match_ref = match_ref.rsplit(commit_point).second;
+}
   }
-}
-EmplaceSafeString(item, "text", match_ref);
+  EmplaceSafeString(item, "text", match_ref);
 
-if (description.empty())
-  EmplaceSafeString(item, "label", match);
-else
-  EmplaceSafeString(item, "label", match + " -- " + description);
+  if (description.empty())
+EmplaceSafeString(item, "label", match);
+  else
+EmplaceSafeString(item, "label", match + " -- " + description);
 
-targets.emplace_back(std::move(item));
+  targets.emplace_back(std::move(item));
+}
   }
 
   body.try_emplace("targets", std::move(targets));
@@ -1223,12 +1235,17 @@
   llvm::json::Object body;
   auto arguments = request.getObject("arguments");
   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
-  const auto 

[Lldb-commits] [PATCH] D154989: [lldb-vsocde] Add a 'continued' event for programmatic continue events.

2023-07-11 Thread David Goldman via Phabricator via lldb-commits
dgoldman added inline comments.



Comment at: lldb/tools/lldb-vscode/lldb-vscode.cpp:285
   if (num_threads_with_reason == 0) {
 lldb::SBThread thread = process.GetThreadAtIndex(0);
 g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));

Should we also set g_vsc.focus_tid here if it's invalid?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154989/new/

https://reviews.llvm.org/D154989

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D154030: [lldb-vscode] Creating a new flag for adjusting the behavior of evaluation repl expressions to allow users to more easily invoke lldb commands.

2023-07-11 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG16317f1ced77: [lldb-vscode] Creating a new flag for 
adjusting the behavior of evaluation repl… (authored by ashgti, committed by 
dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154030/new/

https://reviews.llvm.org/D154030

Files:
  lldb/tools/lldb-vscode/Options.td
  lldb/tools/lldb-vscode/README.md
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -1065,50 +1065,63 @@
   FillResponse(request, response);
   llvm::json::Object body;
   auto arguments = request.getObject("arguments");
+
+  // If we have a frame, try to set the context for variable completions.
+  lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
+  if (frame.IsValid()) {
+frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
+frame.GetThread().SetSelectedFrame(frame.GetFrameID());
+  }
+
   std::string text = std::string(GetString(arguments, "text"));
   auto original_column = GetSigned(arguments, "column", text.size());
-  auto actual_column = original_column - 1;
+  auto original_line = GetSigned(arguments, "line", 1);
+  auto offset = original_column - 1;
+  if (original_line > 1) {
+llvm::StringRef text_ref{text};
+::llvm::SmallVector<::llvm::StringRef, 2> lines;
+text_ref.split(lines, '\n');
+for (int i = 0; i < original_line - 1; i++) {
+  offset += lines[i].size();
+}
+  }
   llvm::json::Array targets;
-  // NOTE: the 'line' argument is not needed, as multiline expressions
-  // work well already
-  // TODO: support frameID. Currently
-  // g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions
-  // is frame-unaware.
-
-  if (!text.empty() && text[0] == '`') {
-text = text.substr(1);
-actual_column--;
-  } else {
-char command[] = "expression -- ";
+
+  if (g_vsc.DetectExpressionContext(frame, text) ==
+  ExpressionContext::Variable) {
+char command[] = "frame variable ";
 text = command + text;
-actual_column += strlen(command);
+offset += strlen(command);
   }
   lldb::SBStringList matches;
   lldb::SBStringList descriptions;
-  g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
-  text.c_str(), actual_column, 0, -1, matches, descriptions);
-  size_t count = std::min((uint32_t)100, matches.GetSize());
-  targets.reserve(count);
-  for (size_t i = 0; i < count; i++) {
-std::string match = matches.GetStringAtIndex(i);
-std::string description = descriptions.GetStringAtIndex(i);
-
-llvm::json::Object item;
-
-llvm::StringRef match_ref = match;
-for (llvm::StringRef commit_point : {".", "->"}) {
-  if (match_ref.contains(commit_point)) {
-match_ref = match_ref.rsplit(commit_point).second;
+
+  if (g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
+  text.c_str(), offset, 0, 100, matches, descriptions)) {
+// The first element is the common substring after the cursor position for
+// all the matches. The rest of the elements are the matches.
+targets.reserve(matches.GetSize() - 1);
+std::string common_pattern = matches.GetStringAtIndex(0);
+for (size_t i = 1; i < matches.GetSize(); i++) {
+  std::string match = matches.GetStringAtIndex(i);
+  std::string description = descriptions.GetStringAtIndex(i);
+
+  llvm::json::Object item;
+  llvm::StringRef match_ref = match;
+  for (llvm::StringRef commit_point : {".", "->"}) {
+if (match_ref.contains(commit_point)) {
+  match_ref = match_ref.rsplit(commit_point).second;
+}
   }
-}
-EmplaceSafeString(item, "text", match_ref);
+  EmplaceSafeString(item, "text", match_ref);
 
-if (description.empty())
-  EmplaceSafeString(item, "label", match);
-else
-  EmplaceSafeString(item, "label", match + " -- " + description);
+  if (description.empty())
+EmplaceSafeString(item, "label", match);
+  else
+EmplaceSafeString(item, "label", match + " -- " + description);
 
-targets.emplace_back(std::move(item));
+  targets.emplace_back(std::move(item));
+}
   }
 
   body.try_emplace("targets", std::move(targets));
@@ -1223,12 +1236,17 @@
   llvm::json::Object body;
   auto arguments = request.getObject("arguments");
   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
-  const auto expression = GetString(arguments, "expression");
+  std::string expression = GetString(arguments, "expression").str();
   llvm::StringRef context = GetString(arguments, "context");
 
-  if (!expression.empty() && expression[0] == '`') {
-auto result =
-RunLLDBCommands(llvm::StringRef(), 

[Lldb-commits] [PATCH] D154029: [lldb-vscode] Adding support for column break points.

2023-07-06 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGda59370b0977: [lldb-vscode] Adding support for column break 
points. (authored by ashgti, committed by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154029/new/

https://reviews.llvm.org/D154029

Files:
  lldb/tools/lldb-vscode/JSONUtils.cpp
  lldb/tools/lldb-vscode/JSONUtils.h
  lldb/tools/lldb-vscode/SourceBreakpoint.cpp


Index: lldb/tools/lldb-vscode/SourceBreakpoint.cpp
===
--- lldb/tools/lldb-vscode/SourceBreakpoint.cpp
+++ lldb/tools/lldb-vscode/SourceBreakpoint.cpp
@@ -16,7 +16,9 @@
   column(GetUnsigned(obj, "column", 0)) {}
 
 void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
-  bp = g_vsc.target.BreakpointCreateByLocation(source_path.str().c_str(), 
line);
+  lldb::SBFileSpecList module_list;
+  bp = g_vsc.target.BreakpointCreateByLocation(source_path.str().c_str(), line,
+   column, 0, module_list);
   // See comments in BreakpointBase::GetBreakpointLabel() for details of why
   // we add a label to our breakpoints.
   bp.AddName(GetBreakpointLabel());
Index: lldb/tools/lldb-vscode/JSONUtils.h
===
--- lldb/tools/lldb-vscode/JSONUtils.h
+++ lldb/tools/lldb-vscode/JSONUtils.h
@@ -232,13 +232,21 @@
 /// provided by the setBreakpoints request are returned to the IDE as a
 /// fallback.
 ///
+/// \param[in] request_column
+/// An optional column to use when creating the resulting "Breakpoint" 
object.
+/// It is used if the breakpoint has no valid locations.
+/// It is useful to ensure the same column
+/// provided by the setBreakpoints request are returned to the IDE as a
+/// fallback.
+///
 /// \return
 /// A "Breakpoint" JSON object with that follows the formal JSON
 /// definition outlined by Microsoft.
 llvm::json::Value
 CreateBreakpoint(lldb::SBBreakpoint ,
  std::optional request_path = std::nullopt,
- std::optional request_line = std::nullopt);
+ std::optional request_line = std::nullopt,
+ std::optional request_column = std::nullopt);
 
 /// Converts a LLDB module to a VS Code DAP module for use in "modules" events.
 ///
Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -308,7 +308,8 @@
 // }
 llvm::json::Value CreateBreakpoint(lldb::SBBreakpoint ,
std::optional request_path,
-   std::optional request_line) {
+   std::optional request_line,
+   std::optional request_column) {
   // Each breakpoint location is treated as a separate breakpoint for VS code.
   // They don't have the notion of a single breakpoint with multiple locations.
   llvm::json::Object object;
@@ -345,11 +346,16 @@
 const auto line = line_entry.GetLine();
 if (line != UINT32_MAX)
   object.try_emplace("line", line);
+const auto column = line_entry.GetColumn();
+if (column != 0)
+  object.try_emplace("column", column);
 object.try_emplace("source", CreateSource(line_entry));
   }
   // We try to add request_line as a fallback
   if (request_line)
 object.try_emplace("line", *request_line);
+  if (request_column)
+object.try_emplace("column", *request_column);
   return llvm::json::Value(std::move(object));
 }
 


Index: lldb/tools/lldb-vscode/SourceBreakpoint.cpp
===
--- lldb/tools/lldb-vscode/SourceBreakpoint.cpp
+++ lldb/tools/lldb-vscode/SourceBreakpoint.cpp
@@ -16,7 +16,9 @@
   column(GetUnsigned(obj, "column", 0)) {}
 
 void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
-  bp = g_vsc.target.BreakpointCreateByLocation(source_path.str().c_str(), line);
+  lldb::SBFileSpecList module_list;
+  bp = g_vsc.target.BreakpointCreateByLocation(source_path.str().c_str(), line,
+   column, 0, module_list);
   // See comments in BreakpointBase::GetBreakpointLabel() for details of why
   // we add a label to our breakpoints.
   bp.AddName(GetBreakpointLabel());
Index: lldb/tools/lldb-vscode/JSONUtils.h
===
--- lldb/tools/lldb-vscode/JSONUtils.h
+++ lldb/tools/lldb-vscode/JSONUtils.h
@@ -232,13 +232,21 @@
 /// provided by the setBreakpoints request are returned to the IDE as a
 /// fallback.
 ///
+/// \param[in] request_column
+/// An optional column to use when creating the resulting "Breakpoint" object.
+/// It is used if the breakpoint has no valid locations.

[Lldb-commits] [PATCH] D154026: [lldb-vscode] Adjusting CreateSource to detect compiler generated frames.

2023-06-29 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb9b0ab32f9d0: [lldb-vscode] Adjusting CreateSource to detect 
compiler generated frames. (authored by ashgti, committed by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154026/new/

https://reviews.llvm.org/D154026

Files:
  lldb/tools/lldb-vscode/JSONUtils.cpp


Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -613,7 +613,9 @@
 llvm::json::Value CreateSource(lldb::SBFrame , int64_t _line) {
   disasm_line = 0;
   auto line_entry = frame.GetLineEntry();
-  if (line_entry.GetFileSpec().IsValid())
+  // A line entry of 0 indicates the line is compiler generated i.e. no source
+  // file so don't return early with the line entry.
+  if (line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0)
 return CreateSource(line_entry);
 
   llvm::json::Object object;
@@ -650,7 +652,11 @@
   }
   const auto num_insts = insts.GetSize();
   if (low_pc != LLDB_INVALID_ADDRESS && num_insts > 0) {
-EmplaceSafeString(object, "name", frame.GetFunctionName());
+if (line_entry.GetLine() == 0) {
+  EmplaceSafeString(object, "name", "");
+} else {
+  EmplaceSafeString(object, "name", frame.GetDisplayFunctionName());
+}
 SourceReference source;
 llvm::raw_string_ostream src_strm(source.content);
 std::string line;


Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -613,7 +613,9 @@
 llvm::json::Value CreateSource(lldb::SBFrame , int64_t _line) {
   disasm_line = 0;
   auto line_entry = frame.GetLineEntry();
-  if (line_entry.GetFileSpec().IsValid())
+  // A line entry of 0 indicates the line is compiler generated i.e. no source
+  // file so don't return early with the line entry.
+  if (line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0)
 return CreateSource(line_entry);
 
   llvm::json::Object object;
@@ -650,7 +652,11 @@
   }
   const auto num_insts = insts.GetSize();
   if (low_pc != LLDB_INVALID_ADDRESS && num_insts > 0) {
-EmplaceSafeString(object, "name", frame.GetFunctionName());
+if (line_entry.GetLine() == 0) {
+  EmplaceSafeString(object, "name", "");
+} else {
+  EmplaceSafeString(object, "name", frame.GetDisplayFunctionName());
+}
 SourceReference source;
 llvm::raw_string_ostream src_strm(source.content);
 std::string line;
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D154028: [lldb-vscode] Prior to running the launchCommands during a launch request set the launch info so the configured launch information is accessible by the launch commands.

2023-06-29 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGfc52f8dc6ce2: [lldb-vscode] Prior to running the 
launchCommands during a launch request set… (authored by ashgti, committed by 
dgoldman).

Changed prior to commit:
  https://reviews.llvm.org/D154028?vs=535576=535943#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154028/new/

https://reviews.llvm.org/D154028

Files:
  lldb/tools/lldb-vscode/README.md
  lldb/tools/lldb-vscode/lldb-vscode.cpp


Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -1695,6 +1695,9 @@
 g_vsc.target.Launch(launch_info, error);
 g_vsc.debugger.SetAsync(true);
   } else {
+// Set the launch info so that run commands can access the configured
+// launch details.
+g_vsc.target.SetLaunchInfo(launch_info);
 g_vsc.RunLLDBCommands("Running launchCommands:", launchCommands);
 // The custom commands might have created a new target so we should use the
 // selected target after these commands are run.
Index: lldb/tools/lldb-vscode/README.md
===
--- lldb/tools/lldb-vscode/README.md
+++ lldb/tools/lldb-vscode/README.md
@@ -95,6 +95,7 @@
 |**initCommands**   |[string]| | LLDB commands executed upon debugger startup 
prior to creating the LLDB target. Commands and command output will be sent to 
the debugger console when they are executed.
 |**preRunCommands** |[string]| | LLDB commands executed just before launching 
after the LLDB target has been created. Commands and command output will be 
sent to the debugger console when they are executed.
 |**stopCommands**   |[string]| | LLDB commands executed just after each stop. 
Commands and command output will be sent to the debugger console when they are 
executed.
+|**launchCommands** |[string]| | LLDB commands executed to launch the program. 
Commands and command output will be sent to the debugger console when they are 
executed.
 |**exitCommands**   |[string]| | LLDB commands executed when the program 
exits. Commands and command output will be sent to the debugger console when 
they are executed.
 |**terminateCommands** |[string]| | LLDB commands executed when the debugging 
session ends. Commands and command output will be sent to the debugger console 
when they are executed.
 |**sourceMap**  |[string[2]]| | Specify an array of path re-mappings. Each 
element in the array must be a two element array containing a source and 
destination pathname.


Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -1695,6 +1695,9 @@
 g_vsc.target.Launch(launch_info, error);
 g_vsc.debugger.SetAsync(true);
   } else {
+// Set the launch info so that run commands can access the configured
+// launch details.
+g_vsc.target.SetLaunchInfo(launch_info);
 g_vsc.RunLLDBCommands("Running launchCommands:", launchCommands);
 // The custom commands might have created a new target so we should use the
 // selected target after these commands are run.
Index: lldb/tools/lldb-vscode/README.md
===
--- lldb/tools/lldb-vscode/README.md
+++ lldb/tools/lldb-vscode/README.md
@@ -95,6 +95,7 @@
 |**initCommands**   |[string]| | LLDB commands executed upon debugger startup prior to creating the LLDB target. Commands and command output will be sent to the debugger console when they are executed.
 |**preRunCommands** |[string]| | LLDB commands executed just before launching after the LLDB target has been created. Commands and command output will be sent to the debugger console when they are executed.
 |**stopCommands**   |[string]| | LLDB commands executed just after each stop. Commands and command output will be sent to the debugger console when they are executed.
+|**launchCommands** |[string]| | LLDB commands executed to launch the program. Commands and command output will be sent to the debugger console when they are executed.
 |**exitCommands**   |[string]| | LLDB commands executed when the program exits. Commands and command output will be sent to the debugger console when they are executed.
 |**terminateCommands** |[string]| | LLDB commands executed when the debugging session ends. Commands and command output will be sent to the debugger console when they are executed.
 |**sourceMap**  |[string[2]]| | Specify an array of path re-mappings. Each element in the array must be a two element array containing a source and destination pathname.
___
lldb-commits mailing list
lldb-commits@lists.llvm.org

[Lldb-commits] [PATCH] D153447: Creating a startDebugging reverse DAP request handler in lldb-vscode.

2023-06-29 Thread David Goldman via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG227b2180eb2b: Creating a startDebugging reverse DAP request 
handler in lldb-vscode. (authored by ashgti, committed by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D153447/new/

https://reviews.llvm.org/D153447

Files:
  lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
  lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py
  lldb/test/API/tools/lldb-vscode/startDebugging/Makefile
  lldb/test/API/tools/lldb-vscode/startDebugging/TestVSCode_startDebugging.py
  lldb/test/API/tools/lldb-vscode/startDebugging/main.c
  lldb/tools/lldb-vscode/JSONUtils.cpp
  lldb/tools/lldb-vscode/README.md
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -1471,6 +1471,13 @@
 
   g_vsc.debugger =
   lldb::SBDebugger::Create(source_init_file, log_cb, nullptr);
+  auto cmd = g_vsc.debugger.GetCommandInterpreter().AddMultiwordCommand(
+  "lldb-vscode", nullptr);
+  cmd.AddCommand(
+  "startDebugging", _vsc.start_debugging_request_handler,
+  "Sends a startDebugging request from the debug adapter to the client to "
+  "start a child debug session of the same type as the caller.");
+
   g_vsc.progress_event_thread = std::thread(ProgressEventThreadFunction);
 
   // Start our event thread so we can receive events from the debugger, target,
@@ -1564,7 +1571,8 @@
   g_vsc.SendJSON(llvm::json::Value(std::move(response)));
 }
 
-llvm::Error request_runInTerminal(const llvm::json::Object _request) {
+llvm::Error request_runInTerminal(const llvm::json::Object _request,
+  const uint64_t timeout_seconds) {
   g_vsc.is_attach = true;
   lldb::SBAttachInfo attach_info;
 
@@ -1582,13 +1590,15 @@
 #endif
   llvm::json::Object reverse_request = CreateRunInTerminalReverseRequest(
   launch_request, g_vsc.debug_adaptor_path, comm_file.m_path, debugger_pid);
-  llvm::json::Object reverse_response;
-  lldb_vscode::PacketStatus status =
-  g_vsc.SendReverseRequest(reverse_request, reverse_response);
-  if (status != lldb_vscode::PacketStatus::Success)
-return llvm::createStringError(llvm::inconvertibleErrorCode(),
-   "Process cannot be launched by the IDE. %s",
-   comm_channel.GetLauncherError().c_str());
+  g_vsc.SendReverseRequest("runInTerminal", std::move(reverse_request),
+   [](llvm::Expected value) {
+ if (!value) {
+   llvm::Error err = value.takeError();
+   llvm::errs()
+   << "runInTerminal request failed: "
+   << llvm::toString(std::move(err)) << "\n";
+ }
+   });
 
   if (llvm::Expected pid = comm_channel.GetLauncherPid())
 attach_info.SetProcessID(*pid);
@@ -1676,7 +1686,7 @@
   const uint64_t timeout_seconds = GetUnsigned(arguments, "timeout", 30);
 
   if (GetBoolean(arguments, "runInTerminal", false)) {
-if (llvm::Error err = request_runInTerminal(request))
+if (llvm::Error err = request_runInTerminal(request, timeout_seconds))
   error.SetErrorString(llvm::toString(std::move(err)).c_str());
   } else if (launchCommands.empty()) {
 // Disable async events so the launch will be successful when we return from
@@ -3464,17 +3474,13 @@
 g_vsc.output.descriptor = StreamDescriptor::from_file(new_stdout_fd, false);
   }
 
-  while (!g_vsc.sent_terminated_event) {
-llvm::json::Object object;
-lldb_vscode::PacketStatus status = g_vsc.GetNextObject(object);
-if (status == lldb_vscode::PacketStatus::EndOfFile)
-  break;
-if (status != lldb_vscode::PacketStatus::Success)
-  return 1; // Fatal error
-
-if (!g_vsc.HandleObject(object))
-  return 1;
+  bool CleanExit = true;
+  if (auto Err = g_vsc.Loop()) {
+if (g_vsc.log)
+  *g_vsc.log << "Transport Error: " << llvm::toString(std::move(Err))
+ << "\n";
+CleanExit = false;
   }
 
-  return EXIT_SUCCESS;
+  return CleanExit ? EXIT_SUCCESS : EXIT_FAILURE;
 }
Index: lldb/tools/lldb-vscode/VSCode.h
===
--- lldb/tools/lldb-vscode/VSCode.h
+++ lldb/tools/lldb-vscode/VSCode.h
@@ -11,8 +11,10 @@
 
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -73,6 +75,7 @@
 };
 
 typedef void (*RequestCallback)(const llvm::json::Object );
+typedef void (*ResponseCallback)(llvm::Expected