[Lldb-commits] [lldb] 132e57b - Retry of D84974
Walter Erquinigo via lldb-commits
lldb-commits at lists.llvm.org
Mon Sep 14 10:45:19 PDT 2020
Author: Walter Erquinigo
Date: 2020-09-14T10:44:13-07:00
New Revision: 132e57bc597bd3f50174b7d286c43f76b47f11c1
URL: https://github.com/llvm/llvm-project/commit/132e57bc597bd3f50174b7d286c43f76b47f11c1
DIFF: https://github.com/llvm/llvm-project/commit/132e57bc597bd3f50174b7d286c43f76b47f11c1.diff
LOG: Retry of D84974
- Fix a small issue caused by a conflicting name (GetObject) on Windows.
The fix was to rename the internal GetObject function to
GetNextFunction.
Added:
lldb/test/API/tools/lldb-vscode/runInTerminal/Makefile
lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py
lldb/test/API/tools/lldb-vscode/runInTerminal/main.c
Modified:
lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
lldb/tools/lldb-vscode/JSONUtils.cpp
lldb/tools/lldb-vscode/JSONUtils.h
lldb/tools/lldb-vscode/VSCode.cpp
lldb/tools/lldb-vscode/VSCode.h
lldb/tools/lldb-vscode/lldb-vscode.cpp
lldb/tools/lldb-vscode/package.json
Removed:
################################################################################
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
index fa5a9c0db1eb..5710751ec34b 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
@@ -282,7 +282,7 @@ def launch(self, program=None, args=None, cwd=None, env=None,
trace=False, initCommands=None, preRunCommands=None,
stopCommands=None, exitCommands=None, terminateCommands=None,
sourcePath=None, debuggerRoot=None, launchCommands=None,
- sourceMap=None, disconnectAutomatically=True):
+ sourceMap=None, disconnectAutomatically=True, runInTerminal=False):
'''Sending launch request to vscode
'''
@@ -316,10 +316,16 @@ def cleanup():
sourcePath=sourcePath,
debuggerRoot=debuggerRoot,
launchCommands=launchCommands,
- sourceMap=sourceMap)
+ sourceMap=sourceMap,
+ runInTerminal=runInTerminal)
if not (response and response['success']):
self.assertTrue(response['success'],
'launch failed (%s)' % (response['message']))
+ # We need to trigger a request_configurationDone after we've successfully
+ # attached a runInTerminal process to finish initialization.
+ if runInTerminal:
+ self.vscode.request_configurationDone()
+
def build_and_launch(self, program, args=None, cwd=None, env=None,
stopOnEntry=False, disableASLR=True,
@@ -327,7 +333,7 @@ def build_and_launch(self, program, args=None, cwd=None, env=None,
trace=False, initCommands=None, preRunCommands=None,
stopCommands=None, exitCommands=None,
terminateCommands=None, sourcePath=None,
- debuggerRoot=None):
+ debuggerRoot=None, runInTerminal=False):
'''Build the default Makefile target, create the VSCode debug adaptor,
and launch the process.
'''
@@ -337,4 +343,4 @@ def build_and_launch(self, program, args=None, cwd=None, env=None,
self.launch(program, args, cwd, env, stopOnEntry, disableASLR,
disableSTDIO, shellExpandArguments, trace,
initCommands, preRunCommands, stopCommands, exitCommands,
- terminateCommands, sourcePath, debuggerRoot)
+ terminateCommands, sourcePath, debuggerRoot, runInTerminal=runInTerminal)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
index 6b1c1c961b54..834e33ef5c3d 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -300,12 +300,29 @@ def send_recv(self, command):
self.send_packet(command)
done = False
while not done:
- response = self.recv_packet(filter_type='response')
- if response is None:
+ response_or_request = self.recv_packet(filter_type=['response', 'request'])
+ if response_or_request is None:
desc = 'no response for "%s"' % (command['command'])
raise ValueError(desc)
- self.validate_response(command, response)
- return response
+ if response_or_request['type'] == 'response':
+ self.validate_response(command, response_or_request)
+ return response_or_request
+ else:
+ if response_or_request['command'] == 'runInTerminal':
+ subprocess.Popen(response_or_request['arguments']['args'],
+ env=response_or_request['arguments']['env'])
+ self.send_packet({
+ "type": "response",
+ "seq": -1,
+ "request_seq": response_or_request['seq'],
+ "success": True,
+ "command": "runInTerminal",
+ "body": {}
+ }, set_sequence=False)
+ else:
+ desc = 'unkonwn reverse request "%s"' % (response_or_request['command'])
+ raise ValueError(desc)
+
return None
def wait_for_event(self, filter=None, timeout=None):
@@ -599,7 +616,8 @@ def request_launch(self, program, args=None, cwd=None, env=None,
trace=False, initCommands=None, preRunCommands=None,
stopCommands=None, exitCommands=None,
terminateCommands=None ,sourcePath=None,
- debuggerRoot=None, launchCommands=None, sourceMap=None):
+ debuggerRoot=None, launchCommands=None, sourceMap=None,
+ runInTerminal=False):
args_dict = {
'program': program
}
@@ -638,6 +656,8 @@ def request_launch(self, program, args=None, cwd=None, env=None,
args_dict['launchCommands'] = launchCommands
if sourceMap:
args_dict['sourceMap'] = sourceMap
+ if runInTerminal:
+ args_dict['runInTerminal'] = runInTerminal
command_dict = {
'command': 'launch',
'type': 'request',
diff --git a/lldb/test/API/tools/lldb-vscode/runInTerminal/Makefile b/lldb/test/API/tools/lldb-vscode/runInTerminal/Makefile
new file mode 100644
index 000000000000..10495940055b
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/runInTerminal/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py
new file mode 100644
index 000000000000..6a463dfacc1f
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py
@@ -0,0 +1,48 @@
+"""
+Test lldb-vscode runInTerminal reverse request
+"""
+
+
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import time
+import os
+
+
+class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ @skipIfRemote
+ def test_runInTerminal(self):
+ '''
+ Tests the "runInTerminal" reverse request. It makes sure that the IDE can
+ launch the inferior with the correct environment variables and arguments.
+ '''
+ program = self.getBuildArtifact("a.out")
+ source = 'main.c'
+ self.build_and_launch(program, stopOnEntry=True, runInTerminal=True, args=["foobar"], env=["FOO=bar"])
+ breakpoint_line = line_number(source, '// breakpoint')
+
+ self.set_source_breakpoints(source, [breakpoint_line])
+ self.continue_to_next_stop()
+
+ # We verify we actually stopped inside the loop
+ counter = int(self.vscode.get_local_variable_value('counter'))
+ self.assertTrue(counter > 0)
+
+ # We verify we were able to set the launch arguments
+ argc = int(self.vscode.get_local_variable_value('argc'))
+ self.assertEqual(argc, 2)
+
+ argv1 = self.vscode.request_evaluate('argv[1]')['body']['result']
+ self.assertIn('foobar', argv1)
+
+ # We verify we were able to set the environment
+ env = self.vscode.request_evaluate('foo')['body']['result']
+ self.assertIn('bar', env)
diff --git a/lldb/test/API/tools/lldb-vscode/runInTerminal/main.c b/lldb/test/API/tools/lldb-vscode/runInTerminal/main.c
new file mode 100644
index 000000000000..676bd830e657
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/runInTerminal/main.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[]) {
+ const char *foo = getenv("FOO");
+ for (int counter = 1;; counter++) {
+ sleep(1); // breakpoint
+ }
+ return 0;
+}
diff --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp
index 36156ca2c42f..044bfd13ec46 100644
--- a/lldb/tools/lldb-vscode/JSONUtils.cpp
+++ b/lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -998,4 +998,44 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit) {
return llvm::json::Value(std::move(object));
}
+/// See
+/// https://microsoft.github.io/debug-adapter-protocol/specification#Reverse_Requests_RunInTerminal
+llvm::json::Object
+CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request) {
+ llvm::json::Object reverse_request;
+ reverse_request.try_emplace("type", "request");
+ reverse_request.try_emplace("command", "runInTerminal");
+
+ llvm::json::Object run_in_terminal_args;
+ // This indicates the IDE to open an embedded terminal, instead of opening the
+ // terminal in a new window.
+ run_in_terminal_args.try_emplace("kind", "integrated");
+
+ auto launch_request_arguments = launch_request.getObject("arguments");
+ std::vector<std::string> args = GetStrings(launch_request_arguments, "args");
+ // The program path must be the first entry in the "args" field
+ args.insert(args.begin(),
+ GetString(launch_request_arguments, "program").str());
+ run_in_terminal_args.try_emplace("args", args);
+
+ const auto cwd = GetString(launch_request_arguments, "cwd");
+ if (!cwd.empty())
+ run_in_terminal_args.try_emplace("cwd", cwd);
+
+ // We need to convert the input list of environments variables into a
+ // dictionary
+ std::vector<std::string> envs = GetStrings(launch_request_arguments, "env");
+ llvm::json::Object environment;
+ for (const std::string &env : envs) {
+ size_t index = env.find("=");
+ environment.try_emplace(env.substr(0, index), env.substr(index + 1));
+ }
+ run_in_terminal_args.try_emplace("env",
+ llvm::json::Value(std::move(environment)));
+
+ reverse_request.try_emplace(
+ "arguments", llvm::json::Value(std::move(run_in_terminal_args)));
+ return reverse_request;
+}
+
} // namespace lldb_vscode
diff --git a/lldb/tools/lldb-vscode/JSONUtils.h b/lldb/tools/lldb-vscode/JSONUtils.h
index df4428f390ba..88cbef9e5fdd 100644
--- a/lldb/tools/lldb-vscode/JSONUtils.h
+++ b/lldb/tools/lldb-vscode/JSONUtils.h
@@ -443,6 +443,18 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit);
+/// Create a runInTerminal reverse request object
+///
+/// \param[in] launch_request
+/// The original launch_request object whose fields are used to construct
+/// the reverse request object.
+///
+/// \return
+/// A "runInTerminal" JSON object that follows the specification outlined by
+/// Microsoft.
+llvm::json::Object
+CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request);
+
} // namespace lldb_vscode
#endif
diff --git a/lldb/tools/lldb-vscode/VSCode.cpp b/lldb/tools/lldb-vscode/VSCode.cpp
index 537cae786863..9450cdf3132a 100644
--- a/lldb/tools/lldb-vscode/VSCode.cpp
+++ b/lldb/tools/lldb-vscode/VSCode.cpp
@@ -38,7 +38,8 @@ VSCode::VSCode()
{"swift_catch", "Swift Catch", lldb::eLanguageTypeSwift},
{"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false),
- stop_at_entry(false), is_attach(false) {
+ stop_at_entry(false), is_attach(false),
+ reverse_request_seq(0), waiting_for_run_in_terminal(false) {
const char *log_file_path = getenv("LLDBVSCODE_LOG");
#if defined(_WIN32)
// Windows opens stdout and stdin in text mode which converts \n to 13,10
@@ -362,4 +363,71 @@ void VSCode::SetTarget(const lldb::SBTarget target) {
}
}
+PacketStatus VSCode::GetNextObject(llvm::json::Object &object) {
+ std::string json = ReadJSON();
+ if (json.empty())
+ return PacketStatus::EndOfFile;
+
+ llvm::StringRef json_sref(json);
+ llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
+ if (!json_value) {
+ auto error = json_value.takeError();
+ if (log) {
+ std::string error_str;
+ llvm::raw_string_ostream strm(error_str);
+ strm << error;
+ strm.flush();
+ *log << "error: failed to parse JSON: " << error_str << std::endl
+ << json << std::endl;
+ }
+ return PacketStatus::JSONMalformed;
+ }
+ object = *json_value->getAsObject();
+ if (!json_value->getAsObject()) {
+ if (log)
+ *log << "error: json packet isn't a object" << std::endl;
+ return PacketStatus::JSONNotObject;
+ }
+ return PacketStatus::Success;
+}
+
+bool VSCode::HandleObject(const llvm::json::Object &object) {
+ const auto packet_type = GetString(object, "type");
+ if (packet_type == "request") {
+ const auto command = GetString(object, "command");
+ auto handler_pos = request_handlers.find(std::string(command));
+ if (handler_pos != request_handlers.end()) {
+ handler_pos->second(object);
+ return true; // Success
+ } else {
+ if (log)
+ *log << "error: unhandled command \"" << command.data() << std::endl;
+ return false; // Fail
+ }
+ }
+ return false;
+}
+
+PacketStatus VSCode::SendReverseRequest(llvm::json::Object request,
+ llvm::json::Object &response) {
+ request.try_emplace("seq", ++reverse_request_seq);
+ SendJSON(llvm::json::Value(std::move(request)));
+ while (true) {
+ PacketStatus status = GetNextObject(response);
+ const auto packet_type = GetString(response, "type");
+ if (packet_type == "response")
+ return status;
+ else {
+ // Not our response, we got another packet
+ HandleObject(response);
+ }
+ }
+ return PacketStatus::EndOfFile;
+}
+
+void VSCode::RegisterRequestCallback(std::string request,
+ RequestCallback callback) {
+ request_handlers[request] = callback;
+}
+
} // namespace lldb_vscode
diff --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h
index 88a0c08de245..28e9eef13d6b 100644
--- a/lldb/tools/lldb-vscode/VSCode.h
+++ b/lldb/tools/lldb-vscode/VSCode.h
@@ -9,6 +9,7 @@
#ifndef LLDB_TOOLS_LLDB_VSCODE_VSCODE_H
#define LLDB_TOOLS_LLDB_VSCODE_VSCODE_H
+#include <condition_variable>
#include <iosfwd>
#include <map>
#include <set>
@@ -19,6 +20,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/JSON.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/API/SBAttachInfo.h"
@@ -65,6 +67,15 @@ enum class OutputType { Console, Stdout, Stderr, Telemetry };
enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
+typedef void (*RequestCallback)(const llvm::json::Object &command);
+
+enum class PacketStatus {
+ Success = 0,
+ EndOfFile,
+ JSONMalformed,
+ JSONNotObject
+};
+
struct VSCode {
InputStream input;
OutputStream output;
@@ -91,6 +102,10 @@ struct VSCode {
bool sent_terminated_event;
bool stop_at_entry;
bool is_attach;
+ uint32_t reverse_request_seq;
+ std::map<std::string, RequestCallback> request_handlers;
+ std::condition_variable request_in_terminal_cv;
+ bool waiting_for_run_in_terminal;
// Keep track of the last stop thread index IDs as threads won't go away
// unless we send a "thread" event to indicate the thread exited.
llvm::DenseSet<lldb::tid_t> thread_ids;
@@ -152,6 +167,36 @@ struct VSCode {
/// Set given target object as a current target for lldb-vscode and start
/// listeing for its breakpoint events.
void SetTarget(const lldb::SBTarget target);
+
+ const std::map<std::string, RequestCallback> &GetRequestHandlers();
+
+ PacketStatus GetNextObject(llvm::json::Object &object);
+ bool HandleObject(const llvm::json::Object &object);
+
+ /// Send a Debug Adapter Protocol reverse request to the IDE
+ ///
+ /// \param[in] request
+ /// The payload of the request to send.
+ ///
+ /// \param[out] response
+ /// The response of the IDE. It might be undefined if there was an error.
+ ///
+ /// \return
+ /// A \a PacketStatus object indicating the sucess or failure of the
+ /// request.
+ PacketStatus SendReverseRequest(llvm::json::Object request,
+ llvm::json::Object &response);
+
+ /// Registers a callback handler for a Debug Adapter Protocol request
+ ///
+ /// \param[in] request
+ /// The name of the request following the Debug Adapter Protocol
+ /// specification.
+ ///
+ /// \param[in] callback
+ /// The callback to execute when the given request is triggered by the
+ /// IDE.
+ void RegisterRequestCallback(std::string request, RequestCallback callback);
};
extern VSCode g_vsc;
diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 7d7d0f9ebe91..08973ec0f171 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -384,7 +384,12 @@ void EventThreadFunction() {
break;
case lldb::eStateSuspended:
break;
- case lldb::eStateStopped:
+ case lldb::eStateStopped: {
+ if (g_vsc.waiting_for_run_in_terminal) {
+ g_vsc.waiting_for_run_in_terminal = false;
+ g_vsc.request_in_terminal_cv.notify_one();
+ }
+ }
// Only report a stopped event if the process was not restarted.
if (!lldb::SBProcess::GetRestartedFromEvent(event)) {
SendStdOutStdErr(process);
@@ -1374,6 +1379,9 @@ void request_initialize(const llvm::json::Object &request) {
filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
}
body.try_emplace("exceptionBreakpointFilters", std::move(filters));
+ // The debug adapter supports launching a debugee in intergrated VSCode
+ // terminal.
+ body.try_emplace("supportsRunInTerminalRequest", true);
// The debug adapter supports stepping back via the stepBack and
// reverseContinue requests.
body.try_emplace("supportsStepBack", false);
@@ -1433,6 +1441,49 @@ void request_initialize(const llvm::json::Object &request) {
g_vsc.SendJSON(llvm::json::Value(std::move(response)));
}
+void request_runInTerminal(const llvm::json::Object &launch_request,
+ llvm::json::Object &launch_response) {
+ // We have already created a target that has a valid "program" path to the
+ // executable. We will attach to the next process whose name matches that
+ // of the target's.
+ g_vsc.is_attach = true;
+ lldb::SBAttachInfo attach_info;
+ lldb::SBError error;
+ attach_info.SetWaitForLaunch(true, /*async*/ true);
+ g_vsc.target.Attach(attach_info, error);
+
+ llvm::json::Object reverse_request =
+ CreateRunInTerminalReverseRequest(launch_request);
+ llvm::json::Object reverse_response;
+ lldb_vscode::PacketStatus status =
+ g_vsc.SendReverseRequest(reverse_request, reverse_response);
+ if (status != lldb_vscode::PacketStatus::Success)
+ error.SetErrorString("Process cannot be launched by IDE.");
+
+ if (error.Success()) {
+ // Wait for the attach stop event to happen or for a timeout.
+ g_vsc.waiting_for_run_in_terminal = true;
+ static std::mutex mutex;
+ std::unique_lock<std::mutex> locker(mutex);
+ g_vsc.request_in_terminal_cv.wait_for(locker, std::chrono::seconds(10));
+
+ auto attached_pid = g_vsc.target.GetProcess().GetProcessID();
+ if (attached_pid == LLDB_INVALID_PROCESS_ID)
+ error.SetErrorString("Failed to attach to a process");
+ else
+ SendProcessEvent(Attach);
+ }
+
+ if (error.Fail()) {
+ launch_response["success"] = llvm::json::Value(false);
+ EmplaceSafeString(launch_response, "message",
+ std::string(error.GetCString()));
+ } else {
+ launch_response["success"] = llvm::json::Value(true);
+ g_vsc.SendJSON(CreateEventObject("initialized"));
+ }
+}
+
// "LaunchRequest": {
// "allOf": [ { "$ref": "#/definitions/Request" }, {
// "type": "object",
@@ -1505,6 +1556,12 @@ void request_launch(const llvm::json::Object &request) {
return;
}
+ if (GetBoolean(arguments, "runInTerminal", false)) {
+ request_runInTerminal(request, response);
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
+
// Instantiate a launch info instance for the target.
auto launch_info = g_vsc.target.GetLaunchInfo();
@@ -2831,39 +2888,35 @@ void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
g_vsc.SendJSON(llvm::json::Value(std::move(response)));
}
-const std::map<std::string, RequestCallback> &GetRequestHandlers() {
-#define REQUEST_CALLBACK(name) \
- { #name, request_##name }
- static std::map<std::string, RequestCallback> g_request_handlers = {
- // VSCode Debug Adaptor requests
- REQUEST_CALLBACK(attach),
- REQUEST_CALLBACK(completions),
- REQUEST_CALLBACK(continue),
- REQUEST_CALLBACK(configurationDone),
- REQUEST_CALLBACK(disconnect),
- REQUEST_CALLBACK(evaluate),
- REQUEST_CALLBACK(exceptionInfo),
- REQUEST_CALLBACK(getCompileUnits),
- REQUEST_CALLBACK(initialize),
- REQUEST_CALLBACK(launch),
- REQUEST_CALLBACK(next),
- REQUEST_CALLBACK(pause),
- REQUEST_CALLBACK(scopes),
- REQUEST_CALLBACK(setBreakpoints),
- REQUEST_CALLBACK(setExceptionBreakpoints),
- REQUEST_CALLBACK(setFunctionBreakpoints),
- REQUEST_CALLBACK(setVariable),
- REQUEST_CALLBACK(source),
- REQUEST_CALLBACK(stackTrace),
- REQUEST_CALLBACK(stepIn),
- REQUEST_CALLBACK(stepOut),
- REQUEST_CALLBACK(threads),
- REQUEST_CALLBACK(variables),
- // Testing requests
- REQUEST_CALLBACK(_testGetTargetBreakpoints),
- };
-#undef REQUEST_CALLBACK
- return g_request_handlers;
+void RegisterRequestCallbacks() {
+ g_vsc.RegisterRequestCallback("attach", request_attach);
+ g_vsc.RegisterRequestCallback("completions", request_completions);
+ g_vsc.RegisterRequestCallback("continue", request_continue);
+ g_vsc.RegisterRequestCallback("configurationDone", request_configurationDone);
+ g_vsc.RegisterRequestCallback("disconnect", request_disconnect);
+ g_vsc.RegisterRequestCallback("evaluate", request_evaluate);
+ g_vsc.RegisterRequestCallback("exceptionInfo", request_exceptionInfo);
+ g_vsc.RegisterRequestCallback("getCompileUnits", request_getCompileUnits);
+ g_vsc.RegisterRequestCallback("initialize", request_initialize);
+ g_vsc.RegisterRequestCallback("launch", request_launch);
+ g_vsc.RegisterRequestCallback("next", request_next);
+ g_vsc.RegisterRequestCallback("pause", request_pause);
+ g_vsc.RegisterRequestCallback("scopes", request_scopes);
+ g_vsc.RegisterRequestCallback("setBreakpoints", request_setBreakpoints);
+ g_vsc.RegisterRequestCallback("setExceptionBreakpoints",
+ request_setExceptionBreakpoints);
+ g_vsc.RegisterRequestCallback("setFunctionBreakpoints",
+ request_setFunctionBreakpoints);
+ g_vsc.RegisterRequestCallback("setVariable", request_setVariable);
+ g_vsc.RegisterRequestCallback("source", request_source);
+ g_vsc.RegisterRequestCallback("stackTrace", request_stackTrace);
+ g_vsc.RegisterRequestCallback("stepIn", request_stepIn);
+ g_vsc.RegisterRequestCallback("stepOut", request_stepOut);
+ g_vsc.RegisterRequestCallback("threads", request_threads);
+ g_vsc.RegisterRequestCallback("variables", request_variables);
+ // Testing requests
+ g_vsc.RegisterRequestCallback("_testGetTargetBreakpoints",
+ request__testGetTargetBreakpoints);
}
} // anonymous namespace
@@ -2895,6 +2948,8 @@ int main(int argc, char *argv[]) {
// Initialize LLDB first before we do anything.
lldb::SBDebugger::Initialize();
+ RegisterRequestCallbacks();
+
int portno = -1;
LLDBVSCodeOptTable T;
@@ -2937,49 +2992,17 @@ int main(int argc, char *argv[]) {
g_vsc.output.descriptor =
StreamDescriptor::from_file(fileno(stdout), false);
}
- auto request_handlers = GetRequestHandlers();
uint32_t packet_idx = 0;
while (!g_vsc.sent_terminated_event) {
- std::string json = g_vsc.ReadJSON();
- if (json.empty())
+ llvm::json::Object object;
+ lldb_vscode::PacketStatus status = g_vsc.GetObject(object);
+ if (status == lldb_vscode::PacketStatus::EndOfFile)
break;
+ if (status != lldb_vscode::PacketStatus::Success)
+ return 1; // Fatal error
- llvm::StringRef json_sref(json);
- llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
- if (!json_value) {
- auto error = json_value.takeError();
- if (g_vsc.log) {
- std::string error_str;
- llvm::raw_string_ostream strm(error_str);
- strm << error;
- strm.flush();
-
- *g_vsc.log << "error: failed to parse JSON: " << error_str << std::endl
- << json << std::endl;
- }
- return 1;
- }
-
- auto object = json_value->getAsObject();
- if (!object) {
- if (g_vsc.log)
- *g_vsc.log << "error: json packet isn't a object" << std::endl;
+ if (!g_vsc.HandleObject(object))
return 1;
- }
-
- const auto packet_type = GetString(object, "type");
- if (packet_type == "request") {
- const auto command = GetString(object, "command");
- auto handler_pos = request_handlers.find(std::string(command));
- if (handler_pos != request_handlers.end()) {
- handler_pos->second(*object);
- } else {
- if (g_vsc.log)
- *g_vsc.log << "error: unhandled command \"" << command.data()
- << std::endl;
- return 1;
- }
- }
++packet_idx;
}
diff --git a/lldb/tools/lldb-vscode/package.json b/lldb/tools/lldb-vscode/package.json
index 29ca06dd17d6..9077ab51dd7f 100644
--- a/lldb/tools/lldb-vscode/package.json
+++ b/lldb/tools/lldb-vscode/package.json
@@ -175,6 +175,11 @@
"type": "array",
"description": "Commands executed at the end of debugging session.",
"default": []
+ },
+ "runInTerminal": {
+ "type": "boolean",
+ "description": "Launch the program inside an integrated terminal in the IDE. Useful for debugging interactive command line programs",
+ "default": false
}
}
},
More information about the lldb-commits
mailing list