summaryrefslogtreecommitdiff
path: root/tools/lldb-vscode
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lldb-vscode')
-rw-r--r--tools/lldb-vscode/BreakpointBase.cpp37
-rw-r--r--tools/lldb-vscode/BreakpointBase.h44
-rw-r--r--tools/lldb-vscode/CMakeLists.txt34
-rw-r--r--tools/lldb-vscode/ExceptionBreakpoint.cpp32
-rw-r--r--tools/lldb-vscode/ExceptionBreakpoint.h38
-rw-r--r--tools/lldb-vscode/FunctionBreakpoint.cpp28
-rw-r--r--tools/lldb-vscode/FunctionBreakpoint.h29
-rw-r--r--tools/lldb-vscode/JSONUtils.cpp892
-rw-r--r--tools/lldb-vscode/JSONUtils.h438
-rw-r--r--tools/lldb-vscode/LLDBUtils.cpp98
-rw-r--r--tools/lldb-vscode/LLDBUtils.h170
-rw-r--r--tools/lldb-vscode/README.md195
-rw-r--r--tools/lldb-vscode/SourceBreakpoint.cpp27
-rw-r--r--tools/lldb-vscode/SourceBreakpoint.h39
-rw-r--r--tools/lldb-vscode/SourceReference.h33
-rw-r--r--tools/lldb-vscode/VSCode.cpp349
-rw-r--r--tools/lldb-vscode/VSCode.h146
-rw-r--r--tools/lldb-vscode/VSCodeForward.h47
-rw-r--r--tools/lldb-vscode/lldb-vscode-Info.plist21
-rw-r--r--tools/lldb-vscode/lldb-vscode.cpp2706
-rw-r--r--tools/lldb-vscode/package.json242
21 files changed, 0 insertions, 5645 deletions
diff --git a/tools/lldb-vscode/BreakpointBase.cpp b/tools/lldb-vscode/BreakpointBase.cpp
deleted file mode 100644
index adb7abd1a3a1..000000000000
--- a/tools/lldb-vscode/BreakpointBase.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//===-- BreakpointBase.cpp --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "BreakpointBase.h"
-#include "llvm/ADT/StringExtras.h"
-
-using namespace lldb_vscode;
-
-BreakpointBase::BreakpointBase(const llvm::json::Object &obj)
- : condition(GetString(obj, "condition")),
- hitCondition(GetString(obj, "hitCondition")),
- logMessage(GetString(obj, "logMessage")) {}
-
-void BreakpointBase::SetCondition() { bp.SetCondition(condition.c_str()); }
-
-void BreakpointBase::SetHitCondition() {
- uint64_t hitCount = 0;
- if (llvm::to_integer(hitCondition, hitCount))
- bp.SetIgnoreCount(hitCount - 1);
-}
-
-void BreakpointBase::UpdateBreakpoint(const BreakpointBase &request_bp) {
- if (condition != request_bp.condition) {
- condition = request_bp.condition;
- SetCondition();
- }
- if (hitCondition != request_bp.hitCondition) {
- hitCondition = request_bp.hitCondition;
- SetHitCondition();
- }
-}
diff --git a/tools/lldb-vscode/BreakpointBase.h b/tools/lldb-vscode/BreakpointBase.h
deleted file mode 100644
index e27ffe3bd390..000000000000
--- a/tools/lldb-vscode/BreakpointBase.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- BreakpointBase.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_BREAKPOINTBASE_H_
-#define LLDBVSCODE_BREAKPOINTBASE_H_
-
-#include "JSONUtils.h"
-#include "lldb/API/SBBreakpoint.h"
-#include "llvm/Support/JSON.h"
-#include <string>
-
-namespace lldb_vscode {
-
-struct BreakpointBase {
-
- // An optional expression for conditional breakpoints.
- std::string condition;
- // An optional expression that controls how many hits of the breakpoint are
- // ignored. The backend is expected to interpret the expression as needed
- std::string hitCondition;
- // If this attribute exists and is non-empty, the backend must not 'break'
- // (stop) but log the message instead. Expressions within {} are
- // interpolated.
- std::string logMessage;
- // The LLDB breakpoint associated wit this source breakpoint
- lldb::SBBreakpoint bp;
-
- BreakpointBase() = default;
- BreakpointBase(const llvm::json::Object &obj);
-
- void SetCondition();
- void SetHitCondition();
- void UpdateBreakpoint(const BreakpointBase &request_bp);
-};
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/CMakeLists.txt b/tools/lldb-vscode/CMakeLists.txt
deleted file mode 100644
index 08511248d335..000000000000
--- a/tools/lldb-vscode/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-if ( CMAKE_SYSTEM_NAME MATCHES "Windows" OR CMAKE_SYSTEM_NAME MATCHES "NetBSD" )
- add_definitions( -DIMPORT_LIBLLDB )
- list(APPEND extra_libs lldbHost)
-endif ()
-
-if (HAVE_LIBPTHREAD)
- list(APPEND extra_libs pthread)
-endif ()
-
-# We need to include the llvm components we depend on manually, as liblldb does
-# not re-export those.
-set(LLVM_LINK_COMPONENTS Support)
-add_lldb_tool(lldb-vscode
- lldb-vscode.cpp
- BreakpointBase.cpp
- ExceptionBreakpoint.cpp
- FunctionBreakpoint.cpp
- JSONUtils.cpp
- LLDBUtils.cpp
- SourceBreakpoint.cpp
- VSCode.cpp
-
- LINK_LIBS
- liblldb
- ${host_lib}
- ${extra_libs}
-
- LINK_COMPONENTS
- Support
- )
-
-if(LLDB_BUILD_FRAMEWORK)
- lldb_setup_framework_rpaths_in_tool(lldb-vscode)
-endif()
diff --git a/tools/lldb-vscode/ExceptionBreakpoint.cpp b/tools/lldb-vscode/ExceptionBreakpoint.cpp
deleted file mode 100644
index 96bc0930e429..000000000000
--- a/tools/lldb-vscode/ExceptionBreakpoint.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- ExceptionBreakpoint.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ExceptionBreakpoint.h"
-#include "VSCode.h"
-
-namespace lldb_vscode {
-
-void ExceptionBreakpoint::SetBreakpoint() {
- if (bp.IsValid())
- return;
- bool catch_value = filter.find("_catch") != std::string::npos;
- bool throw_value = filter.find("_throw") != std::string::npos;
- bp = g_vsc.target.BreakpointCreateForException(language, catch_value,
- throw_value);
-}
-
-void ExceptionBreakpoint::ClearBreakpoint() {
- if (!bp.IsValid())
- return;
- g_vsc.target.BreakpointDelete(bp.GetID());
- bp = lldb::SBBreakpoint();
-}
-
-} // namespace lldb_vscode
-
diff --git a/tools/lldb-vscode/ExceptionBreakpoint.h b/tools/lldb-vscode/ExceptionBreakpoint.h
deleted file mode 100644
index f3e1e7068095..000000000000
--- a/tools/lldb-vscode/ExceptionBreakpoint.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- ExceptionBreakpoint.h -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_EXCEPTIONBREAKPOINT_H_
-#define LLDBVSCODE_EXCEPTIONBREAKPOINT_H_
-
-#include <string>
-
-#include "lldb/API/SBBreakpoint.h"
-
-namespace lldb_vscode {
-
-struct ExceptionBreakpoint {
- std::string filter;
- std::string label;
- lldb::LanguageType language;
- bool default_value;
- lldb::SBBreakpoint bp;
- ExceptionBreakpoint(std::string f, std::string l, lldb::LanguageType lang) :
- filter(std::move(f)),
- label(std::move(l)),
- language(lang),
- default_value(false),
- bp() {}
-
- void SetBreakpoint();
- void ClearBreakpoint();
-};
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/FunctionBreakpoint.cpp b/tools/lldb-vscode/FunctionBreakpoint.cpp
deleted file mode 100644
index f83333dc9895..000000000000
--- a/tools/lldb-vscode/FunctionBreakpoint.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===-- FunctionBreakpoint.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "FunctionBreakpoint.h"
-#include "VSCode.h"
-
-namespace lldb_vscode {
-
-FunctionBreakpoint::FunctionBreakpoint(const llvm::json::Object &obj)
- : BreakpointBase(obj), functionName(GetString(obj, "name")) {}
-
-void FunctionBreakpoint::SetBreakpoint() {
- if (functionName.empty())
- return;
- bp = g_vsc.target.BreakpointCreateByName(functionName.c_str());
- if (!condition.empty())
- SetCondition();
- if (!hitCondition.empty())
- SetHitCondition();
-}
-
-}
diff --git a/tools/lldb-vscode/FunctionBreakpoint.h b/tools/lldb-vscode/FunctionBreakpoint.h
deleted file mode 100644
index ff4f34dba077..000000000000
--- a/tools/lldb-vscode/FunctionBreakpoint.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===-- FunctionBreakpoint.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_FUNCTIONBREAKPOINT_H_
-#define LLDBVSCODE_FUNCTIONBREAKPOINT_H_
-
-#include "BreakpointBase.h"
-
-namespace lldb_vscode {
-
-struct FunctionBreakpoint : public BreakpointBase {
- std::string functionName;
-
- FunctionBreakpoint() = default;
- FunctionBreakpoint(const llvm::json::Object &obj);
-
- // Set this breakpoint in LLDB as a new breakpoint
- void SetBreakpoint();
-};
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/JSONUtils.cpp b/tools/lldb-vscode/JSONUtils.cpp
deleted file mode 100644
index 76cd44cc72d1..000000000000
--- a/tools/lldb-vscode/JSONUtils.cpp
+++ /dev/null
@@ -1,892 +0,0 @@
-//===-- JSONUtils.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <algorithm>
-
-#include "llvm/Support/FormatAdapters.h"
-
-#include "lldb/API/SBBreakpoint.h"
-#include "lldb/API/SBBreakpointLocation.h"
-#include "lldb/API/SBValue.h"
-#include "lldb/Host/PosixApi.h"
-
-#include "ExceptionBreakpoint.h"
-#include "JSONUtils.h"
-#include "LLDBUtils.h"
-#include "VSCode.h"
-
-namespace lldb_vscode {
-
-void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
- llvm::StringRef str) {
- if (LLVM_LIKELY(llvm::json::isUTF8(str)))
- obj.try_emplace(key, str.str());
- else
- obj.try_emplace(key, llvm::json::fixUTF8(str));
-}
-
-llvm::StringRef GetAsString(const llvm::json::Value &value) {
- if (auto s = value.getAsString())
- return *s;
- return llvm::StringRef();
-}
-
-// Gets a string from a JSON object using the key, or returns an empty string.
-llvm::StringRef GetString(const llvm::json::Object &obj, llvm::StringRef key) {
- if (auto value = obj.getString(key))
- return GetAsString(*value);
- return llvm::StringRef();
-}
-
-llvm::StringRef GetString(const llvm::json::Object *obj, llvm::StringRef key) {
- if (obj == nullptr)
- return llvm::StringRef();
- return GetString(*obj, key);
-}
-
-// Gets an unsigned integer from a JSON object using the key, or returns the
-// specified fail value.
-uint64_t GetUnsigned(const llvm::json::Object &obj, llvm::StringRef key,
- uint64_t fail_value) {
- if (auto value = obj.getInteger(key))
- return (uint64_t)*value;
- return fail_value;
-}
-
-uint64_t GetUnsigned(const llvm::json::Object *obj, llvm::StringRef key,
- uint64_t fail_value) {
- if (obj == nullptr)
- return fail_value;
- return GetUnsigned(*obj, key, fail_value);
-}
-
-bool GetBoolean(const llvm::json::Object &obj, llvm::StringRef key,
- bool fail_value) {
- if (auto value = obj.getBoolean(key))
- return *value;
- if (auto value = obj.getInteger(key))
- return *value != 0;
- return fail_value;
-}
-
-bool GetBoolean(const llvm::json::Object *obj, llvm::StringRef key,
- bool fail_value) {
- if (obj == nullptr)
- return fail_value;
- return GetBoolean(*obj, key, fail_value);
-}
-
-int64_t GetSigned(const llvm::json::Object &obj, llvm::StringRef key,
- int64_t fail_value) {
- if (auto value = obj.getInteger(key))
- return *value;
- return fail_value;
-}
-
-int64_t GetSigned(const llvm::json::Object *obj, llvm::StringRef key,
- int64_t fail_value) {
- if (obj == nullptr)
- return fail_value;
- return GetSigned(*obj, key, fail_value);
-}
-
-bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key) {
- return obj.find(key) != obj.end();
-}
-
-std::vector<std::string> GetStrings(const llvm::json::Object *obj,
- llvm::StringRef key) {
- std::vector<std::string> strs;
- auto json_array = obj->getArray(key);
- if (!json_array)
- return strs;
- for (const auto &value : *json_array) {
- switch (value.kind()) {
- case llvm::json::Value::String:
- strs.push_back(value.getAsString()->str());
- break;
- case llvm::json::Value::Number:
- case llvm::json::Value::Boolean: {
- std::string s;
- llvm::raw_string_ostream strm(s);
- strm << value;
- strs.push_back(strm.str());
- break;
- }
- case llvm::json::Value::Null:
- case llvm::json::Value::Object:
- case llvm::json::Value::Array:
- break;
- }
- }
- return strs;
-}
-
-void SetValueForKey(lldb::SBValue &v, llvm::json::Object &object,
- llvm::StringRef key) {
-
- llvm::StringRef value = v.GetValue();
- llvm::StringRef summary = v.GetSummary();
- llvm::StringRef type_name = v.GetType().GetDisplayTypeName();
-
- std::string result;
- llvm::raw_string_ostream strm(result);
- if (!value.empty()) {
- strm << value;
- if (!summary.empty())
- strm << ' ' << summary;
- } else if (!summary.empty()) {
- strm << ' ' << summary;
- } else if (!type_name.empty()) {
- strm << type_name;
- lldb::addr_t address = v.GetLoadAddress();
- if (address != LLDB_INVALID_ADDRESS)
- strm << " @ " << llvm::format_hex(address, 0);
- }
- strm.flush();
- EmplaceSafeString(object, key, result);
-}
-
-void FillResponse(const llvm::json::Object &request,
- llvm::json::Object &response) {
- // Fill in all of the needed response fields to a "request" and set "success"
- // to true by default.
- response.try_emplace("type", "response");
- response.try_emplace("seq", (int64_t)0);
- EmplaceSafeString(response, "command", GetString(request, "command"));
- const int64_t seq = GetSigned(request, "seq", 0);
- response.try_emplace("request_seq", seq);
- response.try_emplace("success", true);
-}
-
-//----------------------------------------------------------------------
-// "Scope": {
-// "type": "object",
-// "description": "A Scope is a named container for variables. Optionally
-// a scope can map to a source or a range within a source.",
-// "properties": {
-// "name": {
-// "type": "string",
-// "description": "Name of the scope such as 'Arguments', 'Locals'."
-// },
-// "variablesReference": {
-// "type": "integer",
-// "description": "The variables of this scope can be retrieved by
-// passing the value of variablesReference to the
-// VariablesRequest."
-// },
-// "namedVariables": {
-// "type": "integer",
-// "description": "The number of named variables in this scope. The
-// client can use this optional information to present
-// the variables in a paged UI and fetch them in chunks."
-// },
-// "indexedVariables": {
-// "type": "integer",
-// "description": "The number of indexed variables in this scope. The
-// client can use this optional information to present
-// the variables in a paged UI and fetch them in chunks."
-// },
-// "expensive": {
-// "type": "boolean",
-// "description": "If true, the number of variables in this scope is
-// large or expensive to retrieve."
-// },
-// "source": {
-// "$ref": "#/definitions/Source",
-// "description": "Optional source for this scope."
-// },
-// "line": {
-// "type": "integer",
-// "description": "Optional start line of the range covered by this
-// scope."
-// },
-// "column": {
-// "type": "integer",
-// "description": "Optional start column of the range covered by this
-// scope."
-// },
-// "endLine": {
-// "type": "integer",
-// "description": "Optional end line of the range covered by this scope."
-// },
-// "endColumn": {
-// "type": "integer",
-// "description": "Optional end column of the range covered by this
-// scope."
-// }
-// },
-// "required": [ "name", "variablesReference", "expensive" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateScope(const llvm::StringRef name,
- int64_t variablesReference,
- int64_t namedVariables, bool expensive) {
- llvm::json::Object object;
- EmplaceSafeString(object, "name", name.str());
- object.try_emplace("variablesReference", variablesReference);
- object.try_emplace("expensive", expensive);
- object.try_emplace("namedVariables", namedVariables);
- return llvm::json::Value(std::move(object));
-}
-
-//----------------------------------------------------------------------
-// "Breakpoint": {
-// "type": "object",
-// "description": "Information about a Breakpoint created in setBreakpoints
-// or setFunctionBreakpoints.",
-// "properties": {
-// "id": {
-// "type": "integer",
-// "description": "An optional unique identifier for the breakpoint."
-// },
-// "verified": {
-// "type": "boolean",
-// "description": "If true breakpoint could be set (but not necessarily
-// at the desired location)."
-// },
-// "message": {
-// "type": "string",
-// "description": "An optional message about the state of the breakpoint.
-// This is shown to the user and can be used to explain
-// why a breakpoint could not be verified."
-// },
-// "source": {
-// "$ref": "#/definitions/Source",
-// "description": "The source where the breakpoint is located."
-// },
-// "line": {
-// "type": "integer",
-// "description": "The start line of the actual range covered by the
-// breakpoint."
-// },
-// "column": {
-// "type": "integer",
-// "description": "An optional start column of the actual range covered
-// by the breakpoint."
-// },
-// "endLine": {
-// "type": "integer",
-// "description": "An optional end line of the actual range covered by
-// the breakpoint."
-// },
-// "endColumn": {
-// "type": "integer",
-// "description": "An optional end column of the actual range covered by
-// the breakpoint. If no end line is given, then the end
-// column is assumed to be in the start line."
-// }
-// },
-// "required": [ "verified" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateBreakpoint(lldb::SBBreakpointLocation &bp_loc) {
- // 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;
- if (!bp_loc.IsValid())
- return llvm::json::Value(std::move(object));
-
- object.try_emplace("verified", true);
- const auto vs_id = MakeVSCodeBreakpointID(bp_loc);
- object.try_emplace("id", vs_id);
- auto bp_addr = bp_loc.GetAddress();
- if (bp_addr.IsValid()) {
- auto line_entry = bp_addr.GetLineEntry();
- const auto line = line_entry.GetLine();
- if (line != UINT32_MAX)
- object.try_emplace("line", line);
- object.try_emplace("source", CreateSource(line_entry));
- }
- return llvm::json::Value(std::move(object));
-}
-
-void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints) {
- if (!bp.IsValid())
- return;
- const auto num_locations = bp.GetNumLocations();
- if (num_locations == 0)
- return;
- for (size_t i = 0; i < num_locations; ++i) {
- auto bp_loc = bp.GetLocationAtIndex(i);
- breakpoints.emplace_back(CreateBreakpoint(bp_loc));
- }
-}
-
-//----------------------------------------------------------------------
-// "Event": {
-// "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, {
-// "type": "object",
-// "description": "Server-initiated event.",
-// "properties": {
-// "type": {
-// "type": "string",
-// "enum": [ "event" ]
-// },
-// "event": {
-// "type": "string",
-// "description": "Type of event."
-// },
-// "body": {
-// "type": [ "array", "boolean", "integer", "null", "number" ,
-// "object", "string" ],
-// "description": "Event-specific information."
-// }
-// },
-// "required": [ "type", "event" ]
-// }]
-// },
-// "ProtocolMessage": {
-// "type": "object",
-// "description": "Base class of requests, responses, and events.",
-// "properties": {
-// "seq": {
-// "type": "integer",
-// "description": "Sequence number."
-// },
-// "type": {
-// "type": "string",
-// "description": "Message type.",
-// "_enum": [ "request", "response", "event" ]
-// }
-// },
-// "required": [ "seq", "type" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Object CreateEventObject(const llvm::StringRef event_name) {
- llvm::json::Object event;
- event.try_emplace("seq", 0);
- event.try_emplace("type", "event");
- EmplaceSafeString(event, "event", event_name);
- return event;
-}
-
-//----------------------------------------------------------------------
-// "ExceptionBreakpointsFilter": {
-// "type": "object",
-// "description": "An ExceptionBreakpointsFilter is shown in the UI as an
-// option for configuring how exceptions are dealt with.",
-// "properties": {
-// "filter": {
-// "type": "string",
-// "description": "The internal ID of the filter. This value is passed
-// to the setExceptionBreakpoints request."
-// },
-// "label": {
-// "type": "string",
-// "description": "The name of the filter. This will be shown in the UI."
-// },
-// "default": {
-// "type": "boolean",
-// "description": "Initial value of the filter. If not specified a value
-// 'false' is assumed."
-// }
-// },
-// "required": [ "filter", "label" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value
-CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp) {
- llvm::json::Object object;
- EmplaceSafeString(object, "filter", bp.filter);
- EmplaceSafeString(object, "label", bp.label);
- object.try_emplace("default", bp.default_value);
- return llvm::json::Value(std::move(object));
-}
-
-//----------------------------------------------------------------------
-// "Source": {
-// "type": "object",
-// "description": "A Source is a descriptor for source code. It is returned
-// from the debug adapter as part of a StackFrame and it is
-// used by clients when specifying breakpoints.",
-// "properties": {
-// "name": {
-// "type": "string",
-// "description": "The short name of the source. Every source returned
-// from the debug adapter has a name. When sending a
-// source to the debug adapter this name is optional."
-// },
-// "path": {
-// "type": "string",
-// "description": "The path of the source to be shown in the UI. It is
-// only used to locate and load the content of the
-// source if no sourceReference is specified (or its
-// value is 0)."
-// },
-// "sourceReference": {
-// "type": "number",
-// "description": "If sourceReference > 0 the contents of the source must
-// be retrieved through the SourceRequest (even if a path
-// is specified). A sourceReference is only valid for a
-// session, so it must not be used to persist a source."
-// },
-// "presentationHint": {
-// "type": "string",
-// "description": "An optional hint for how to present the source in the
-// UI. A value of 'deemphasize' can be used to indicate
-// that the source is not available or that it is
-// skipped on stepping.",
-// "enum": [ "normal", "emphasize", "deemphasize" ]
-// },
-// "origin": {
-// "type": "string",
-// "description": "The (optional) origin of this source: possible values
-// 'internal module', 'inlined content from source map',
-// etc."
-// },
-// "sources": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Source"
-// },
-// "description": "An optional list of sources that are related to this
-// source. These may be the source that generated this
-// source."
-// },
-// "adapterData": {
-// "type":["array","boolean","integer","null","number","object","string"],
-// "description": "Optional data that a debug adapter might want to loop
-// through the client. The client should leave the data
-// intact and persist it across sessions. The client
-// should not interpret the data."
-// },
-// "checksums": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Checksum"
-// },
-// "description": "The checksums associated with this file."
-// }
-// }
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateSource(lldb::SBLineEntry &line_entry) {
- llvm::json::Object object;
- lldb::SBFileSpec file = line_entry.GetFileSpec();
- if (file.IsValid()) {
- const char *name = file.GetFilename();
- if (name)
- EmplaceSafeString(object, "name", name);
- char path[PATH_MAX] = "";
- file.GetPath(path, sizeof(path));
- if (path[0]) {
- EmplaceSafeString(object, "path", std::string(path));
- }
- }
- return llvm::json::Value(std::move(object));
-}
-
-llvm::json::Value CreateSource(lldb::SBFrame &frame, int64_t &disasm_line) {
- disasm_line = 0;
- auto line_entry = frame.GetLineEntry();
- if (line_entry.GetFileSpec().IsValid())
- return CreateSource(line_entry);
-
- llvm::json::Object object;
- const auto pc = frame.GetPC();
-
- lldb::SBInstructionList insts;
- lldb::SBFunction function = frame.GetFunction();
- lldb::addr_t low_pc = LLDB_INVALID_ADDRESS;
- if (function.IsValid()) {
- low_pc = function.GetStartAddress().GetLoadAddress(g_vsc.target);
- auto addr_srcref = g_vsc.addr_to_source_ref.find(low_pc);
- if (addr_srcref != g_vsc.addr_to_source_ref.end()) {
- // We have this disassembly cached already, return the existing
- // sourceReference
- object.try_emplace("sourceReference", addr_srcref->second);
- disasm_line = g_vsc.GetLineForPC(addr_srcref->second, pc);
- } else {
- insts = function.GetInstructions(g_vsc.target);
- }
- } else {
- lldb::SBSymbol symbol = frame.GetSymbol();
- if (symbol.IsValid()) {
- low_pc = symbol.GetStartAddress().GetLoadAddress(g_vsc.target);
- auto addr_srcref = g_vsc.addr_to_source_ref.find(low_pc);
- if (addr_srcref != g_vsc.addr_to_source_ref.end()) {
- // We have this disassembly cached already, return the existing
- // sourceReference
- object.try_emplace("sourceReference", addr_srcref->second);
- disasm_line = g_vsc.GetLineForPC(addr_srcref->second, pc);
- } else {
- insts = symbol.GetInstructions(g_vsc.target);
- }
- }
- }
- const auto num_insts = insts.GetSize();
- if (low_pc != LLDB_INVALID_ADDRESS && num_insts > 0) {
- EmplaceSafeString(object, "name", frame.GetFunctionName());
- SourceReference source;
- llvm::raw_string_ostream src_strm(source.content);
- std::string line;
- for (size_t i = 0; i < num_insts; ++i) {
- lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);
- const auto inst_addr = inst.GetAddress().GetLoadAddress(g_vsc.target);
- const char *m = inst.GetMnemonic(g_vsc.target);
- const char *o = inst.GetOperands(g_vsc.target);
- const char *c = inst.GetComment(g_vsc.target);
- if (pc == inst_addr)
- disasm_line = i + 1;
- const auto inst_offset = inst_addr - low_pc;
- int spaces = 0;
- if (inst_offset < 10)
- spaces = 3;
- else if (inst_offset < 100)
- spaces = 2;
- else if (inst_offset < 1000)
- spaces = 1;
- line.clear();
- llvm::raw_string_ostream line_strm(line);
- line_strm << llvm::formatv("{0:X+}: <{1}> {2} {3,12} {4}", inst_addr,
- inst_offset, llvm::fmt_repeat(' ', spaces), m,
- o);
-
- // If there is a comment append it starting at column 60 or after one
- // space past the last char
- const uint32_t comment_row = std::max(line_strm.str().size(), (size_t)60);
- if (c && c[0]) {
- if (line.size() < comment_row)
- line_strm.indent(comment_row - line_strm.str().size());
- line_strm << " # " << c;
- }
- src_strm << line_strm.str() << "\n";
- source.addr_to_line[inst_addr] = i + 1;
- }
- // Flush the source stream
- src_strm.str();
- auto sourceReference = VSCode::GetNextSourceReference();
- g_vsc.source_map[sourceReference] = std::move(source);
- g_vsc.addr_to_source_ref[low_pc] = sourceReference;
- object.try_emplace("sourceReference", sourceReference);
- }
- return llvm::json::Value(std::move(object));
-}
-
-//----------------------------------------------------------------------
-// "StackFrame": {
-// "type": "object",
-// "description": "A Stackframe contains the source location.",
-// "properties": {
-// "id": {
-// "type": "integer",
-// "description": "An identifier for the stack frame. It must be unique
-// across all threads. This id can be used to retrieve
-// the scopes of the frame with the 'scopesRequest' or
-// to restart the execution of a stackframe."
-// },
-// "name": {
-// "type": "string",
-// "description": "The name of the stack frame, typically a method name."
-// },
-// "source": {
-// "$ref": "#/definitions/Source",
-// "description": "The optional source of the frame."
-// },
-// "line": {
-// "type": "integer",
-// "description": "The line within the file of the frame. If source is
-// null or doesn't exist, line is 0 and must be ignored."
-// },
-// "column": {
-// "type": "integer",
-// "description": "The column within the line. If source is null or
-// doesn't exist, column is 0 and must be ignored."
-// },
-// "endLine": {
-// "type": "integer",
-// "description": "An optional end line of the range covered by the
-// stack frame."
-// },
-// "endColumn": {
-// "type": "integer",
-// "description": "An optional end column of the range covered by the
-// stack frame."
-// },
-// "moduleId": {
-// "type": ["integer", "string"],
-// "description": "The module associated with this frame, if any."
-// },
-// "presentationHint": {
-// "type": "string",
-// "enum": [ "normal", "label", "subtle" ],
-// "description": "An optional hint for how to present this frame in
-// the UI. A value of 'label' can be used to indicate
-// that the frame is an artificial frame that is used
-// as a visual label or separator. A value of 'subtle'
-// can be used to change the appearance of a frame in
-// a 'subtle' way."
-// }
-// },
-// "required": [ "id", "name", "line", "column" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateStackFrame(lldb::SBFrame &frame) {
- llvm::json::Object object;
- int64_t frame_id = MakeVSCodeFrameID(frame);
- object.try_emplace("id", frame_id);
- EmplaceSafeString(object, "name", frame.GetFunctionName());
- int64_t disasm_line = 0;
- object.try_emplace("source", CreateSource(frame, disasm_line));
-
- auto line_entry = frame.GetLineEntry();
- if (disasm_line > 0) {
- object.try_emplace("line", disasm_line);
- } else {
- auto line = line_entry.GetLine();
- if (line == UINT32_MAX)
- line = 0;
- object.try_emplace("line", line);
- }
- object.try_emplace("column", line_entry.GetColumn());
- return llvm::json::Value(std::move(object));
-}
-
-//----------------------------------------------------------------------
-// "Thread": {
-// "type": "object",
-// "description": "A Thread",
-// "properties": {
-// "id": {
-// "type": "integer",
-// "description": "Unique identifier for the thread."
-// },
-// "name": {
-// "type": "string",
-// "description": "A name of the thread."
-// }
-// },
-// "required": [ "id", "name" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateThread(lldb::SBThread &thread) {
- 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);
- } else {
- EmplaceSafeString(object, "name", std::string(thread_str));
- }
- return llvm::json::Value(std::move(object));
-}
-
-//----------------------------------------------------------------------
-// "StoppedEvent": {
-// "allOf": [ { "$ref": "#/definitions/Event" }, {
-// "type": "object",
-// "description": "Event message for 'stopped' event type. The event
-// indicates that the execution of the debuggee has stopped
-// due to some condition. This can be caused by a break
-// point previously set, a stepping action has completed,
-// by executing a debugger statement etc.",
-// "properties": {
-// "event": {
-// "type": "string",
-// "enum": [ "stopped" ]
-// },
-// "body": {
-// "type": "object",
-// "properties": {
-// "reason": {
-// "type": "string",
-// "description": "The reason for the event. For backward
-// compatibility this string is shown in the UI if
-// the 'description' attribute is missing (but it
-// must not be translated).",
-// "_enum": [ "step", "breakpoint", "exception", "pause", "entry" ]
-// },
-// "description": {
-// "type": "string",
-// "description": "The full reason for the event, e.g. 'Paused
-// on exception'. This string is shown in the UI
-// as is."
-// },
-// "threadId": {
-// "type": "integer",
-// "description": "The thread which was stopped."
-// },
-// "text": {
-// "type": "string",
-// "description": "Additional information. E.g. if reason is
-// 'exception', text contains the exception name.
-// This string is shown in the UI."
-// },
-// "allThreadsStopped": {
-// "type": "boolean",
-// "description": "If allThreadsStopped is true, a debug adapter
-// can announce that all threads have stopped.
-// The client should use this information to
-// enable that all threads can be expanded to
-// access their stacktraces. If the attribute
-// is missing or false, only the thread with the
-// given threadId can be expanded."
-// }
-// },
-// "required": [ "reason" ]
-// }
-// },
-// "required": [ "event", "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateThreadStopped(lldb::SBThread &thread,
- uint32_t stop_id) {
- llvm::json::Object event(CreateEventObject("stopped"));
- llvm::json::Object body;
- switch (thread.GetStopReason()) {
- case lldb::eStopReasonTrace:
- case lldb::eStopReasonPlanComplete:
- body.try_emplace("reason", "step");
- break;
- case lldb::eStopReasonBreakpoint: {
- ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
- if (exc_bp) {
- body.try_emplace("reason", "exception");
- EmplaceSafeString(body, "description", exc_bp->label);
- } else {
- body.try_emplace("reason", "breakpoint");
- }
- } break;
- case lldb::eStopReasonWatchpoint:
- case lldb::eStopReasonInstrumentation:
- body.try_emplace("reason", "breakpoint");
- break;
- case lldb::eStopReasonSignal:
- body.try_emplace("reason", "exception");
- break;
- case lldb::eStopReasonException:
- body.try_emplace("reason", "exception");
- break;
- case lldb::eStopReasonExec:
- body.try_emplace("reason", "entry");
- break;
- case lldb::eStopReasonThreadExiting:
- case lldb::eStopReasonInvalid:
- case lldb::eStopReasonNone:
- break;
- }
- if (stop_id == 0)
- body.try_emplace("reason", "entry");
- const lldb::tid_t tid = thread.GetThreadID();
- body.try_emplace("threadId", (int64_t)tid);
- // If no description has been set, then set it to the default thread stopped
- // description. If we have breakpoints that get hit and shouldn't be reported
- // as breakpoints, then they will set the description above.
- if (ObjectContainsKey(body, "description")) {
- char description[1024];
- if (thread.GetStopDescription(description, sizeof(description))) {
- EmplaceSafeString(body, "description", std::string(description));
- }
- }
- if (tid == g_vsc.focus_tid) {
- body.try_emplace("threadCausedFocus", true);
- }
- body.try_emplace("preserveFocusHint", tid != g_vsc.focus_tid);
- body.try_emplace("allThreadsStopped", true);
- event.try_emplace("body", std::move(body));
- return llvm::json::Value(std::move(event));
-}
-
-//----------------------------------------------------------------------
-// "Variable": {
-// "type": "object",
-// "description": "A Variable is a name/value pair. Optionally a variable
-// can have a 'type' that is shown if space permits or when
-// hovering over the variable's name. An optional 'kind' is
-// used to render additional properties of the variable,
-// e.g. different icons can be used to indicate that a
-// variable is public or private. If the value is
-// structured (has children), a handle is provided to
-// retrieve the children with the VariablesRequest. If
-// the number of named or indexed children is large, the
-// numbers should be returned via the optional
-// 'namedVariables' and 'indexedVariables' attributes. The
-// client can use this optional information to present the
-// children in a paged UI and fetch them in chunks.",
-// "properties": {
-// "name": {
-// "type": "string",
-// "description": "The variable's name."
-// },
-// "value": {
-// "type": "string",
-// "description": "The variable's value. This can be a multi-line text,
-// e.g. for a function the body of a function."
-// },
-// "type": {
-// "type": "string",
-// "description": "The type of the variable's value. Typically shown in
-// the UI when hovering over the value."
-// },
-// "presentationHint": {
-// "$ref": "#/definitions/VariablePresentationHint",
-// "description": "Properties of a variable that can be used to determine
-// how to render the variable in the UI."
-// },
-// "evaluateName": {
-// "type": "string",
-// "description": "Optional evaluatable name of this variable which can
-// be passed to the 'EvaluateRequest' to fetch the
-// variable's value."
-// },
-// "variablesReference": {
-// "type": "integer",
-// "description": "If variablesReference is > 0, the variable is
-// structured and its children can be retrieved by
-// passing variablesReference to the VariablesRequest."
-// },
-// "namedVariables": {
-// "type": "integer",
-// "description": "The number of named child variables. The client can
-// use this optional information to present the children
-// in a paged UI and fetch them in chunks."
-// },
-// "indexedVariables": {
-// "type": "integer",
-// "description": "The number of indexed child variables. The client
-// can use this optional information to present the
-// children in a paged UI and fetch them in chunks."
-// }
-// },
-// "required": [ "name", "value", "variablesReference" ]
-// }
-//----------------------------------------------------------------------
-llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
- int64_t varID, bool format_hex) {
- llvm::json::Object object;
- auto name = v.GetName();
- EmplaceSafeString(object, "name", name ? name : "<null>");
- if (format_hex)
- v.SetFormat(lldb::eFormatHex);
- SetValueForKey(v, object, "value");
- auto type_cstr = v.GetType().GetDisplayTypeName();
- EmplaceSafeString(object, "type", type_cstr ? type_cstr : NO_TYPENAME);
- if (varID != INT64_MAX)
- object.try_emplace("id", varID);
- if (v.MightHaveChildren())
- object.try_emplace("variablesReference", variablesReference);
- else
- object.try_emplace("variablesReference", (int64_t)0);
- lldb::SBStream evaluateStream;
- v.GetExpressionPath(evaluateStream);
- const char *evaluateName = evaluateStream.GetData();
- if (evaluateName && evaluateName[0])
- EmplaceSafeString(object, "evaluateName", std::string(evaluateName));
- return llvm::json::Value(std::move(object));
-}
-
-} // namespace lldb_vscode
-
diff --git a/tools/lldb-vscode/JSONUtils.h b/tools/lldb-vscode/JSONUtils.h
deleted file mode 100644
index 0ca000ce9385..000000000000
--- a/tools/lldb-vscode/JSONUtils.h
+++ /dev/null
@@ -1,438 +0,0 @@
-//===-- JSONUtils.h ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_JSONUTILS_H_
-#define LLDBVSCODE_JSONUTILS_H_
-
-#include <stdint.h>
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/JSON.h"
-#include "VSCodeForward.h"
-
-namespace lldb_vscode {
-
-//------------------------------------------------------------------
-/// Emplace a StringRef in a json::Object after enusring that the
-/// string is valid UTF8. If not, first call llvm::json::fixUTF8
-/// before emplacing.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to emplace the value in
-///
-/// @param[in] key
-/// The key to use when emplacing the value
-///
-/// @param[in] str
-/// The string to emplace
-//------------------------------------------------------------------
-void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
- llvm::StringRef str);
-
-//------------------------------------------------------------------
-/// Extract simple values as a string.
-///
-/// @param[in] value
-/// A JSON value to extract the string from.
-///
-/// @return
-/// A llvm::StringRef that contains the string value, or an empty
-/// string if \a value isn't a string.
-//------------------------------------------------------------------
-llvm::StringRef GetAsString(const llvm::json::Value &value);
-
-//------------------------------------------------------------------
-/// Extract the string value for the specified key from the
-/// specified object.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to extract the value from
-///
-/// @param[in] key
-/// The key to use when extracting the value
-///
-/// @return
-/// A llvm::StringRef that contains the string value for the
-/// specified \a key, or an empty string if there is no key that
-/// matches or if the value is not a string.
-//------------------------------------------------------------------
-llvm::StringRef GetString(const llvm::json::Object &obj, llvm::StringRef key);
-llvm::StringRef GetString(const llvm::json::Object *obj, llvm::StringRef key);
-
-//------------------------------------------------------------------
-/// Extract the unsigned integer value for the specified key from
-/// the specified object.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to extract the value from
-///
-/// @param[in] key
-/// The key to use when extracting the value
-///
-/// @return
-/// The unsigned integer value for the specified \a key, or
-/// \a fail_value if there is no key that matches or if the
-/// value is not an integer.
-//------------------------------------------------------------------
-uint64_t GetUnsigned(const llvm::json::Object &obj, llvm::StringRef key,
- uint64_t fail_value);
-uint64_t GetUnsigned(const llvm::json::Object *obj, llvm::StringRef key,
- uint64_t fail_value);
-
-//------------------------------------------------------------------
-/// Extract the boolean value for the specified key from the
-/// specified object.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to extract the value from
-///
-/// @param[in] key
-/// The key to use when extracting the value
-///
-/// @return
-/// The boolean value for the specified \a key, or \a fail_value
-/// if there is no key that matches or if the value is not a
-/// boolean value of an integer.
-//------------------------------------------------------------------
-bool GetBoolean(const llvm::json::Object &obj, llvm::StringRef key,
- bool fail_value);
-bool GetBoolean(const llvm::json::Object *obj, llvm::StringRef key,
- bool fail_value);
-
-//------------------------------------------------------------------
-/// Extract the signed integer for the specified key from the
-/// specified object.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to extract the value from
-///
-/// @param[in] key
-/// The key to use when extracting the value
-///
-/// @return
-/// The signed integer value for the specified \a key, or
-/// \a fail_value if there is no key that matches or if the
-/// value is not an integer.
-//------------------------------------------------------------------
-int64_t GetSigned(const llvm::json::Object &obj, llvm::StringRef key,
- int64_t fail_value);
-int64_t GetSigned(const llvm::json::Object *obj, llvm::StringRef key,
- int64_t fail_value);
-
-//------------------------------------------------------------------
-/// Check if the specified key exists in the specified object.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to extract the value from
-///
-/// @param[in] key
-/// The key to check for
-///
-/// @return
-/// \b True if the key exists in the \a obj, \b False otherwise.
-//------------------------------------------------------------------
-bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key);
-
-//------------------------------------------------------------------
-/// Extract an array of strings for the specified key from an object.
-///
-/// String values in the array will be extracted without any quotes
-/// around them. Numbers and Booleans will be converted into
-/// strings. Any NULL, array or objects values in the array will be
-/// ignored.
-///
-/// @param[in] obj
-/// A JSON object that we will attempt to extract the array from
-///
-/// @param[in] key
-/// The key to use when extracting the value
-///
-/// @return
-/// An array of string values for the specified \a key, or
-/// \a fail_value if there is no key that matches or if the
-/// value is not an array or all items in the array are not
-/// strings, numbers or booleans.
-//------------------------------------------------------------------
-std::vector<std::string> GetStrings(const llvm::json::Object *obj,
- llvm::StringRef key);
-
-//------------------------------------------------------------------
-/// Fill a response object given the request object.
-///
-/// The \a response object will get its "type" set to "response",
-/// the "seq" set to zero, "response_seq" set to the "seq" value from
-/// \a request, "command" set to the "command" from \a request,
-/// and "success" set to true.
-///
-/// @param[in] request
-/// The request object received from a call to VSCode::ReadJSON().
-///
-/// @param[in,out] response
-/// An empty llvm::json::Object object that will be filled
-/// in as noted in description.
-//------------------------------------------------------------------
-void FillResponse(const llvm::json::Object &request,
- llvm::json::Object &response);
-
-//----------------------------------------------------------------------
-/// Emplace the string value from an SBValue into the supplied object
-/// using \a key as the key that will contain the value.
-///
-/// The value is what we will display in VS Code. Some SBValue objects
-/// can have a value and/or a summary. If a value has both, we
-/// combine the value and the summary into one string. If we only have a
-/// value or summary, then that is considered the value. If there is
-/// no value and no summary then the value is the type name followed by
-/// the address of the type if it has an address.
-///
-///
-/// @param[in] v
-/// A lldb::SBValue object to extract the string value from
-///
-///
-/// @param[in] object
-/// The object to place the value object into
-///
-///
-/// @param[in] key
-/// The key name to use when inserting the value object we create
-//----------------------------------------------------------------------
-void SetValueForKey(lldb::SBValue &v, llvm::json::Object &object,
- llvm::StringRef key);
-
-//----------------------------------------------------------------------
-/// Converts \a bp to a JSON value and appends all locations to the
-/// \a breakpoints array.
-///
-/// @param[in] bp
-/// A LLDB breakpoint object which will get all locations extracted
-/// and converted into a JSON objects in the \a breakpoints array
-///
-/// @param[in] breakpoints
-/// A JSON array that will get a llvm::json::Value for \a bp
-/// appended to it.
-//----------------------------------------------------------------------
-void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints);
-
-//----------------------------------------------------------------------
-/// Converts breakpoint location to a Visual Studio Code "Breakpoint"
-/// JSON object and appends it to the \a breakpoints array.
-///
-/// @param[in] bp_loc
-/// A LLDB breakpoint location object to convert into a JSON value
-///
-/// @return
-/// A "Breakpoint" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateBreakpoint(lldb::SBBreakpointLocation &bp_loc);
-
-//----------------------------------------------------------------------
-/// Create a "Event" JSON object using \a event_name as the event name
-///
-/// @param[in] event_name
-/// The string value to use for the "event" key in the JSON object.
-///
-/// @return
-/// A "Event" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Object CreateEventObject(const llvm::StringRef event_name);
-
-//----------------------------------------------------------------------
-/// Create a "ExceptionBreakpointsFilter" JSON object as described in
-/// the Visual Studio Code debug adaptor definition.
-///
-/// @param[in] bp
-/// The exception breakppoint object to use
-///
-/// @return
-/// A "ExceptionBreakpointsFilter" JSON object with that follows
-/// the formal JSON definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value
-CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp);
-
-//----------------------------------------------------------------------
-/// Create a "Scope" JSON object as described in the Visual Studio Code
-/// debug adaptor definition.
-///
-/// @param[in] name
-/// The value to place into the "name" key
-//
-/// @param[in] variablesReference
-/// The value to place into the "variablesReference" key
-//
-/// @param[in] namedVariables
-/// The value to place into the "namedVariables" key
-//
-/// @param[in] expensive
-/// The value to place into the "expensive" key
-///
-/// @return
-/// A "Scope" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateScope(const llvm::StringRef name,
- int64_t variablesReference,
- int64_t namedVariables, bool expensive);
-
-//----------------------------------------------------------------------
-/// Create a "Source" JSON object as described in the Visual Studio Code
-/// debug adaptor definition.
-///
-/// @param[in] line_entry
-/// The LLDB line table to use when populating out the "Source"
-/// object
-///
-/// @return
-/// A "Source" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateSource(lldb::SBLineEntry &line_entry);
-
-//----------------------------------------------------------------------
-/// Create a "Source" object for a given frame.
-///
-/// When there is no source file information for a stack frame, we will
-/// create disassembly for a function and store a permanent
-/// "sourceReference" that contains the textual disassembly for a
-/// function along with address to line information. The "Source" object
-/// that is created will contain a "sourceReference" that the VSCode
-/// protocol can later fetch as text in order to display disassembly.
-/// The PC will be extracted from the frame and the disassembly line
-/// within the source referred to by "sourceReference" will be filled
-/// in.
-///
-/// @param[in] frame
-/// The LLDB stack frame to use when populating out the "Source"
-/// object.
-///
-/// @param[out] disasm_line
-/// The line within the "sourceReference" file that the PC from
-/// \a frame matches.
-///
-/// @return
-/// A "Source" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateSource(lldb::SBFrame &frame, int64_t &disasm_line);
-
-//----------------------------------------------------------------------
-/// Create a "StackFrame" object for a LLDB frame object.
-///
-/// This function will fill in the following keys in the returned
-/// object:
-/// "id" - the stack frame ID as an integer
-/// "name" - the function name as a string
-/// "source" - source file information as a "Source" VSCode object
-/// "line" - the source file line number as an integer
-/// "column" - the source file column number as an integer
-///
-/// @param[in] frame
-/// The LLDB stack frame to use when populating out the "StackFrame"
-/// object.
-///
-/// @return
-/// A "StackFrame" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateStackFrame(lldb::SBFrame &frame);
-
-//----------------------------------------------------------------------
-/// Create a "Thread" object for a LLDB thread object.
-///
-/// This function will fill in the following keys in the returned
-/// object:
-/// "id" - the thread ID as an integer
-/// "name" - the thread name as a string which combines the LLDB
-/// thread index ID along with the string name of the thread
-/// from the OS if it has a name.
-///
-/// @param[in] thread
-/// The LLDB thread to use when populating out the "Thread"
-/// object.
-///
-/// @return
-/// A "Thread" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateThread(lldb::SBThread &thread);
-
-//----------------------------------------------------------------------
-/// Create a "StoppedEvent" object for a LLDB thread object.
-///
-/// This function will fill in the following keys in the returned
-/// object's "body" object:
-/// "reason" - With a valid stop reason enumeration string value
-/// that Microsoft specifies
-/// "threadId" - The thread ID as an integer
-/// "description" - a stop description (like "breakpoint 12.3") as a
-/// string
-/// "preserveFocusHint" - a boolean value that states if this thread
-/// should keep the focus in the GUI.
-/// "allThreadsStopped" - set to True to indicate that all threads
-/// stop when any thread stops.
-///
-/// @param[in] thread
-/// The LLDB thread to use when populating out the "StoppedEvent"
-/// object.
-///
-/// @return
-/// A "StoppedEvent" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, uint32_t stop_id);
-
-//----------------------------------------------------------------------
-/// Create a "Variable" object for a LLDB thread object.
-///
-/// This function will fill in the following keys in the returned
-/// object:
-/// "name" - the name of the variable
-/// "value" - the value of the variable as a string
-/// "type" - the typename of the variable as a string
-/// "id" - a unique identifier for a value in case there are multiple
-/// variables with the same name. Other parts of the VSCode
-/// protocol refer to values by name so this can help
-/// disambiguate such cases if a IDE passes this "id" value
-/// back down.
-/// "variablesReference" - Zero if the variable has no children,
-/// non-zero integer otherwise which can be used to expand
-/// the variable.
-/// "evaluateName" - The name of the variable to use in expressions
-/// as a string.
-///
-/// @param[in] v
-/// The LLDB value to use when populating out the "Variable"
-/// object.
-///
-/// @param[in] variablesReference
-/// The variable reference. Zero if this value isn't structured
-/// and has no children, non-zero if it does have children and
-/// might be asked to expand itself.
-///
-/// @param[in] varID
-/// A unique variable identifier to help in properly identifying
-/// variables with the same name. This is an extension to the
-/// VS protocol.
-///
-/// @param[in] format_hex
-/// It set to true the variable will be formatted as hex in
-/// the "value" key value pair for the value of the variable.
-///
-/// @return
-/// A "Variable" JSON object with that follows the formal JSON
-/// definition outlined by Microsoft.
-//----------------------------------------------------------------------
-llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
- int64_t varID, bool format_hex);
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/LLDBUtils.cpp b/tools/lldb-vscode/LLDBUtils.cpp
deleted file mode 100644
index 9653522a2d3a..000000000000
--- a/tools/lldb-vscode/LLDBUtils.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===-- LLDBUtils.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LLDBUtils.h"
-#include "VSCode.h"
-
-namespace lldb_vscode {
-
-void RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands,
- llvm::raw_ostream &strm) {
- if (commands.empty())
- return;
- lldb::SBCommandInterpreter interp = g_vsc.debugger.GetCommandInterpreter();
- if (!prefix.empty())
- strm << prefix << "\n";
- for (const auto &command : commands) {
- lldb::SBCommandReturnObject result;
- strm << "(lldb) " << command << "\n";
- interp.HandleCommand(command.c_str(), result);
- auto output_len = result.GetOutputSize();
- if (output_len) {
- const char *output = result.GetOutput();
- strm << output;
- }
- auto error_len = result.GetErrorSize();
- if (error_len) {
- const char *error = result.GetError();
- strm << error;
- }
- }
-}
-
-std::string RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands) {
- std::string s;
- llvm::raw_string_ostream strm(s);
- RunLLDBCommands(prefix, commands, strm);
- strm.flush();
- return s;
-}
-
-bool ThreadHasStopReason(lldb::SBThread &thread) {
- switch (thread.GetStopReason()) {
- case lldb::eStopReasonTrace:
- case lldb::eStopReasonPlanComplete:
- case lldb::eStopReasonBreakpoint:
- case lldb::eStopReasonWatchpoint:
- case lldb::eStopReasonInstrumentation:
- case lldb::eStopReasonSignal:
- case lldb::eStopReasonException:
- case lldb::eStopReasonExec:
- return true;
- case lldb::eStopReasonThreadExiting:
- case lldb::eStopReasonInvalid:
- case lldb::eStopReasonNone:
- break;
- }
- return false;
-}
-
-static uint32_t constexpr THREAD_INDEX_SHIFT = 19;
-
-uint32_t GetLLDBThreadIndexID(uint64_t dap_frame_id) {
- return dap_frame_id >> THREAD_INDEX_SHIFT;
-}
-
-uint32_t GetLLDBFrameID(uint64_t dap_frame_id) {
- return dap_frame_id & ((1u << THREAD_INDEX_SHIFT) - 1);
-}
-
-int64_t MakeVSCodeFrameID(lldb::SBFrame &frame) {
- return (int64_t)(frame.GetThread().GetIndexID() << THREAD_INDEX_SHIFT |
- frame.GetFrameID());
-}
-
-static uint32_t constexpr BREAKPOINT_ID_SHIFT = 22;
-
-uint32_t GetLLDBBreakpointID(uint64_t dap_breakpoint_id) {
- return dap_breakpoint_id >> BREAKPOINT_ID_SHIFT;
-}
-
-uint32_t GetLLDBBreakpointLocationID(uint64_t dap_breakpoint_id) {
- return dap_breakpoint_id & ((1u << BREAKPOINT_ID_SHIFT) - 1);
-}
-
-int64_t MakeVSCodeBreakpointID(lldb::SBBreakpointLocation &bp_loc) {
- return (int64_t)(bp_loc.GetBreakpoint().GetID() << BREAKPOINT_ID_SHIFT |
- bp_loc.GetID());
-}
-
-} // namespace lldb_vscode
diff --git a/tools/lldb-vscode/LLDBUtils.h b/tools/lldb-vscode/LLDBUtils.h
deleted file mode 100644
index 96ebb85f14b1..000000000000
--- a/tools/lldb-vscode/LLDBUtils.h
+++ /dev/null
@@ -1,170 +0,0 @@
-//===-- LLDBUtils.h ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_LLDBUTILS_H_
-#define LLDBVSCODE_LLDBUTILS_H_
-
-#include "VSCodeForward.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-#include <vector>
-
-namespace lldb_vscode {
-
-///----------------------------------------------------------------------
-/// Run a list of LLDB commands in the LLDB command interpreter.
-///
-/// All output from every command, including the prompt + the command
-/// is placed into the "strm" argument.
-///
-/// @param[in] prefix
-/// A string that will be printed into \a strm prior to emitting
-/// the prompt + command and command output. Can be NULL.
-///
-/// @param[in] commands
-/// An array of LLDB commands to execute.
-///
-/// @param[in] strm
-/// The stream that will receive the prefix, prompt + command and
-/// all command output.
-//----------------------------------------------------------------------
-void RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands,
- llvm::raw_ostream &strm);
-
-///----------------------------------------------------------------------
-/// Run a list of LLDB commands in the LLDB command interpreter.
-///
-/// All output from every command, including the prompt + the command
-/// is returned in the std::string return value.
-///
-/// @param[in] prefix
-/// A string that will be printed into \a strm prior to emitting
-/// the prompt + command and command output. Can be NULL.
-///
-/// @param[in] commands
-/// An array of LLDB commands to execute.
-///
-/// @return
-/// A std::string that contains the prefix and all commands and
-/// command output
-//----------------------------------------------------------------------
-std::string RunLLDBCommands(llvm::StringRef prefix,
- const llvm::ArrayRef<std::string> &commands);
-
-///----------------------------------------------------------------------
-/// Check if a thread has a stop reason.
-///
-/// @param[in] thread
-/// The LLDB thread object to check
-///
-/// @return
-/// \b True if the thread has a valid stop reason, \b false
-/// otherwise.
-//----------------------------------------------------------------------
-bool ThreadHasStopReason(lldb::SBThread &thread);
-
-///----------------------------------------------------------------------
-/// Given a LLDB frame, make a frame ID that is unique to a specific
-/// thread and frame.
-///
-/// VSCode requires a Stackframe "id" to be unique, so we use the frame
-/// index in the lower 32 bits and the thread index ID in the upper 32
-/// bits.
-///
-/// @param[in] frame
-/// The LLDB stack frame object generate the ID for
-///
-/// @return
-/// A unique integer that allows us to easily find the right
-/// stack frame within a thread on subsequent VS code requests.
-//----------------------------------------------------------------------
-int64_t MakeVSCodeFrameID(lldb::SBFrame &frame);
-
-///----------------------------------------------------------------------
-/// Given a VSCode frame ID, convert to a LLDB thread index id.
-///
-/// VSCode requires a Stackframe "id" to be unique, so we use the frame
-/// index in the lower THREAD_INDEX_SHIFT bits and the thread index ID in
-/// the upper 32 - THREAD_INDEX_SHIFT bits.
-///
-/// @param[in] dap_frame_id
-/// The VSCode frame ID to convert to a thread index ID.
-///
-/// @return
-/// The LLDB thread index ID.
-//----------------------------------------------------------------------
-uint32_t GetLLDBThreadIndexID(uint64_t dap_frame_id);
-
-///----------------------------------------------------------------------
-/// Given a VSCode frame ID, convert to a LLDB frame ID.
-///
-/// VSCode requires a Stackframe "id" to be unique, so we use the frame
-/// index in the lower THREAD_INDEX_SHIFT bits and the thread index ID in
-/// the upper 32 - THREAD_INDEX_SHIFT bits.
-///
-/// @param[in] dap_frame_id
-/// The VSCode frame ID to convert to a frame ID.
-///
-/// @return
-/// The LLDB frame index ID.
-//----------------------------------------------------------------------
-uint32_t GetLLDBFrameID(uint64_t dap_frame_id);
-
-///----------------------------------------------------------------------
-/// Given a LLDB breakpoint, make a breakpoint ID that is unique to a
-/// specific breakpoint and breakpoint location.
-///
-/// VSCode requires a Breakpoint "id" to be unique, so we use the
-/// breakpoint ID in the lower BREAKPOINT_ID_SHIFT bits and the
-/// breakpoint location ID in the upper BREAKPOINT_ID_SHIFT bits.
-///
-/// @param[in] frame
-/// The LLDB stack frame object generate the ID for
-///
-/// @return
-/// A unique integer that allows us to easily find the right
-/// stack frame within a thread on subsequent VS code requests.
-//----------------------------------------------------------------------
-int64_t MakeVSCodeBreakpointID(lldb::SBBreakpointLocation &bp_loc);
-
-///----------------------------------------------------------------------
-/// Given a VSCode breakpoint ID, convert to a LLDB breakpoint ID.
-///
-/// VSCode requires a Breakpoint "id" to be unique, so we use the
-/// breakpoint ID in the lower BREAKPOINT_ID_SHIFT bits and the
-/// breakpoint location ID in the upper BREAKPOINT_ID_SHIFT bits.
-///
-/// @param[in] dap_breakpoint_id
-/// The VSCode breakpoint ID to convert to an LLDB breakpoint ID.
-///
-/// @return
-/// The LLDB breakpoint ID.
-//----------------------------------------------------------------------
-uint32_t GetLLDBBreakpointID(uint64_t dap_breakpoint_id);
-
-///----------------------------------------------------------------------
-/// Given a VSCode breakpoint ID, convert to a LLDB breakpoint location ID.
-///
-/// VSCode requires a Breakpoint "id" to be unique, so we use the
-/// breakpoint ID in the lower BREAKPOINT_ID_SHIFT bits and the
-/// breakpoint location ID in the upper BREAKPOINT_ID_SHIFT bits.
-///
-/// @param[in] dap_breakpoint_id
-/// The VSCode frame ID to convert to a breakpoint location ID.
-///
-/// @return
-/// The LLDB breakpoint location ID.
-//----------------------------------------------------------------------
-uint32_t GetLLDBBreakpointLocationID(uint64_t dap_breakpoint_id);
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/README.md b/tools/lldb-vscode/README.md
deleted file mode 100644
index 2294659fc294..000000000000
--- a/tools/lldb-vscode/README.md
+++ /dev/null
@@ -1,195 +0,0 @@
-
-# Table of Contents
-
-- [Introduction](#Introduction)
-- [Installation](#Installation-Visual-Studio-Code)
-- [Configurations](#configurations)
- - [Launch Configuration Settings](#launch-configuration-settings)
- - [Attach Configuration Settings](#attach-configuration-settings)
- - [Example configurations](#example-configurations)
- - [Launching](#launching)
- - [Attach to process using process ID](#attach-using-pid)
- - [Attach to process by name](#attach-by-name)
- - [Loading a core file](#loading-a-core-file)
-
-# Introduction
-
-The `lldb-vscode` tool creates a command line tool that implements the [Visual
-Studio Code Debug API](https://code.visualstudio.com/docs/extensionAPI/api-debugging).
-It can be installed as an extension for the Visual Studio Code and Nuclide IDE.
-The protocol is easy to run remotely and also can allow other tools and IDEs to
-get a full featured debugger with a well defined protocol.
-
-# Installation for Visual Studio Code
-
-Installing the plug-in involves creating a directory in the `~/.vscode/extensions` folder and copying the package.json file that is in the same directory as this
-documentation into it, and copying to symlinking a lldb-vscode binary into
-the `bin` directory inside the plug-in directory.
-
-If you want to make a stand alone plug-in that you can send to others on unix systems:
-
-```
-$ mkdir -p ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
-$ cp package.json ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0
-$ cd ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
-$ cp /path/to/a/built/lldb-vscode .
-$ cp /path/to/a/built/liblldb.so .
-```
-
-
-If you want to make a stand alone plug-in that you can send to others on macOS systems:
-
-```
-$ mkdir -p ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
-$ cp package.json ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0
-$ cd ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
-$ cp /path/to/a/built/lldb-vscode .
-$ rsync -av /path/to/a/built/LLDB.framework LLDB.framework
-```
-
-You might need to create additional directories for the `liblldb.so` or `LLDB.framework` inside or next to the `bin` folder depending on how the [rpath](https://en.wikipedia.org/wiki/Rpath) is set in your `lldb-vscode` binary. By default the `Debug` builds of LLDB usually includes
-the current executable directory in the rpath, so these steps should work for most people.
-
-To create a plug-in that symlinks into your `lldb-vscode` in your build directory:
-
-```
-$ mkdir -p ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
-$ cp package.json ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0
-$ cd ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
-$ ln -s /path/to/a/built/lldb-vscode
-```
-
-This is handy if you want to debug and develope the `lldb-vscode` executable when adding features or fixing bugs.
-
-# Configurations
-
-Launching to attaching require you to create a [launch configuration](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations). This file
-defines arguments that get passed to `lldb-vscode` and the configuration settings
-control how the launch or attach happens.
-
-## Launch Configuration Settings
-
-When you launch a program with Visual Studio Code you will need to create a [launch.json](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations)
-file that defines how your program will be run. The JSON configuration file can contain the following `lldb-vscode` specific launch key/value pairs:
-
-|parameter |type|req | |
-|-------------------|----|:--:|---------|
-|**name** |string|Y| A configuration name that will be displayed in the IDE.
-|**type** |string|Y| Must be "lldb-vscode".
-|**request** |string|Y| Must be "launch".
-|**program** |string|Y| Path to the executable to launch.
-|**args** |[string]|| An array of command line argument strings to be passed to the program being launched.
-|**cwd** |string| | The program working directory.
-|**env** |dictionary| | Environment variables to set when launching the program. The format of each environment variable string is "VAR=VALUE" for environment variables with values or just "VAR" for environment variables with no values.
-|**stopOnEntry** |boolean| | Whether to stop program immediately after launching.
-|**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.
-|**exitCommands** |[string]| | LLDB commands executed when the program exits. 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.
-|**debuggerRoot** | string| |Specify a working directory to use when launching lldb-vscode. If the debug information in your executable contains relative paths, this option can be used so that `lldb-vscode` can find source files and object files that have relative paths.
-
-## Attaching Settings
-
-When attaching to a process using LLDB you can attach in a few ways
-
-1. Attach to an existing process using the process ID
-2. Attach to an existing process by name
-3. Attach by name by waiting for the next instance of a process to launch
-
-The JSON configuration file can contain the following `lldb-vscode` specific launch key/value pairs:
-
-|parameter |type |req | |
-|-------------------|--------|:--:|---------|
-|**name** |string |Y| A configuration name that will be displayed in the IDE.
-|**type** |string |Y| Must be "lldb-vscode".
-|**request** |string |Y| Must be "attach".
-|**program** |string | | Path to the executable to attach to. This value is optional but can help to resolve breakpoints prior the attaching to the program.
-|**pid** |number | | The process id of the process you wish to attach to. If **pid** is omitted, the debugger will attempt to attach to the program by finding a process whose file name matches the file name from **porgram**. Setting this value to `${command:pickMyProcess}` will allow interactive process selection in the IDE.
-|**stopOnEntry** |boolean| | Whether to stop program immediately after launching.
-|**waitFor** |boolean | | Wait for the process to launch.
-|**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.
-|**exitCommands** |[string]| | LLDB commands executed when the program exits. Commands and command output will be sent to the debugger console when they are executed.
-|**attachCommands** |[string]| | LLDB commands that will be executed after **preRunCommands** which take place of the code that normally does the attach. The commands can create a new target and attach or launch it however desired. This allows custom launch and attach configurations. Core files can use `target create --core /path/to/core` to attach to core files.
-
-
-## Example configurations
-
-### Launching
-
-This will launch `/tmp/a.out` with arguments `one`, `two`, and `three` and
-adds `FOO=1` and `bar` to the environment:
-
-```javascript
-{
- "type": "lldb-vscode",
- "request": "launch",
- "name": "Debug",
- "program": "/tmp/a.out",
- "args": [ "one", "two", "three" ],
- "env": [ "FOO=1", "BAR" ],
-}
-```
-
-### Attach using PID
-
-This will attach to a process `a.out` whose process ID is 123:
-
-```javascript
-{
- "type": "lldb-vscode",
- "request": "attach",
- "name": "Attach to PID",
- "program": "/tmp/a.out",
- "pid": 123
-}
-```
-
-### Attach by Name
-
-This will attach to an existing process whose base
-name matches `a.out`. All we have to do is leave the `pid` value out of the
-above configuration:
-
-```javascript
-{
- "name": "Attach to Name",
- "type": "lldb-vscode",
- "request": "attach",
- "program": "/tmp/a.out",
-}
-```
-
-If you want to ignore any existing a.out processes and wait for the next instance
-to be launched you can add the "waitFor" key value pair:
-
-```javascript
-{
- "name": "Attach to Name (wait)",
- "type": "lldb-vscode",
- "request": "attach",
- "program": "/tmp/a.out",
- "waitFor": true
-}
-```
-
-This will work as long as the architecture, vendor and OS supports waiting
-for processes. Currently MacOS is the only platform that supports this.
-
-
-### Loading a Core File
-
-Loading a core file can use the `"attach"` request along with the
-`"attachCommands"` to implement a custom attach:
-
-```javascript
-{
- "name": "Attach to Name (wait)",
- "type": "lldb-vscode",
- "request": "attach",
- "attachCommands": ["target create -c /path/to/123.core /path/to/executable"],
- "stopOnEntry": false
-}
-```
diff --git a/tools/lldb-vscode/SourceBreakpoint.cpp b/tools/lldb-vscode/SourceBreakpoint.cpp
deleted file mode 100644
index f2a286c9eca2..000000000000
--- a/tools/lldb-vscode/SourceBreakpoint.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===-- SourceBreakpoint.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SourceBreakpoint.h"
-#include "VSCode.h"
-
-namespace lldb_vscode {
-
-SourceBreakpoint::SourceBreakpoint(const llvm::json::Object &obj)
- : BreakpointBase(obj), line(GetUnsigned(obj, "line", 0)),
- column(GetUnsigned(obj, "column", 0)) {}
-
-void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
- bp = g_vsc.target.BreakpointCreateByLocation(source_path.str().c_str(), line);
- if (!condition.empty())
- SetCondition();
- if (!hitCondition.empty())
- SetHitCondition();
-}
-
-} // namespace lldb_vscode
diff --git a/tools/lldb-vscode/SourceBreakpoint.h b/tools/lldb-vscode/SourceBreakpoint.h
deleted file mode 100644
index 8af647ca8fe5..000000000000
--- a/tools/lldb-vscode/SourceBreakpoint.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===-- SourceBreakpoint.h --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_SOURCEBREAKPOINT_H_
-#define LLDBVSCODE_SOURCEBREAKPOINT_H_
-
-#include "llvm/ADT/StringRef.h"
-#include "BreakpointBase.h"
-
-namespace lldb_vscode {
-
-struct SourceBreakpoint : public BreakpointBase {
-
- uint32_t line; ///< The source line of the breakpoint or logpoint
- uint32_t column; ///< An optional source column of the breakpoint
-
- SourceBreakpoint() : BreakpointBase(), line(0), column(0) {}
- SourceBreakpoint(const llvm::json::Object &obj);
-
- // Set this breakpoint in LLDB as a new breakpoint
- void SetBreakpoint(const llvm::StringRef source_path);
-};
-
-inline bool operator<(const SourceBreakpoint &lhs,
- const SourceBreakpoint &rhs) {
- if (lhs.line == rhs.line)
- return lhs.column < rhs.column;
- return lhs.line < rhs.line;
-}
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/SourceReference.h b/tools/lldb-vscode/SourceReference.h
deleted file mode 100644
index f047143e6c84..000000000000
--- a/tools/lldb-vscode/SourceReference.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===-- SourceReference.h ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_SOURCEREFERENCE_H_
-#define LLDBVSCODE_SOURCEREFERENCE_H_
-
-#include "lldb/lldb-types.h"
-#include "llvm/ADT/DenseMap.h"
-#include <string>
-
-namespace lldb_vscode {
-
-struct SourceReference {
- std::string content;
- llvm::DenseMap<lldb::addr_t, int64_t> addr_to_line;
-
- int64_t GetLineForPC(lldb::addr_t pc) const {
- auto addr_line = addr_to_line.find(pc);
- if (addr_line != addr_to_line.end())
- return addr_line->second;
- return 0;
- }
-};
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/VSCode.cpp b/tools/lldb-vscode/VSCode.cpp
deleted file mode 100644
index 0f138ec77707..000000000000
--- a/tools/lldb-vscode/VSCode.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-//===-- VSCode.cpp ----------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <stdarg.h>
-#include <fstream>
-#include <mutex>
-
-#include "VSCode.h"
-#include "LLDBUtils.h"
-
-#if defined(_WIN32)
-#include <io.h>
-#include <fcntl.h>
-#endif
-
-using namespace lldb_vscode;
-
-namespace {
- inline bool IsEmptyLine(llvm::StringRef S) {
- return S.ltrim().empty();
- }
-} // namespace
-
-namespace lldb_vscode {
-
-VSCode g_vsc;
-
-VSCode::VSCode()
- : in(stdin), out(stdout), launch_info(nullptr), variables(),
- broadcaster("lldb-vscode"), num_regs(0), num_locals(0), num_globals(0),
- log(), exception_breakpoints(
- {{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
- {"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
- {"objc_catch", "Objective C Catch", lldb::eLanguageTypeObjC},
- {"objc_throw", "Objective C Throw", lldb::eLanguageTypeObjC},
- {"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) {
- 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
-// while the value is just 10 on Darwin/Linux. Setting the file mode to binary
-// fixes this.
- assert(_setmode(fileno(stdout), _O_BINARY));
- assert(_setmode(fileno(stdin), _O_BINARY));
-#endif
- if (log_file_path)
- log.reset(new std::ofstream(log_file_path));
-}
-
-VSCode::~VSCode() {
- CloseInputStream();
- CloseOutputStream();
-}
-
-void VSCode::CloseInputStream() {
- if (in != stdin) {
- fclose(in);
- in = nullptr;
- }
-}
-
-void VSCode::CloseOutputStream() {
- if (out != stdout) {
- fclose(out);
- out = nullptr;
- }
-}
-
-int64_t VSCode::GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const {
- auto pos = source_map.find(sourceReference);
- if (pos != source_map.end())
- return pos->second.GetLineForPC(pc);
- return 0;
-}
-
-ExceptionBreakpoint *VSCode::GetExceptionBreakpoint(const std::string &filter) {
- for (auto &bp : exception_breakpoints) {
- if (bp.filter == filter)
- return &bp;
- }
- return nullptr;
-}
-
-ExceptionBreakpoint *
-VSCode::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
- for (auto &bp : exception_breakpoints) {
- if (bp.bp.GetID() == bp_id)
- return &bp;
- }
- return nullptr;
-}
-
-//----------------------------------------------------------------------
-// Send the JSON in "json_str" to the "out" stream. Correctly send the
-// "Content-Length:" field followed by the length, followed by the raw
-// JSON bytes.
-//----------------------------------------------------------------------
-void VSCode::SendJSON(const std::string &json_str) {
- fprintf(out, "Content-Length: %u\r\n\r\n%s", (uint32_t)json_str.size(),
- json_str.c_str());
- fflush(out);
- if (log) {
- *log << "<-- " << std::endl
- << "Content-Length: " << json_str.size() << "\r\n\r\n"
- << json_str << std::endl;
- }
-}
-
-//----------------------------------------------------------------------
-// Serialize the JSON value into a string and send the JSON packet to
-// the "out" stream.
-//----------------------------------------------------------------------
-void VSCode::SendJSON(const llvm::json::Value &json) {
- std::string s;
- llvm::raw_string_ostream strm(s);
- strm << json;
- static std::mutex mutex;
- std::lock_guard<std::mutex> locker(mutex);
- SendJSON(strm.str());
-}
-
-//----------------------------------------------------------------------
-// Read a JSON packet from the "in" stream.
-//----------------------------------------------------------------------
-std::string VSCode::ReadJSON() {
- static std::string header("Content-Length: ");
-
- uint32_t packet_len = 0;
- std::string json_str;
- char line[1024];
-
- while (fgets(line, sizeof(line), in)) {
- if (strncmp(line, header.data(), header.size()) == 0) {
- packet_len = atoi(line + header.size());
- if (fgets(line, sizeof(line), in)) {
- if (!IsEmptyLine(line))
- if (log)
- *log << "warning: expected empty line but got: \"" << line << "\""
- << std::endl;
- break;
- }
- } else {
- if (log)
- *log << "warning: expected \"" << header << "\" but got: \"" << line
- << "\"" << std::endl;
- }
- }
- // This is followed by two windows newline sequences ("\r\n\r\n") so eat
- // two the newline sequences
- if (packet_len > 0) {
- json_str.resize(packet_len);
- auto bytes_read = fread(&json_str[0], 1, packet_len, in);
- if (bytes_read < packet_len) {
- if (log)
- *log << "error: read fewer bytes (" << bytes_read
- << ") than requested (" << packet_len << ")" << std::endl;
- json_str.erase(bytes_read);
- }
- if (log) {
- *log << "--> " << std::endl;
- *log << header << packet_len << "\r\n\r\n" << json_str << std::endl;
- }
- }
- return json_str;
-}
-
-//----------------------------------------------------------------------
-// "OutputEvent": {
-// "allOf": [ { "$ref": "#/definitions/Event" }, {
-// "type": "object",
-// "description": "Event message for 'output' event type. The event
-// indicates that the target has produced some output.",
-// "properties": {
-// "event": {
-// "type": "string",
-// "enum": [ "output" ]
-// },
-// "body": {
-// "type": "object",
-// "properties": {
-// "category": {
-// "type": "string",
-// "description": "The output category. If not specified,
-// 'console' is assumed.",
-// "_enum": [ "console", "stdout", "stderr", "telemetry" ]
-// },
-// "output": {
-// "type": "string",
-// "description": "The output to report."
-// },
-// "variablesReference": {
-// "type": "number",
-// "description": "If an attribute 'variablesReference' exists
-// and its value is > 0, the output contains
-// objects which can be retrieved by passing
-// variablesReference to the VariablesRequest."
-// },
-// "source": {
-// "$ref": "#/definitions/Source",
-// "description": "An optional source location where the output
-// was produced."
-// },
-// "line": {
-// "type": "integer",
-// "description": "An optional source location line where the
-// output was produced."
-// },
-// "column": {
-// "type": "integer",
-// "description": "An optional source location column where the
-// output was produced."
-// },
-// "data": {
-// "type":["array","boolean","integer","null","number","object",
-// "string"],
-// "description": "Optional data to report. For the 'telemetry'
-// category the data will be sent to telemetry, for
-// the other categories the data is shown in JSON
-// format."
-// }
-// },
-// "required": ["output"]
-// }
-// },
-// "required": [ "event", "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void VSCode::SendOutput(OutputType o, const llvm::StringRef output) {
- if (output.empty())
- return;
-
- llvm::json::Object event(CreateEventObject("output"));
- llvm::json::Object body;
- const char *category = nullptr;
- switch (o) {
- case OutputType::Console:
- category = "console";
- break;
- case OutputType::Stdout:
- category = "stdout";
- break;
- case OutputType::Stderr:
- category = "stderr";
- break;
- case OutputType::Telemetry:
- category = "telemetry";
- break;
- }
- body.try_emplace("category", category);
- EmplaceSafeString(body, "output", output.str());
- event.try_emplace("body", std::move(body));
- SendJSON(llvm::json::Value(std::move(event)));
-}
-
-void __attribute__((format(printf, 3, 4)))
-VSCode::SendFormattedOutput(OutputType o, const char *format, ...) {
- char buffer[1024];
- va_list args;
- va_start(args, format);
- int actual_length = vsnprintf(buffer, sizeof(buffer), format, args);
- va_end(args);
- SendOutput(o, llvm::StringRef(buffer,
- std::min<int>(actual_length, sizeof(buffer))));
-}
-
-int64_t VSCode::GetNextSourceReference() {
- static int64_t ref = 0;
- return ++ref;
-}
-
-ExceptionBreakpoint *
-VSCode::GetExceptionBPFromStopReason(lldb::SBThread &thread) {
- const auto num = thread.GetStopReasonDataCount();
- // Check to see if have hit an exception breakpoint and change the
- // reason to "exception", but only do so if all breakpoints that were
- // hit are exception breakpoints.
- ExceptionBreakpoint *exc_bp = nullptr;
- for (size_t i = 0; i < num; i += 2) {
- // thread.GetStopReasonDataAtIndex(i) will return the bp ID and
- // thread.GetStopReasonDataAtIndex(i+1) will return the location
- // within that breakpoint. We only care about the bp ID so we can
- // see if this is an exception breakpoint that is getting hit.
- lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(i);
- exc_bp = GetExceptionBreakpoint(bp_id);
- // If any breakpoint is not an exception breakpoint, then stop and
- // report this as a normal breakpoint
- if (exc_bp == nullptr)
- return nullptr;
- }
- return exc_bp;
-}
-
-lldb::SBThread VSCode::GetLLDBThread(const llvm::json::Object &arguments) {
- auto tid = GetSigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
- return target.GetProcess().GetThreadByID(tid);
-}
-
-lldb::SBFrame VSCode::GetLLDBFrame(const llvm::json::Object &arguments) {
- const uint64_t frame_id = GetUnsigned(arguments, "frameId", UINT64_MAX);
- lldb::SBProcess process = target.GetProcess();
- // Upper 32 bits is the thread index ID
- lldb::SBThread thread =
- process.GetThreadByIndexID(GetLLDBThreadIndexID(frame_id));
- // Lower 32 bits is the frame index
- return thread.GetFrameAtIndex(GetLLDBFrameID(frame_id));
-}
-
-llvm::json::Value VSCode::CreateTopLevelScopes() {
- llvm::json::Array scopes;
- scopes.emplace_back(CreateScope("Locals", VARREF_LOCALS, num_locals, false));
- scopes.emplace_back(
- CreateScope("Globals", VARREF_GLOBALS, num_globals, false));
- scopes.emplace_back(CreateScope("Registers", VARREF_REGS, num_regs, false));
- return llvm::json::Value(std::move(scopes));
-}
-
-void VSCode::RunLLDBCommands(llvm::StringRef prefix,
- const std::vector<std::string> &commands) {
- SendOutput(OutputType::Console,
- llvm::StringRef(::RunLLDBCommands(prefix, commands)));
-}
-
-void VSCode::RunInitCommands() {
- RunLLDBCommands("Running initCommands:", init_commands);
-}
-
-void VSCode::RunPreRunCommands() {
- RunLLDBCommands("Running preRunCommands:", pre_run_commands);
-}
-
-void VSCode::RunStopCommands() {
- RunLLDBCommands("Running stopCommands:", stop_commands);
-}
-
-void VSCode::RunExitCommands() {
- RunLLDBCommands("Running exitCommands:", exit_commands);
-}
-
-} // namespace lldb_vscode
-
diff --git a/tools/lldb-vscode/VSCode.h b/tools/lldb-vscode/VSCode.h
deleted file mode 100644
index 142be3318367..000000000000
--- a/tools/lldb-vscode/VSCode.h
+++ /dev/null
@@ -1,146 +0,0 @@
-//===-- VSCode.h ------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_VSCODE_H_
-#define LLDBVSCODE_VSCODE_H_
-
-#include <iosfwd>
-#include <map>
-#include <set>
-#include <stdio.h>
-#include <thread>
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-
-#include "lldb/API/SBAttachInfo.h"
-#include "lldb/API/SBBreakpoint.h"
-#include "lldb/API/SBBreakpointLocation.h"
-#include "lldb/API/SBCommandInterpreter.h"
-#include "lldb/API/SBCommandReturnObject.h"
-#include "lldb/API/SBCommunication.h"
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBEvent.h"
-#include "lldb/API/SBHostOS.h"
-#include "lldb/API/SBInstruction.h"
-#include "lldb/API/SBInstructionList.h"
-#include "lldb/API/SBLanguageRuntime.h"
-#include "lldb/API/SBLaunchInfo.h"
-#include "lldb/API/SBLineEntry.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBProcess.h"
-#include "lldb/API/SBStream.h"
-#include "lldb/API/SBStringList.h"
-#include "lldb/API/SBTarget.h"
-#include "lldb/API/SBThread.h"
-
-#include "ExceptionBreakpoint.h"
-#include "FunctionBreakpoint.h"
-#include "SourceBreakpoint.h"
-#include "SourceReference.h"
-
-#define VARREF_LOCALS (int64_t)1
-#define VARREF_GLOBALS (int64_t)2
-#define VARREF_REGS (int64_t)3
-#define VARREF_FIRST_VAR_IDX (int64_t)4
-#define VARREF_IS_SCOPE(v) (VARREF_LOCALS <= 1 && v < VARREF_FIRST_VAR_IDX)
-#define VARIDX_TO_VARREF(i) ((i) + VARREF_FIRST_VAR_IDX)
-#define VARREF_TO_VARIDX(v) ((v)-VARREF_FIRST_VAR_IDX)
-#define NO_TYPENAME "<no-type>"
-
-namespace lldb_vscode {
-
-typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap;
-typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
-enum class OutputType { Console, Stdout, Stderr, Telemetry };
-
-struct VSCode {
- FILE *in;
- FILE *out;
- lldb::SBDebugger debugger;
- lldb::SBTarget target;
- lldb::SBAttachInfo attach_info;
- lldb::SBLaunchInfo launch_info;
- lldb::SBValueList variables;
- lldb::SBBroadcaster broadcaster;
- int64_t num_regs;
- int64_t num_locals;
- int64_t num_globals;
- std::thread event_thread;
- std::unique_ptr<std::ofstream> log;
- llvm::DenseMap<lldb::addr_t, int64_t> addr_to_source_ref;
- llvm::DenseMap<int64_t, SourceReference> source_map;
- llvm::StringMap<SourceBreakpointMap> source_breakpoints;
- FunctionBreakpointMap function_breakpoints;
- std::vector<ExceptionBreakpoint> exception_breakpoints;
- std::vector<std::string> init_commands;
- std::vector<std::string> pre_run_commands;
- std::vector<std::string> exit_commands;
- std::vector<std::string> stop_commands;
- lldb::tid_t focus_tid;
- bool sent_terminated_event;
- bool stop_at_entry;
- // 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;
- VSCode();
- ~VSCode();
- VSCode(const VSCode &rhs) = delete;
- void operator=(const VSCode &rhs) = delete;
- void CloseInputStream();
- void CloseOutputStream();
- int64_t GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const;
- ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
- ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
- //----------------------------------------------------------------------
- // Send the JSON in "json_str" to the "out" stream. Correctly send the
- // "Content-Length:" field followed by the length, followed by the raw
- // JSON bytes.
- //----------------------------------------------------------------------
- void SendJSON(const std::string &json_str);
-
- //----------------------------------------------------------------------
- // Serialize the JSON value into a string and send the JSON packet to
- // the "out" stream.
- //----------------------------------------------------------------------
- void SendJSON(const llvm::json::Value &json);
-
- std::string ReadJSON();
-
- void SendOutput(OutputType o, const llvm::StringRef output);
-
- void __attribute__((format(printf, 3, 4)))
- SendFormattedOutput(OutputType o, const char *format, ...);
-
- static int64_t GetNextSourceReference();
-
- ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);
-
- lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments);
-
- lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments);
-
- llvm::json::Value CreateTopLevelScopes();
-
- void RunLLDBCommands(llvm::StringRef prefix,
- const std::vector<std::string> &commands);
-
- void RunInitCommands();
- void RunPreRunCommands();
- void RunStopCommands();
- void RunExitCommands();
-};
-
-extern VSCode g_vsc;
-
-} // namespace lldb_vscode
-
-#endif
diff --git a/tools/lldb-vscode/VSCodeForward.h b/tools/lldb-vscode/VSCodeForward.h
deleted file mode 100644
index d5b7f8d53f77..000000000000
--- a/tools/lldb-vscode/VSCodeForward.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===-- VSCodeForward.h -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDBVSCODE_VSCODEFORWARD_H_
-#define LLDBVSCODE_VSCODEFORWARD_H_
-
-
-namespace lldb_vscode {
-struct BreakpointBase;
-struct ExceptionBreakpoint;
-struct FunctionBreakpoint;
-struct SourceBreakpoint;
-struct SourceReference;
-} // namespace lldb_vscode
-
-namespace lldb {
-class SBAttachInfo;
-class SBBreakpoint;
-class SBBreakpointLocation;
-class SBCommandInterpreter;
-class SBCommandReturnObject;
-class SBCommunication;
-class SBDebugger;
-class SBEvent;
-class SBFrame;
-class SBHostOS;
-class SBInstruction;
-class SBInstructionList;
-class SBLanguageRuntime;
-class SBLaunchInfo;
-class SBLineEntry;
-class SBListener;
-class SBProcess;
-class SBStream;
-class SBStringList;
-class SBTarget;
-class SBThread;
-class SBValue;
-} // namespace lldb
-
-#endif
diff --git a/tools/lldb-vscode/lldb-vscode-Info.plist b/tools/lldb-vscode/lldb-vscode-Info.plist
deleted file mode 100644
index a6b824372546..000000000000
--- a/tools/lldb-vscode/lldb-vscode-Info.plist
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleIdentifier</key>
- <string>com.apple.lldb-vscode</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundleName</key>
- <string>lldb-vscode</string>
- <key>CFBundleVersion</key>
- <string>360.99.0</string>
- <key>SecTaskAccess</key>
- <array>
- <string>allowed</string>
- <string>debug</string>
- </array>
-</dict>
-</plist>
diff --git a/tools/lldb-vscode/lldb-vscode.cpp b/tools/lldb-vscode/lldb-vscode.cpp
deleted file mode 100644
index 2aad7977efa0..000000000000
--- a/tools/lldb-vscode/lldb-vscode.cpp
+++ /dev/null
@@ -1,2706 +0,0 @@
-//===-- lldb-vscode.cpp -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <assert.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#if defined(_WIN32)
-// We need to #define NOMINMAX in order to skip `min()` and `max()` macro
-// definitions that conflict with other system headers.
-// We also need to #undef GetObject (which is defined to GetObjectW) because
-// the JSON code we use also has methods named `GetObject()` and we conflict
-// against these.
-#define NOMINMAX
-#include <windows.h>
-#undef GetObject
-#else
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#endif
-
-#include <algorithm>
-#include <chrono>
-#include <fstream>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <thread>
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include "JSONUtils.h"
-#include "LLDBUtils.h"
-#include "VSCode.h"
-
-#if defined(_WIN32)
-#define PATH_MAX MAX_PATH
-typedef int socklen_t;
-constexpr const char *dev_null_path = "nul";
-
-#else
-typedef int SOCKET;
-constexpr const char *dev_null_path = "/dev/null";
-
-#endif
-
-using namespace lldb_vscode;
-
-namespace {
-
-typedef void (*RequestCallback)(const llvm::json::Object &command);
-
-enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
-
-enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
-
-int AcceptConnection(int portno) {
- // Accept a socket connection from any host on "portno".
- int newsockfd = -1;
- struct sockaddr_in serv_addr, cli_addr;
- SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0) {
- if (g_vsc.log)
- *g_vsc.log << "error: opening socket (" << strerror(errno) << ")"
- << std::endl;
- } else {
- memset((char *)&serv_addr, 0, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- // serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- serv_addr.sin_port = htons(portno);
- if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
- if (g_vsc.log)
- *g_vsc.log << "error: binding socket (" << strerror(errno) << ")"
- << std::endl;
- } else {
- listen(sockfd, 5);
- socklen_t clilen = sizeof(cli_addr);
- newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
- if (newsockfd < 0)
- if (g_vsc.log)
- *g_vsc.log << "error: accept (" << strerror(errno) << ")"
- << std::endl;
- }
-#if defined(_WIN32)
- closesocket(sockfd);
-#else
- close(sockfd);
-#endif
- }
- return newsockfd;
-}
-
-std::vector<const char *> MakeArgv(const llvm::ArrayRef<std::string> &strs) {
- // Create and return an array of "const char *", one for each C string in
- // "strs" and terminate the list with a NULL. This can be used for argument
- // vectors (argv) or environment vectors (envp) like those passed to the
- // "main" function in C programs.
- std::vector<const char *> argv;
- for (const auto &s : strs)
- argv.push_back(s.c_str());
- argv.push_back(nullptr);
- return argv;
-}
-
-//----------------------------------------------------------------------
-// Send a "exited" event to indicate the process has exited.
-//----------------------------------------------------------------------
-void SendProcessExitedEvent(lldb::SBProcess &process) {
- llvm::json::Object event(CreateEventObject("exited"));
- llvm::json::Object body;
- body.try_emplace("exitCode", (int64_t)process.GetExitStatus());
- event.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(event)));
-}
-
-void SendThreadExitedEvent(lldb::tid_t tid) {
- llvm::json::Object event(CreateEventObject("thread"));
- llvm::json::Object body;
- body.try_emplace("reason", "exited");
- body.try_emplace("threadId", (int64_t)tid);
- 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() {
- if (!g_vsc.sent_terminated_event) {
- g_vsc.sent_terminated_event = true;
- // Send a "terminated" event
- llvm::json::Object event(CreateEventObject("terminated"));
- g_vsc.SendJSON(llvm::json::Value(std::move(event)));
- }
-}
-
-//----------------------------------------------------------------------
-// Send a thread stopped event for all threads as long as the process
-// is stopped.
-//----------------------------------------------------------------------
-void SendThreadStoppedEvent() {
- lldb::SBProcess process = g_vsc.target.GetProcess();
- if (process.IsValid()) {
- auto state = process.GetState();
- if (state == lldb::eStateStopped) {
- llvm::DenseSet<lldb::tid_t> old_thread_ids;
- old_thread_ids.swap(g_vsc.thread_ids);
- uint32_t stop_id = process.GetStopID();
- const uint32_t num_threads = process.GetNumThreads();
-
- // First make a pass through the threads to see if the focused thread
- // has a stop reason. In case the focus thread doesn't have a stop
- // reason, remember the first thread that has a stop reason so we can
- // set it as the focus thread if below if needed.
- lldb::tid_t first_tid_with_reason = LLDB_INVALID_THREAD_ID;
- uint32_t num_threads_with_reason = 0;
- for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
- lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
- const lldb::tid_t tid = thread.GetThreadID();
- const bool has_reason = ThreadHasStopReason(thread);
- // If the focus thread doesn't have a stop reason, clear the thread ID
- if (tid == g_vsc.focus_tid && !has_reason)
- g_vsc.focus_tid = LLDB_INVALID_THREAD_ID;
- if (has_reason) {
- ++num_threads_with_reason;
- if (first_tid_with_reason == LLDB_INVALID_THREAD_ID)
- first_tid_with_reason = tid;
- }
- }
-
- // We will have cleared g_vsc.focus_tid if he focus thread doesn't
- // have a stop reason, so if it was cleared, or wasn't set, then set the
- // focus thread to the first thread with a stop reason.
- if (g_vsc.focus_tid == LLDB_INVALID_THREAD_ID)
- g_vsc.focus_tid = first_tid_with_reason;
-
- // If no threads stopped with a reason, then report the first one so
- // we at least let the UI know we stopped.
- if (num_threads_with_reason == 0) {
- lldb::SBThread thread = process.GetThreadAtIndex(0);
- g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
- } else {
- for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
- lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
- g_vsc.thread_ids.insert(thread.GetThreadID());
- if (ThreadHasStopReason(thread)) {
- g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
- }
- }
- }
-
- for (auto tid : old_thread_ids) {
- auto end = g_vsc.thread_ids.end();
- auto pos = g_vsc.thread_ids.find(tid);
- if (pos == end)
- SendThreadExitedEvent(tid);
- }
- } else {
- if (g_vsc.log)
- *g_vsc.log << "error: SendThreadStoppedEvent() when process"
- " isn't stopped ("
- << lldb::SBDebugger::StateAsCString(state) << ')'
- << std::endl;
- }
- } else {
- if (g_vsc.log)
- *g_vsc.log << "error: SendThreadStoppedEvent() invalid process"
- << std::endl;
- }
- g_vsc.RunStopCommands();
-}
-
-//----------------------------------------------------------------------
-// "ProcessEvent": {
-// "allOf": [
-// { "$ref": "#/definitions/Event" },
-// {
-// "type": "object",
-// "description": "Event message for 'process' event type. The event
-// indicates that the debugger has begun debugging a
-// new process. Either one that it has launched, or one
-// that it has attached to.",
-// "properties": {
-// "event": {
-// "type": "string",
-// "enum": [ "process" ]
-// },
-// "body": {
-// "type": "object",
-// "properties": {
-// "name": {
-// "type": "string",
-// "description": "The logical name of the process. This is
-// usually the full path to process's executable
-// file. Example: /home/myproj/program.js."
-// },
-// "systemProcessId": {
-// "type": "integer",
-// "description": "The system process id of the debugged process.
-// This property will be missing for non-system
-// processes."
-// },
-// "isLocalProcess": {
-// "type": "boolean",
-// "description": "If true, the process is running on the same
-// computer as the debug adapter."
-// },
-// "startMethod": {
-// "type": "string",
-// "enum": [ "launch", "attach", "attachForSuspendedLaunch" ],
-// "description": "Describes how the debug engine started
-// debugging this process.",
-// "enumDescriptions": [
-// "Process was launched under the debugger.",
-// "Debugger attached to an existing process.",
-// "A project launcher component has launched a new process in
-// a suspended state and then asked the debugger to attach."
-// ]
-// }
-// },
-// "required": [ "name" ]
-// }
-// },
-// "required": [ "event", "body" ]
-// }
-// ]
-// }
-//----------------------------------------------------------------------
-void SendProcessEvent(LaunchMethod launch_method) {
- lldb::SBFileSpec exe_fspec = g_vsc.target.GetExecutable();
- char exe_path[PATH_MAX];
- exe_fspec.GetPath(exe_path, sizeof(exe_path));
- llvm::json::Object event(CreateEventObject("process"));
- llvm::json::Object body;
- EmplaceSafeString(body, "name", std::string(exe_path));
- const auto pid = g_vsc.target.GetProcess().GetProcessID();
- body.try_emplace("systemProcessId", (int64_t)pid);
- body.try_emplace("isLocalProcess", true);
- const char *startMethod = nullptr;
- switch (launch_method) {
- case Launch:
- startMethod = "launch";
- break;
- case Attach:
- startMethod = "attach";
- break;
- case AttachForSuspendedLaunch:
- startMethod = "attachForSuspendedLaunch";
- break;
- }
- body.try_emplace("startMethod", startMethod);
- event.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(event)));
-}
-
-//----------------------------------------------------------------------
-// Grab any STDOUT and STDERR from the process and send it up to VS Code
-// via an "output" event to the "stdout" and "stderr" categories.
-//----------------------------------------------------------------------
-void SendStdOutStdErr(lldb::SBProcess &process) {
- char buffer[1024];
- size_t count;
- while ((count = process.GetSTDOUT(buffer, sizeof(buffer))) > 0)
- g_vsc.SendOutput(OutputType::Stdout, llvm::StringRef(buffer, count));
- while ((count = process.GetSTDERR(buffer, sizeof(buffer))) > 0)
- g_vsc.SendOutput(OutputType::Stderr, llvm::StringRef(buffer, count));
-}
-
-//----------------------------------------------------------------------
-// All events from the debugger, target, process, thread and frames are
-// received in this function that runs in its own thread. We are using a
-// "FILE *" to output packets back to VS Code and they have mutexes in them
-// them prevent multiple threads from writing simultaneously so no locking
-// is required.
-//----------------------------------------------------------------------
-void EventThreadFunction() {
- lldb::SBEvent event;
- lldb::SBListener listener = g_vsc.debugger.GetListener();
- bool done = false;
- while (!done) {
- if (listener.WaitForEvent(1, event)) {
- const auto event_mask = event.GetType();
- if (lldb::SBProcess::EventIsProcessEvent(event)) {
- lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(event);
- if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
- auto state = lldb::SBProcess::GetStateFromEvent(event);
- switch (state) {
- case lldb::eStateInvalid:
- // Not a state event
- break;
- case lldb::eStateUnloaded:
- break;
- case lldb::eStateConnected:
- break;
- case lldb::eStateAttaching:
- break;
- case lldb::eStateLaunching:
- break;
- case lldb::eStateStepping:
- break;
- case lldb::eStateCrashed:
- break;
- case lldb::eStateDetached:
- break;
- case lldb::eStateSuspended:
- break;
- case lldb::eStateStopped:
- // Only report a stopped event if the process was not restarted.
- if (!lldb::SBProcess::GetRestartedFromEvent(event)) {
- SendStdOutStdErr(process);
- SendThreadStoppedEvent();
- }
- break;
- case lldb::eStateRunning:
- break;
- case lldb::eStateExited: {
- // Run any exit LLDB commands the user specified in the
- // launch.json
- g_vsc.RunExitCommands();
- SendProcessExitedEvent(process);
- SendTerminatedEvent();
- done = true;
- } break;
- }
- } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
- (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
- SendStdOutStdErr(process);
- }
- } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(event)) {
- if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
- auto event_type =
- lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(event);
- const auto num_locs =
- lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
- auto bp = lldb::SBBreakpoint::GetBreakpointFromEvent(event);
- bool added = event_type & lldb::eBreakpointEventTypeLocationsAdded;
- bool removed =
- event_type & lldb::eBreakpointEventTypeLocationsRemoved;
- if (added || removed) {
- for (size_t i = 0; i < num_locs; ++i) {
- auto bp_loc =
- lldb::SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(
- event, i);
- auto bp_event = CreateEventObject("breakpoint");
- llvm::json::Object body;
- body.try_emplace("breakpoint", CreateBreakpoint(bp_loc));
- if (added)
- body.try_emplace("reason", "new");
- else
- body.try_emplace("reason", "removed");
- bp_event.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(bp_event)));
- }
- }
- }
- } else if (event.BroadcasterMatchesRef(g_vsc.broadcaster)) {
- if (event_mask & eBroadcastBitStopEventThread) {
- done = true;
- }
- }
- }
- }
-}
-
-//----------------------------------------------------------------------
-// Both attach and launch take a either a sourcePath or sourceMap
-// argument (or neither), from which we need to set the target.source-map.
-//----------------------------------------------------------------------
-void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
- const char *sourceMapHelp =
- "source must be be an array of two-element arrays, "
- "each containing a source and replacement path string.\n";
-
- std::string sourceMapCommand;
- llvm::raw_string_ostream strm(sourceMapCommand);
- strm << "settings set target.source-map ";
- auto sourcePath = GetString(arguments, "sourcePath");
-
- // sourceMap is the new, more general form of sourcePath and overrides it.
- auto sourceMap = arguments.getArray("sourceMap");
- if (sourceMap) {
- for (const auto &value : *sourceMap) {
- auto mapping = value.getAsArray();
- if (mapping == nullptr || mapping->size() != 2 ||
- (*mapping)[0].kind() != llvm::json::Value::String ||
- (*mapping)[1].kind() != llvm::json::Value::String) {
- g_vsc.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
- return;
- }
- auto mapFrom = GetAsString((*mapping)[0]);
- auto mapTo = GetAsString((*mapping)[1]);
- strm << "\"" << mapFrom << "\" \"" << mapTo << "\"";
- }
- } else {
- if (ObjectContainsKey(arguments, "sourceMap")) {
- g_vsc.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
- return;
- }
- if (sourcePath.empty())
- return;
- // Do any source remapping needed before we create our targets
- strm << "\".\" \"" << sourcePath << "\"";
- }
- strm.flush();
- if (!sourceMapCommand.empty()) {
- g_vsc.RunLLDBCommands("Setting source map:", {sourceMapCommand});
- }
-}
-
-//----------------------------------------------------------------------
-// "AttachRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Attach request; value of command field is 'attach'.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "attach" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/AttachRequestArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "AttachRequestArguments": {
-// "type": "object",
-// "description": "Arguments for 'attach' request.\nThe attach request has no
-// standardized attributes."
-// },
-// "AttachResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'attach' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_attach(const llvm::json::Object &request) {
- llvm::json::Object response;
- lldb::SBError error;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- const lldb::pid_t pid =
- GetUnsigned(arguments, "pid", LLDB_INVALID_PROCESS_ID);
- if (pid != LLDB_INVALID_PROCESS_ID)
- g_vsc.attach_info.SetProcessID(pid);
- const auto wait_for = GetBoolean(arguments, "waitFor", false);
- g_vsc.attach_info.SetWaitForLaunch(wait_for, false /*async*/);
- g_vsc.init_commands = GetStrings(arguments, "initCommands");
- g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
- g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
- g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
- auto attachCommands = GetStrings(arguments, "attachCommands");
- g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
- const auto debuggerRoot = GetString(arguments, "debuggerRoot");
-
- // This is a hack for loading DWARF in .o files on Mac where the .o files
- // in the debug map of the main executable have relative paths which require
- // the lldb-vscode binary to have its working directory set to that relative
- // root for the .o files in order to be able to load debug info.
- if (!debuggerRoot.empty()) {
- llvm::sys::fs::set_current_path(debuggerRoot.data());
- }
-
- // Run any initialize LLDB commands the user specified in the launch.json
- g_vsc.RunInitCommands();
-
- // Grab the name of the program we need to debug and set it as the first
- // argument that will be passed to the program we will debug.
- const auto program = GetString(arguments, "program");
- if (!program.empty()) {
- lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
-
- g_vsc.launch_info.SetExecutableFile(program_fspec,
- false /*add_as_first_arg*/);
- const char *target_triple = nullptr;
- const char *uuid_cstr = nullptr;
- // Stand alone debug info file if different from executable
- const char *symfile = nullptr;
- g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
- if (error.Fail()) {
- response.try_emplace("success", false);
- EmplaceSafeString(response, "message", std::string(error.GetCString()));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
- return;
- }
- }
-
- const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
- g_vsc.launch_info.SetDetachOnError(detatchOnError);
-
- // Run any pre run LLDB commands the user specified in the launch.json
- g_vsc.RunPreRunCommands();
-
- if (pid == LLDB_INVALID_PROCESS_ID && wait_for) {
- char attach_info[256];
- auto attach_info_len =
- snprintf(attach_info, sizeof(attach_info),
- "Waiting to attach to \"%s\"...", program.data());
- g_vsc.SendOutput(OutputType::Console, llvm::StringRef(attach_info,
- attach_info_len));
- }
- if (attachCommands.empty()) {
- // No "attachCommands", just attach normally.
- // Disable async events so the attach will be successful when we return from
- // the launch call and the launch will happen synchronously
- g_vsc.debugger.SetAsync(false);
- g_vsc.target.Attach(g_vsc.attach_info, error);
- // Reenable async events
- g_vsc.debugger.SetAsync(true);
- } else {
- // We have "attachCommands" that are a set of commands that are expected
- // to execute the commands after which a process should be created. If there
- // is no valid process after running these commands, we have failed.
- g_vsc.RunLLDBCommands("Running attachCommands:", attachCommands);
- // The custom commands might have created a new target so we should use the
- // selected target after these commands are run.
- g_vsc.target = g_vsc.debugger.GetSelectedTarget();
- }
-
- SetSourceMapFromArguments(*arguments);
-
- if (error.Success()) {
- auto attached_pid = g_vsc.target.GetProcess().GetProcessID();
- if (attached_pid == LLDB_INVALID_PROCESS_ID) {
- if (attachCommands.empty())
- error.SetErrorString("failed to attach to a process");
- else
- error.SetErrorString("attachCommands failed to attach to a process");
- }
- }
-
- if (error.Fail()) {
- response.try_emplace("success", false);
- EmplaceSafeString(response, "message", std::string(error.GetCString()));
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
- if (error.Success()) {
- SendProcessEvent(Attach);
- g_vsc.SendJSON(CreateEventObject("initialized"));
- // SendThreadStoppedEvent();
- }
-}
-
-//----------------------------------------------------------------------
-// "ContinueRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Continue request; value of command field is 'continue'.
-// The request starts the debuggee to run again.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "continue" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/ContinueArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "ContinueArguments": {
-// "type": "object",
-// "description": "Arguments for 'continue' request.",
-// "properties": {
-// "threadId": {
-// "type": "integer",
-// "description": "Continue execution for the specified thread (if
-// possible). If the backend cannot continue on a single
-// thread but will continue on all threads, it should
-// set the allThreadsContinued attribute in the response
-// to true."
-// }
-// },
-// "required": [ "threadId" ]
-// },
-// "ContinueResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'continue' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "allThreadsContinued": {
-// "type": "boolean",
-// "description": "If true, the continue request has ignored the
-// specified thread and continued all threads
-// instead. If this attribute is missing a value
-// of 'true' is assumed for backward
-// compatibility."
-// }
-// }
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_continue(const llvm::json::Object &request) {
- 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);
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "ConfigurationDoneRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "ConfigurationDone request; value of command field
-// is 'configurationDone'.\nThe client of the debug protocol must
-// send this request at the end of the sequence of configuration
-// requests (which was started by the InitializedEvent).",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "configurationDone" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/ConfigurationDoneArguments"
-// }
-// },
-// "required": [ "command" ]
-// }]
-// },
-// "ConfigurationDoneArguments": {
-// "type": "object",
-// "description": "Arguments for 'configurationDone' request.\nThe
-// configurationDone request has no standardized attributes."
-// },
-// "ConfigurationDoneResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'configurationDone' request. This is
-// just an acknowledgement, so no body field is required."
-// }]
-// },
-//----------------------------------------------------------------------
-void request_configurationDone(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
- if (g_vsc.stop_at_entry)
- SendThreadStoppedEvent();
- else
- g_vsc.target.GetProcess().Continue();
-}
-
-//----------------------------------------------------------------------
-// "DisconnectRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Disconnect request; value of command field is
-// 'disconnect'.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "disconnect" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/DisconnectArguments"
-// }
-// },
-// "required": [ "command" ]
-// }]
-// },
-// "DisconnectArguments": {
-// "type": "object",
-// "description": "Arguments for 'disconnect' request.",
-// "properties": {
-// "terminateDebuggee": {
-// "type": "boolean",
-// "description": "Indicates whether the debuggee should be terminated
-// when the debugger is disconnected. If unspecified,
-// the debug adapter is free to do whatever it thinks
-// is best. A client can only rely on this attribute
-// being properly honored if a debug adapter returns
-// true for the 'supportTerminateDebuggee' capability."
-// },
-// "restart": {
-// "type": "boolean",
-// "description": "Indicates whether the debuggee should be restart
-// the process."
-// }
-// }
-// },
-// "DisconnectResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'disconnect' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_disconnect(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
-
- bool terminateDebuggee = GetBoolean(arguments, "terminateDebuggee", false);
- lldb::SBProcess process = g_vsc.target.GetProcess();
- auto state = process.GetState();
-
- switch (state) {
- case lldb::eStateInvalid:
- case lldb::eStateUnloaded:
- case lldb::eStateDetached:
- case lldb::eStateExited:
- break;
- case lldb::eStateConnected:
- case lldb::eStateAttaching:
- case lldb::eStateLaunching:
- case lldb::eStateStepping:
- case lldb::eStateCrashed:
- case lldb::eStateSuspended:
- case lldb::eStateStopped:
- case lldb::eStateRunning:
- g_vsc.debugger.SetAsync(false);
- if (terminateDebuggee)
- process.Kill();
- else
- process.Detach();
- g_vsc.debugger.SetAsync(true);
- break;
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
- SendTerminatedEvent();
- if (g_vsc.event_thread.joinable()) {
- g_vsc.broadcaster.BroadcastEventByType(eBroadcastBitStopEventThread);
- g_vsc.event_thread.join();
- }
-}
-
-void request_exceptionInfo(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- llvm::json::Object body;
- lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
- if (thread.IsValid()) {
- auto stopReason = thread.GetStopReason();
- if (stopReason == lldb::eStopReasonSignal)
- body.try_emplace("exceptionId", "signal");
- else if (stopReason == lldb::eStopReasonBreakpoint) {
- ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
- if (exc_bp) {
- EmplaceSafeString(body, "exceptionId", exc_bp->filter);
- EmplaceSafeString(body, "description", exc_bp->label);
- } else {
- body.try_emplace("exceptionId", "exception");
- }
- } else {
- body.try_emplace("exceptionId", "exception");
- }
- if (!ObjectContainsKey(body, "description")) {
- char description[1024];
- if (thread.GetStopDescription(description, sizeof(description))) {
- EmplaceSafeString(body, "description", std::string(description));
- }
- }
- body.try_emplace("breakMode", "always");
- // auto excInfoCount = thread.GetStopReasonDataCount();
- // for (auto i=0; i<excInfoCount; ++i) {
- // uint64_t exc_data = thread.GetStopReasonDataAtIndex(i);
- // }
- } else {
- response.try_emplace("success", false);
- }
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "EvaluateRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Evaluate request; value of command field is 'evaluate'.
-// Evaluates the given expression in the context of the
-// top most stack frame. The expression has access to any
-// variables and arguments that are in scope.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "evaluate" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/EvaluateArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "EvaluateArguments": {
-// "type": "object",
-// "description": "Arguments for 'evaluate' request.",
-// "properties": {
-// "expression": {
-// "type": "string",
-// "description": "The expression to evaluate."
-// },
-// "frameId": {
-// "type": "integer",
-// "description": "Evaluate the expression in the scope of this stack
-// frame. If not specified, the expression is evaluated
-// in the global scope."
-// },
-// "context": {
-// "type": "string",
-// "_enum": [ "watch", "repl", "hover" ],
-// "enumDescriptions": [
-// "evaluate is run in a watch.",
-// "evaluate is run from REPL console.",
-// "evaluate is run from a data hover."
-// ],
-// "description": "The context in which the evaluate request is run."
-// },
-// "format": {
-// "$ref": "#/definitions/ValueFormat",
-// "description": "Specifies details on how to format the Evaluate
-// result."
-// }
-// },
-// "required": [ "expression" ]
-// },
-// "EvaluateResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'evaluate' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "result": {
-// "type": "string",
-// "description": "The result of the evaluate request."
-// },
-// "type": {
-// "type": "string",
-// "description": "The optional type of the evaluate result."
-// },
-// "presentationHint": {
-// "$ref": "#/definitions/VariablePresentationHint",
-// "description": "Properties of a evaluate result that can be
-// used to determine how to render the result in
-// the UI."
-// },
-// "variablesReference": {
-// "type": "number",
-// "description": "If variablesReference is > 0, the evaluate
-// result is structured and its children can be
-// retrieved by passing variablesReference to the
-// VariablesRequest."
-// },
-// "namedVariables": {
-// "type": "number",
-// "description": "The number of named child variables. The
-// client can use this optional information to
-// present the variables in a paged UI and fetch
-// them in chunks."
-// },
-// "indexedVariables": {
-// "type": "number",
-// "description": "The number of indexed child variables. The
-// client can use this optional information to
-// present the variables in a paged UI and fetch
-// them in chunks."
-// }
-// },
-// "required": [ "result", "variablesReference" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_evaluate(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Object body;
- auto arguments = request.getObject("arguments");
- lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
- const auto expression = GetString(arguments, "expression");
-
- if (!expression.empty() && expression[0] == '`') {
- auto result = RunLLDBCommands(llvm::StringRef(),
- {expression.substr(1)});
- EmplaceSafeString(body, "result", result);
- body.try_emplace("variablesReference", (int64_t)0);
- } else {
- // Always try to get the answer from the local variables if possible. If
- // this fails, then actually evaluate an expression using the expression
- // parser. "frame variable" is more reliable than the expression parser in
- // many cases and it is faster.
- lldb::SBValue value = frame.GetValueForVariablePath(
- expression.data(), lldb::eDynamicDontRunTarget);
- if (value.GetError().Fail())
- value = frame.EvaluateExpression(expression.data());
- if (value.GetError().Fail()) {
- response.try_emplace("success", false);
- const char *error_cstr = value.GetError().GetCString();
- if (error_cstr && error_cstr[0])
- EmplaceSafeString(response, "message", std::string(error_cstr));
- else
- EmplaceSafeString(response, "message", "evaluate failed");
- } else {
- SetValueForKey(value, body, "result");
- auto value_typename = value.GetType().GetDisplayTypeName();
- EmplaceSafeString(body, "type", value_typename ? value_typename : NO_TYPENAME);
- if (value.MightHaveChildren()) {
- auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
- g_vsc.variables.Append(value);
- body.try_emplace("variablesReference", variablesReference);
- } else {
- body.try_emplace("variablesReference", (int64_t)0);
- }
- }
- }
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "InitializeRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Initialize request; value of command field is
-// 'initialize'.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "initialize" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/InitializeRequestArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "InitializeRequestArguments": {
-// "type": "object",
-// "description": "Arguments for 'initialize' request.",
-// "properties": {
-// "clientID": {
-// "type": "string",
-// "description": "The ID of the (frontend) client using this adapter."
-// },
-// "adapterID": {
-// "type": "string",
-// "description": "The ID of the debug adapter."
-// },
-// "locale": {
-// "type": "string",
-// "description": "The ISO-639 locale of the (frontend) client using
-// this adapter, e.g. en-US or de-CH."
-// },
-// "linesStartAt1": {
-// "type": "boolean",
-// "description": "If true all line numbers are 1-based (default)."
-// },
-// "columnsStartAt1": {
-// "type": "boolean",
-// "description": "If true all column numbers are 1-based (default)."
-// },
-// "pathFormat": {
-// "type": "string",
-// "_enum": [ "path", "uri" ],
-// "description": "Determines in what format paths are specified. The
-// default is 'path', which is the native format."
-// },
-// "supportsVariableType": {
-// "type": "boolean",
-// "description": "Client supports the optional type attribute for
-// variables."
-// },
-// "supportsVariablePaging": {
-// "type": "boolean",
-// "description": "Client supports the paging of variables."
-// },
-// "supportsRunInTerminalRequest": {
-// "type": "boolean",
-// "description": "Client supports the runInTerminal request."
-// }
-// },
-// "required": [ "adapterID" ]
-// },
-// "InitializeResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'initialize' request.",
-// "properties": {
-// "body": {
-// "$ref": "#/definitions/Capabilities",
-// "description": "The capabilities of this debug adapter."
-// }
-// }
-// }]
-// }
-//----------------------------------------------------------------------
-void request_initialize(const llvm::json::Object &request) {
- g_vsc.debugger = lldb::SBDebugger::Create(true /*source_init_files*/);
- // Create an empty target right away since we might get breakpoint requests
- // before we are given an executable to launch in a "launch" request, or a
- // executable when attaching to a process by process ID in a "attach"
- // request.
- FILE *out = fopen(dev_null_path, "w");
- if (out) {
- // Set the output and error file handles to redirect into nothing otherwise
- // if any code in LLDB prints to the debugger file handles, the output and
- // error file handles are initialized to STDOUT and STDERR and any output
- // will kill our debug session.
- g_vsc.debugger.SetOutputFileHandle(out, true);
- g_vsc.debugger.SetErrorFileHandle(out, false);
- }
-
- g_vsc.target = g_vsc.debugger.CreateTarget(nullptr);
- lldb::SBListener listener = g_vsc.debugger.GetListener();
- listener.StartListeningForEvents(
- g_vsc.target.GetBroadcaster(),
- lldb::SBTarget::eBroadcastBitBreakpointChanged);
- listener.StartListeningForEvents(g_vsc.broadcaster,
- eBroadcastBitStopEventThread);
- // Start our event thread so we can receive events from the debugger, target,
- // process and more.
- g_vsc.event_thread = std::thread(EventThreadFunction);
-
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Object body;
- // The debug adapter supports the configurationDoneRequest.
- body.try_emplace("supportsConfigurationDoneRequest", true);
- // The debug adapter supports function breakpoints.
- body.try_emplace("supportsFunctionBreakpoints", true);
- // The debug adapter supports conditional breakpoints.
- body.try_emplace("supportsConditionalBreakpoints", true);
- // The debug adapter supports breakpoints that break execution after a
- // specified number of hits.
- body.try_emplace("supportsHitConditionalBreakpoints", true);
- // The debug adapter supports a (side effect free) evaluate request for
- // data hovers.
- body.try_emplace("supportsEvaluateForHovers", true);
- // Available filters or options for the setExceptionBreakpoints request.
- llvm::json::Array filters;
- for (const auto &exc_bp : g_vsc.exception_breakpoints) {
- filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
- }
- body.try_emplace("exceptionBreakpointFilters", std::move(filters));
- // The debug adapter supports stepping back via the stepBack and
- // reverseContinue requests.
- body.try_emplace("supportsStepBack", false);
- // The debug adapter supports setting a variable to a value.
- body.try_emplace("supportsSetVariable", true);
- // The debug adapter supports restarting a frame.
- body.try_emplace("supportsRestartFrame", false);
- // The debug adapter supports the gotoTargetsRequest.
- body.try_emplace("supportsGotoTargetsRequest", false);
- // The debug adapter supports the stepInTargetsRequest.
- body.try_emplace("supportsStepInTargetsRequest", false);
- // The debug adapter supports the completionsRequest.
- body.try_emplace("supportsCompletionsRequest", false);
- // The debug adapter supports the modules request.
- body.try_emplace("supportsModulesRequest", false);
- // The set of additional module information exposed by the debug adapter.
- // body.try_emplace("additionalModuleColumns"] = ColumnDescriptor
- // Checksum algorithms supported by the debug adapter.
- // body.try_emplace("supportedChecksumAlgorithms"] = ChecksumAlgorithm
- // The debug adapter supports the RestartRequest. In this case a client
- // should not implement 'restart' by terminating and relaunching the adapter
- // but by calling the RestartRequest.
- body.try_emplace("supportsRestartRequest", false);
- // The debug adapter supports 'exceptionOptions' on the
- // setExceptionBreakpoints request.
- body.try_emplace("supportsExceptionOptions", true);
- // The debug adapter supports a 'format' attribute on the stackTraceRequest,
- // variablesRequest, and evaluateRequest.
- body.try_emplace("supportsValueFormattingOptions", true);
- // The debug adapter supports the exceptionInfo request.
- body.try_emplace("supportsExceptionInfoRequest", true);
- // The debug adapter supports the 'terminateDebuggee' attribute on the
- // 'disconnect' request.
- body.try_emplace("supportTerminateDebuggee", true);
- // The debug adapter supports the delayed loading of parts of the stack,
- // which requires that both the 'startFrame' and 'levels' arguments and the
- // 'totalFrames' result of the 'StackTrace' request are supported.
- body.try_emplace("supportsDelayedStackTraceLoading", true);
- // The debug adapter supports the 'loadedSources' request.
- body.try_emplace("supportsLoadedSourcesRequest", false);
-
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "LaunchRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Launch request; value of command field is 'launch'.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "launch" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/LaunchRequestArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "LaunchRequestArguments": {
-// "type": "object",
-// "description": "Arguments for 'launch' request.",
-// "properties": {
-// "noDebug": {
-// "type": "boolean",
-// "description": "If noDebug is true the launch request should launch
-// the program without enabling debugging."
-// }
-// }
-// },
-// "LaunchResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'launch' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_launch(const llvm::json::Object &request) {
- llvm::json::Object response;
- lldb::SBError error;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- g_vsc.init_commands = GetStrings(arguments, "initCommands");
- g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
- g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
- g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
- g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
- const auto debuggerRoot = GetString(arguments, "debuggerRoot");
-
- // This is a hack for loading DWARF in .o files on Mac where the .o files
- // in the debug map of the main executable have relative paths which require
- // the lldb-vscode binary to have its working directory set to that relative
- // root for the .o files in order to be able to load debug info.
- if (!debuggerRoot.empty()) {
- llvm::sys::fs::set_current_path(debuggerRoot.data());
- }
-
- SetSourceMapFromArguments(*arguments);
-
- // Run any initialize LLDB commands the user specified in the launch.json
- g_vsc.RunInitCommands();
-
- // Grab the current working directory if there is one and set it in the
- // launch info.
- const auto cwd = GetString(arguments, "cwd");
- if (!cwd.empty())
- g_vsc.launch_info.SetWorkingDirectory(cwd.data());
-
- // Grab the name of the program we need to debug and set it as the first
- // argument that will be passed to the program we will debug.
- const auto program = GetString(arguments, "program");
- if (!program.empty()) {
- lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
-
- g_vsc.launch_info.SetExecutableFile(program_fspec,
- true /*add_as_first_arg*/);
- const char *target_triple = nullptr;
- const char *uuid_cstr = nullptr;
- // Stand alone debug info file if different from executable
- const char *symfile = nullptr;
- g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
- if (error.Fail()) {
- response.try_emplace("success", false);
- EmplaceSafeString(response, "message", std::string(error.GetCString()));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
- }
- }
-
- // Extract any extra arguments and append them to our program arguments for
- // when we launch
- auto args = GetStrings(arguments, "args");
- if (!args.empty())
- g_vsc.launch_info.SetArguments(MakeArgv(args).data(), true);
-
- // Pass any environment variables along that the user specified.
- auto envs = GetStrings(arguments, "env");
- if (!envs.empty())
- g_vsc.launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
-
- auto flags = g_vsc.launch_info.GetLaunchFlags();
-
- if (GetBoolean(arguments, "disableASLR", true))
- flags |= lldb::eLaunchFlagDisableASLR;
- if (GetBoolean(arguments, "disableSTDIO", false))
- flags |= lldb::eLaunchFlagDisableSTDIO;
- if (GetBoolean(arguments, "shellExpandArguments", false))
- flags |= lldb::eLaunchFlagShellExpandArguments;
- const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
- g_vsc.launch_info.SetDetachOnError(detatchOnError);
- g_vsc.launch_info.SetLaunchFlags(flags | lldb::eLaunchFlagDebug |
- lldb::eLaunchFlagStopAtEntry);
-
- // Run any pre run LLDB commands the user specified in the launch.json
- g_vsc.RunPreRunCommands();
-
- // Disable async events so the launch will be successful when we return from
- // the launch call and the launch will happen synchronously
- g_vsc.debugger.SetAsync(false);
- g_vsc.target.Launch(g_vsc.launch_info, error);
- if (error.Fail()) {
- response.try_emplace("success", false);
- EmplaceSafeString(response, "message", std::string(error.GetCString()));
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-
- SendProcessEvent(Launch);
- g_vsc.SendJSON(llvm::json::Value(CreateEventObject("initialized")));
- // Reenable async events and start the event thread to catch async events.
- g_vsc.debugger.SetAsync(true);
-}
-
-//----------------------------------------------------------------------
-// "NextRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Next request; value of command field is 'next'. The
-// request starts the debuggee to run again for one step.
-// The debug adapter first sends the NextResponse and then
-// a StoppedEvent (event type 'step') after the step has
-// completed.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "next" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/NextArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "NextArguments": {
-// "type": "object",
-// "description": "Arguments for 'next' request.",
-// "properties": {
-// "threadId": {
-// "type": "integer",
-// "description": "Execute 'next' for this thread."
-// }
-// },
-// "required": [ "threadId" ]
-// },
-// "NextResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'next' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_next(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
- if (thread.IsValid()) {
- // Remember the thread ID that caused the resume so we can set the
- // "threadCausedFocus" boolean value in the "stopped" events.
- g_vsc.focus_tid = thread.GetThreadID();
- thread.StepOver();
- } else {
- response.try_emplace("success", false);
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "PauseRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Pause request; value of command field is 'pause'. The
-// request suspenses the debuggee. The debug adapter first sends the
-// PauseResponse and then a StoppedEvent (event type 'pause') after the
-// thread has been paused successfully.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "pause" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/PauseArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "PauseArguments": {
-// "type": "object",
-// "description": "Arguments for 'pause' request.",
-// "properties": {
-// "threadId": {
-// "type": "integer",
-// "description": "Pause execution for this thread."
-// }
-// },
-// "required": [ "threadId" ]
-// },
-// "PauseResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'pause' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_pause(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- lldb::SBProcess process = g_vsc.target.GetProcess();
- lldb::SBError error = process.Stop();
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "ScopesRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Scopes request; value of command field is 'scopes'. The
-// request returns the variable scopes for a given stackframe ID.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "scopes" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/ScopesArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "ScopesArguments": {
-// "type": "object",
-// "description": "Arguments for 'scopes' request.",
-// "properties": {
-// "frameId": {
-// "type": "integer",
-// "description": "Retrieve the scopes for this stackframe."
-// }
-// },
-// "required": [ "frameId" ]
-// },
-// "ScopesResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'scopes' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "scopes": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Scope"
-// },
-// "description": "The scopes of the stackframe. If the array has
-// length zero, there are no scopes available."
-// }
-// },
-// "required": [ "scopes" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_scopes(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Object body;
- auto arguments = request.getObject("arguments");
- lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
- g_vsc.variables.Clear();
- g_vsc.variables.Append(frame.GetVariables(true, // arguments
- true, // locals
- false, // statics
- true)); // in_scope_only
- g_vsc.num_locals = g_vsc.variables.GetSize();
- g_vsc.variables.Append(frame.GetVariables(false, // arguments
- false, // locals
- true, // statics
- true)); // in_scope_only
- g_vsc.num_globals = g_vsc.variables.GetSize() - (g_vsc.num_locals);
- g_vsc.variables.Append(frame.GetRegisters());
- g_vsc.num_regs =
- g_vsc.variables.GetSize() - (g_vsc.num_locals + g_vsc.num_globals);
- body.try_emplace("scopes", g_vsc.CreateTopLevelScopes());
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "SetBreakpointsRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "SetBreakpoints request; value of command field is
-// 'setBreakpoints'. Sets multiple breakpoints for a single source and
-// clears all previous breakpoints in that source. To clear all breakpoint
-// for a source, specify an empty array. When a breakpoint is hit, a
-// StoppedEvent (event type 'breakpoint') is generated.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "setBreakpoints" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/SetBreakpointsArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "SetBreakpointsArguments": {
-// "type": "object",
-// "description": "Arguments for 'setBreakpoints' request.",
-// "properties": {
-// "source": {
-// "$ref": "#/definitions/Source",
-// "description": "The source location of the breakpoints; either
-// source.path or source.reference must be specified."
-// },
-// "breakpoints": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/SourceBreakpoint"
-// },
-// "description": "The code locations of the breakpoints."
-// },
-// "lines": {
-// "type": "array",
-// "items": {
-// "type": "integer"
-// },
-// "description": "Deprecated: The code locations of the breakpoints."
-// },
-// "sourceModified": {
-// "type": "boolean",
-// "description": "A value of true indicates that the underlying source
-// has been modified which results in new breakpoint locations."
-// }
-// },
-// "required": [ "source" ]
-// },
-// "SetBreakpointsResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'setBreakpoints' request. Returned is
-// information about each breakpoint created by this request. This includes
-// the actual code location and whether the breakpoint could be verified.
-// The breakpoints returned are in the same order as the elements of the
-// 'breakpoints' (or the deprecated 'lines') in the
-// SetBreakpointsArguments.", "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "breakpoints": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Breakpoint"
-// },
-// "description": "Information about the breakpoints. The array
-// elements are in the same order as the elements of the
-// 'breakpoints' (or the deprecated 'lines') in the
-// SetBreakpointsArguments."
-// }
-// },
-// "required": [ "breakpoints" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// },
-// "SourceBreakpoint": {
-// "type": "object",
-// "description": "Properties of a breakpoint or logpoint passed to the
-// setBreakpoints request.", "properties": {
-// "line": {
-// "type": "integer",
-// "description": "The source line of the breakpoint or logpoint."
-// },
-// "column": {
-// "type": "integer",
-// "description": "An optional source column of the breakpoint."
-// },
-// "condition": {
-// "type": "string",
-// "description": "An optional expression for conditional breakpoints."
-// },
-// "hitCondition": {
-// "type": "string",
-// "description": "An optional expression that controls how many hits of
-// the breakpoint are ignored. The backend is expected to interpret the
-// expression as needed."
-// },
-// "logMessage": {
-// "type": "string",
-// "description": "If this attribute exists and is non-empty, the backend
-// must not 'break' (stop) but log the message instead. Expressions within
-// {} are interpolated."
-// }
-// },
-// "required": [ "line" ]
-// }
-//----------------------------------------------------------------------
-void request_setBreakpoints(const llvm::json::Object &request) {
- llvm::json::Object response;
- lldb::SBError error;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- auto source = arguments->getObject("source");
- const auto path = GetString(source, "path");
- auto breakpoints = arguments->getArray("breakpoints");
- llvm::json::Array response_breakpoints;
- // Decode the source breakpoint infos for this "setBreakpoints" request
- SourceBreakpointMap request_bps;
- for (const auto &bp : *breakpoints) {
- auto bp_obj = bp.getAsObject();
- if (bp_obj) {
- SourceBreakpoint src_bp(*bp_obj);
- request_bps[src_bp.line] = std::move(src_bp);
- }
- }
-
- // See if we already have breakpoints set for this source file from a
- // previous "setBreakpoints" request
- auto old_src_bp_pos = g_vsc.source_breakpoints.find(path);
- if (old_src_bp_pos != g_vsc.source_breakpoints.end()) {
-
- // We have already set breakpoints in this source file and they are giving
- // use a new list of lines to set breakpoints on. Some breakpoints might
- // already be set, and some might not. We need to remove any breakpoints
- // whose lines are not contained in the any breakpoints lines in in the
- // "breakpoints" array.
-
- // Delete any breakpoints in this source file that aren't in the
- // request_bps set. There is no call to remove breakpoints other than
- // calling this function with a smaller or empty "breakpoints" list.
- std::vector<uint32_t> remove_lines;
- for (auto &pair: old_src_bp_pos->second) {
- auto request_pos = request_bps.find(pair.first);
- if (request_pos == request_bps.end()) {
- // This breakpoint no longer exists in this source file, delete it
- g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
- remove_lines.push_back(pair.first);
- } else {
- pair.second.UpdateBreakpoint(request_pos->second);
- // Remove this breakpoint from the request breakpoints since we have
- // handled it here and we don't need to set a new breakpoint below.
- request_bps.erase(request_pos);
- // Add this breakpoint info to the response
- AppendBreakpoint(pair.second.bp, response_breakpoints);
- }
- }
- // Remove any lines from this existing source breakpoint map
- for (auto line: remove_lines)
- old_src_bp_pos->second.erase(line);
-
- // Now add any breakpoint infos left over in request_bps are the
- // breakpoints that weren't set in this source file yet. We need to update
- // thread source breakpoint info for the source file in the variable
- // "old_src_bp_pos->second" so the info for this source file is up to date.
- for (auto &pair : request_bps) {
- pair.second.SetBreakpoint(path.data());
- // Add this breakpoint info to the response
- AppendBreakpoint(pair.second.bp, response_breakpoints);
- old_src_bp_pos->second[pair.first] = std::move(pair.second);
- }
- } else {
- // No breakpoints were set for this source file yet. Set all breakpoints
- // for each line and add them to the response and create an entry in
- // g_vsc.source_breakpoints for this source file.
- for (auto &pair : request_bps) {
- pair.second.SetBreakpoint(path.data());
- // Add this breakpoint info to the response
- AppendBreakpoint(pair.second.bp, response_breakpoints);
- }
- g_vsc.source_breakpoints[path] = std::move(request_bps);
- }
-
- llvm::json::Object body;
- body.try_emplace("breakpoints", std::move(response_breakpoints));
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "SetExceptionBreakpointsRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "SetExceptionBreakpoints request; value of command field
-// is 'setExceptionBreakpoints'. The request configures the debuggers
-// response to thrown exceptions. If an exception is configured to break, a
-// StoppedEvent is fired (event type 'exception').", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "setExceptionBreakpoints" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/SetExceptionBreakpointsArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "SetExceptionBreakpointsArguments": {
-// "type": "object",
-// "description": "Arguments for 'setExceptionBreakpoints' request.",
-// "properties": {
-// "filters": {
-// "type": "array",
-// "items": {
-// "type": "string"
-// },
-// "description": "IDs of checked exception options. The set of IDs is
-// returned via the 'exceptionBreakpointFilters' capability."
-// },
-// "exceptionOptions": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/ExceptionOptions"
-// },
-// "description": "Configuration options for selected exceptions."
-// }
-// },
-// "required": [ "filters" ]
-// },
-// "SetExceptionBreakpointsResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'setExceptionBreakpoints' request. This is
-// just an acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_setExceptionBreakpoints(const llvm::json::Object &request) {
- llvm::json::Object response;
- lldb::SBError error;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- auto filters = arguments->getArray("filters");
- // Keep a list of any exception breakpoint filter names that weren't set
- // so we can clear any exception breakpoints if needed.
- std::set<std::string> unset_filters;
- for (const auto &bp : g_vsc.exception_breakpoints)
- unset_filters.insert(bp.filter);
-
- for (const auto &value : *filters) {
- const auto filter = GetAsString(value);
- auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
- if (exc_bp) {
- exc_bp->SetBreakpoint();
- unset_filters.erase(filter);
- }
- }
- for (const auto &filter : unset_filters) {
- auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
- if (exc_bp)
- exc_bp->ClearBreakpoint();
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "SetFunctionBreakpointsRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "SetFunctionBreakpoints request; value of command field is
-// 'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
-// all previous function breakpoints. To clear all function breakpoint,
-// specify an empty array. When a function breakpoint is hit, a StoppedEvent
-// (event type 'function breakpoint') is generated.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "setFunctionBreakpoints" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/SetFunctionBreakpointsArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "SetFunctionBreakpointsArguments": {
-// "type": "object",
-// "description": "Arguments for 'setFunctionBreakpoints' request.",
-// "properties": {
-// "breakpoints": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/FunctionBreakpoint"
-// },
-// "description": "The function names of the breakpoints."
-// }
-// },
-// "required": [ "breakpoints" ]
-// },
-// "FunctionBreakpoint": {
-// "type": "object",
-// "description": "Properties of a breakpoint passed to the
-// setFunctionBreakpoints request.", "properties": {
-// "name": {
-// "type": "string",
-// "description": "The name of the function."
-// },
-// "condition": {
-// "type": "string",
-// "description": "An optional expression for conditional breakpoints."
-// },
-// "hitCondition": {
-// "type": "string",
-// "description": "An optional expression that controls how many hits of
-// the breakpoint are ignored. The backend is expected to interpret the
-// expression as needed."
-// }
-// },
-// "required": [ "name" ]
-// },
-// "SetFunctionBreakpointsResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'setFunctionBreakpoints' request. Returned is
-// information about each breakpoint created by this request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "breakpoints": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Breakpoint"
-// },
-// "description": "Information about the breakpoints. The array
-// elements correspond to the elements of the 'breakpoints' array."
-// }
-// },
-// "required": [ "breakpoints" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_setFunctionBreakpoints(const llvm::json::Object &request) {
- llvm::json::Object response;
- lldb::SBError error;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- auto breakpoints = arguments->getArray("breakpoints");
- FunctionBreakpointMap request_bps;
- llvm::json::Array response_breakpoints;
- for (const auto &value : *breakpoints) {
- auto bp_obj = value.getAsObject();
- if (bp_obj == nullptr)
- continue;
- FunctionBreakpoint func_bp(*bp_obj);
- request_bps[func_bp.functionName] = std::move(func_bp);
- }
-
- std::vector<llvm::StringRef> remove_names;
- // Disable any function breakpoints that aren't in the request_bps.
- // There is no call to remove function breakpoints other than calling this
- // function with a smaller or empty "breakpoints" list.
- for (auto &pair: g_vsc.function_breakpoints) {
- auto request_pos = request_bps.find(pair.first());
- if (request_pos == request_bps.end()) {
- // This function breakpoint no longer exists delete it from LLDB
- g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
- remove_names.push_back(pair.first());
- } else {
- // Update the existing breakpoint as any setting withing the function
- // breakpoint might have changed.
- pair.second.UpdateBreakpoint(request_pos->second);
- // Remove this breakpoint from the request breakpoints since we have
- // handled it here and we don't need to set a new breakpoint below.
- request_bps.erase(request_pos);
- // Add this breakpoint info to the response
- AppendBreakpoint(pair.second.bp, response_breakpoints);
- }
- }
- // Remove any breakpoints that are no longer in our list
- for (const auto &name: remove_names)
- g_vsc.function_breakpoints.erase(name);
-
- // Any breakpoints that are left in "request_bps" are breakpoints that
- // need to be set.
- for (auto &pair : request_bps) {
- pair.second.SetBreakpoint();
- // Add this breakpoint info to the response
- AppendBreakpoint(pair.second.bp, response_breakpoints);
- g_vsc.function_breakpoints[pair.first()] = std::move(pair.second);
- }
-
- llvm::json::Object body;
- body.try_emplace("breakpoints", std::move(response_breakpoints));
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "SourceRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Source request; value of command field is 'source'. The
-// request retrieves the source code for a given source reference.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "source" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/SourceArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "SourceArguments": {
-// "type": "object",
-// "description": "Arguments for 'source' request.",
-// "properties": {
-// "source": {
-// "$ref": "#/definitions/Source",
-// "description": "Specifies the source content to load. Either
-// source.path or source.sourceReference must be specified."
-// },
-// "sourceReference": {
-// "type": "integer",
-// "description": "The reference to the source. This is the same as
-// source.sourceReference. This is provided for backward compatibility
-// since old backends do not understand the 'source' attribute."
-// }
-// },
-// "required": [ "sourceReference" ]
-// },
-// "SourceResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'source' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "content": {
-// "type": "string",
-// "description": "Content of the source reference."
-// },
-// "mimeType": {
-// "type": "string",
-// "description": "Optional content type (mime type) of the source."
-// }
-// },
-// "required": [ "content" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_source(const llvm::json::Object &request) {
- 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.try_emplace("success", false);
- }
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "StackTraceRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "StackTrace request; value of command field is
-// 'stackTrace'. The request returns a stacktrace from the current execution
-// state.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "stackTrace" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/StackTraceArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "StackTraceArguments": {
-// "type": "object",
-// "description": "Arguments for 'stackTrace' request.",
-// "properties": {
-// "threadId": {
-// "type": "integer",
-// "description": "Retrieve the stacktrace for this thread."
-// },
-// "startFrame": {
-// "type": "integer",
-// "description": "The index of the first frame to return; if omitted
-// frames start at 0."
-// },
-// "levels": {
-// "type": "integer",
-// "description": "The maximum number of frames to return. If levels is
-// not specified or 0, all frames are returned."
-// },
-// "format": {
-// "$ref": "#/definitions/StackFrameFormat",
-// "description": "Specifies details on how to format the stack frames."
-// }
-// },
-// "required": [ "threadId" ]
-// },
-// "StackTraceResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'stackTrace' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "stackFrames": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/StackFrame"
-// },
-// "description": "The frames of the stackframe. If the array has
-// length zero, there are no stackframes available. This means that
-// there is no location information available."
-// },
-// "totalFrames": {
-// "type": "integer",
-// "description": "The total number of frames available."
-// }
-// },
-// "required": [ "stackFrames" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_stackTrace(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- lldb::SBError error;
- auto arguments = request.getObject("arguments");
- lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
- llvm::json::Array stackFrames;
- llvm::json::Object body;
-
- if (thread.IsValid()) {
- const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
- const auto levels = GetUnsigned(arguments, "levels", 0);
- const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
- for (uint32_t i = startFrame; i < endFrame; ++i) {
- auto frame = thread.GetFrameAtIndex(i);
- if (!frame.IsValid())
- break;
- stackFrames.emplace_back(CreateStackFrame(frame));
- }
- }
- body.try_emplace("stackFrames", std::move(stackFrames));
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "StepInRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "StepIn request; value of command field is 'stepIn'. The
-// request starts the debuggee to step into a function/method if possible.
-// If it cannot step into a target, 'stepIn' behaves like 'next'. The debug
-// adapter first sends the StepInResponse and then a StoppedEvent (event
-// type 'step') after the step has completed. If there are multiple
-// function/method calls (or other targets) on the source line, the optional
-// argument 'targetId' can be used to control into which target the 'stepIn'
-// should occur. The list of possible targets for a given source line can be
-// retrieved via the 'stepInTargets' request.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "stepIn" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/StepInArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "StepInArguments": {
-// "type": "object",
-// "description": "Arguments for 'stepIn' request.",
-// "properties": {
-// "threadId": {
-// "type": "integer",
-// "description": "Execute 'stepIn' for this thread."
-// },
-// "targetId": {
-// "type": "integer",
-// "description": "Optional id of the target to step into."
-// }
-// },
-// "required": [ "threadId" ]
-// },
-// "StepInResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'stepIn' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_stepIn(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
- if (thread.IsValid()) {
- // Remember the thread ID that caused the resume so we can set the
- // "threadCausedFocus" boolean value in the "stopped" events.
- g_vsc.focus_tid = thread.GetThreadID();
- thread.StepInto();
- } else {
- response.try_emplace("success", false);
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "StepOutRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "StepOut request; value of command field is 'stepOut'. The
-// request starts the debuggee to run again for one step. The debug adapter
-// first sends the StepOutResponse and then a StoppedEvent (event type
-// 'step') after the step has completed.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "stepOut" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/StepOutArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "StepOutArguments": {
-// "type": "object",
-// "description": "Arguments for 'stepOut' request.",
-// "properties": {
-// "threadId": {
-// "type": "integer",
-// "description": "Execute 'stepOut' for this thread."
-// }
-// },
-// "required": [ "threadId" ]
-// },
-// "StepOutResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'stepOut' request. This is just an
-// acknowledgement, so no body field is required."
-// }]
-// }
-//----------------------------------------------------------------------
-void request_stepOut(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- auto arguments = request.getObject("arguments");
- lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
- if (thread.IsValid()) {
- // Remember the thread ID that caused the resume so we can set the
- // "threadCausedFocus" boolean value in the "stopped" events.
- g_vsc.focus_tid = thread.GetThreadID();
- thread.StepOut();
- } else {
- response.try_emplace("success", false);
- }
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "ThreadsRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Thread request; value of command field is 'threads'. The
-// request retrieves a list of all threads.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "threads" ]
-// }
-// },
-// "required": [ "command" ]
-// }]
-// },
-// "ThreadsResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'threads' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "threads": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Thread"
-// },
-// "description": "All threads."
-// }
-// },
-// "required": [ "threads" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_threads(const llvm::json::Object &request) {
-
- lldb::SBProcess process = g_vsc.target.GetProcess();
- llvm::json::Object response;
- FillResponse(request, response);
-
- const uint32_t num_threads = process.GetNumThreads();
- llvm::json::Array threads;
- for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
- lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
- threads.emplace_back(CreateThread(thread));
- }
- if (threads.size() == 0) {
- response.try_emplace("success", false);
- }
- llvm::json::Object body;
- body.try_emplace("threads", std::move(threads));
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "SetVariableRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "setVariable request; value of command field is
-// 'setVariable'. Set the variable with the given name in the variable
-// container to a new value.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "setVariable" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/SetVariableArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "SetVariableArguments": {
-// "type": "object",
-// "description": "Arguments for 'setVariable' request.",
-// "properties": {
-// "variablesReference": {
-// "type": "integer",
-// "description": "The reference of the variable container."
-// },
-// "name": {
-// "type": "string",
-// "description": "The name of the variable."
-// },
-// "value": {
-// "type": "string",
-// "description": "The value of the variable."
-// },
-// "format": {
-// "$ref": "#/definitions/ValueFormat",
-// "description": "Specifies details on how to format the response value."
-// }
-// },
-// "required": [ "variablesReference", "name", "value" ]
-// },
-// "SetVariableResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'setVariable' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "value": {
-// "type": "string",
-// "description": "The new value of the variable."
-// },
-// "type": {
-// "type": "string",
-// "description": "The type of the new value. Typically shown in the
-// UI when hovering over the value."
-// },
-// "variablesReference": {
-// "type": "number",
-// "description": "If variablesReference is > 0, the new value is
-// structured and its children can be retrieved by passing
-// variablesReference to the VariablesRequest."
-// },
-// "namedVariables": {
-// "type": "number",
-// "description": "The number of named child variables. The client
-// can use this optional information to present the variables in a
-// paged UI and fetch them in chunks."
-// },
-// "indexedVariables": {
-// "type": "number",
-// "description": "The number of indexed child variables. The client
-// can use this optional information to present the variables in a
-// paged UI and fetch them in chunks."
-// }
-// },
-// "required": [ "value" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_setVariable(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Array variables;
- llvm::json::Object body;
- auto arguments = request.getObject("arguments");
- // This is a reference to the containing variable/scope
- const auto variablesReference =
- GetUnsigned(arguments, "variablesReference", 0);
- const auto name = GetString(arguments, "name");
- const auto value = GetString(arguments, "value");
- // Set success to false just in case we don't find the variable by name
- response.try_emplace("success", false);
-
- lldb::SBValue variable;
- int64_t newVariablesReference = 0;
-
- // The "id" is the unique integer ID that is unique within the enclosing
- // variablesReference. It is optionally added to any "interface Variable"
- // objects to uniquely identify a variable within an enclosing
- // variablesReference. It helps to disambiguate between two variables that
- // have the same name within the same scope since the "setVariables" request
- // only specifies the variable reference of the enclosing scope/variable, and
- // the name of the variable. We could have two shadowed variables with the
- // same name in "Locals" or "Globals". In our case the "id" absolute index
- // of the variable within the g_vsc.variables list.
- const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
- if (id_value != UINT64_MAX) {
- variable = g_vsc.variables.GetValueAtIndex(id_value);
- } else if (VARREF_IS_SCOPE(variablesReference)) {
- // variablesReference is one of our scopes, not an actual variable it is
- // asking for a variable in locals or globals or registers
- int64_t start_idx = 0;
- int64_t end_idx = 0;
- switch (variablesReference) {
- case VARREF_LOCALS:
- start_idx = 0;
- end_idx = start_idx + g_vsc.num_locals;
- break;
- case VARREF_GLOBALS:
- start_idx = g_vsc.num_locals;
- end_idx = start_idx + g_vsc.num_globals;
- break;
- case VARREF_REGS:
- start_idx = g_vsc.num_locals + g_vsc.num_globals;
- end_idx = start_idx + g_vsc.num_regs;
- break;
- default:
- break;
- }
-
- // Find the variable by name in the correct scope and hope we don't have
- // multiple variables with the same name. We search backwards because
- // the list of variables has the top most variables first and variables
- // in deeper scopes are last. This means we will catch the deepest
- // variable whose name matches which is probably what the user wants.
- for (int64_t i = end_idx - 1; i >= start_idx; --i) {
- auto curr_variable = g_vsc.variables.GetValueAtIndex(i);
- llvm::StringRef variable_name(curr_variable.GetName());
- if (variable_name == name) {
- variable = curr_variable;
- if (curr_variable.MightHaveChildren())
- newVariablesReference = i;
- break;
- }
- }
- } else {
- // We have a named item within an actual variable so we need to find it
- // withing the container variable by name.
- const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
- lldb::SBValue container = g_vsc.variables.GetValueAtIndex(var_idx);
- variable = container.GetChildMemberWithName(name.data());
- if (!variable.IsValid()) {
- if (name.startswith("[")) {
- llvm::StringRef index_str(name.drop_front(1));
- uint64_t index = 0;
- if (!index_str.consumeInteger(0, index)) {
- if (index_str == "]")
- variable = container.GetChildAtIndex(index);
- }
- }
- }
-
- // We don't know the index of the variable in our g_vsc.variables
- if (variable.IsValid()) {
- if (variable.MightHaveChildren()) {
- newVariablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
- g_vsc.variables.Append(variable);
- }
- }
- }
-
- if (variable.IsValid()) {
- lldb::SBError error;
- bool success = variable.SetValueFromCString(value.data(), error);
- if (success) {
- SetValueForKey(variable, body, "value");
- EmplaceSafeString(body, "type", variable.GetType().GetDisplayTypeName());
- body.try_emplace("variablesReference", newVariablesReference);
- } else {
- EmplaceSafeString(body, "message", std::string(error.GetCString()));
- }
- response.try_emplace("success", success);
- }
-
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-//----------------------------------------------------------------------
-// "VariablesRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Variables request; value of command field is 'variables'.
-// Retrieves all child variables for the given variable reference. An
-// optional filter can be used to limit the fetched children to either named
-// or indexed children.", "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "variables" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/VariablesArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "VariablesArguments": {
-// "type": "object",
-// "description": "Arguments for 'variables' request.",
-// "properties": {
-// "variablesReference": {
-// "type": "integer",
-// "description": "The Variable reference."
-// },
-// "filter": {
-// "type": "string",
-// "enum": [ "indexed", "named" ],
-// "description": "Optional filter to limit the child variables to either
-// named or indexed. If ommited, both types are fetched."
-// },
-// "start": {
-// "type": "integer",
-// "description": "The index of the first variable to return; if omitted
-// children start at 0."
-// },
-// "count": {
-// "type": "integer",
-// "description": "The number of variables to return. If count is missing
-// or 0, all variables are returned."
-// },
-// "format": {
-// "$ref": "#/definitions/ValueFormat",
-// "description": "Specifies details on how to format the Variable
-// values."
-// }
-// },
-// "required": [ "variablesReference" ]
-// },
-// "VariablesResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'variables' request.",
-// "properties": {
-// "body": {
-// "type": "object",
-// "properties": {
-// "variables": {
-// "type": "array",
-// "items": {
-// "$ref": "#/definitions/Variable"
-// },
-// "description": "All (or a range) of variables for the given
-// variable reference."
-// }
-// },
-// "required": [ "variables" ]
-// }
-// },
-// "required": [ "body" ]
-// }]
-// }
-//----------------------------------------------------------------------
-void request_variables(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Array variables;
- auto arguments = request.getObject("arguments");
- const auto variablesReference =
- GetUnsigned(arguments, "variablesReference", 0);
- const int64_t start = GetSigned(arguments, "start", 0);
- const int64_t count = GetSigned(arguments, "count", 0);
- bool hex = false;
- auto format = arguments->getObject("format");
- if (format)
- hex = GetBoolean(format, "hex", false);
-
- if (VARREF_IS_SCOPE(variablesReference)) {
- // variablesReference is one of our scopes, not an actual variable it is
- // asking for the list of args, locals or globals.
- int64_t start_idx = 0;
- int64_t num_children = 0;
- switch (variablesReference) {
- case VARREF_LOCALS:
- start_idx = start;
- num_children = g_vsc.num_locals;
- break;
- case VARREF_GLOBALS:
- start_idx = start + g_vsc.num_locals + start;
- num_children = g_vsc.num_globals;
- break;
- case VARREF_REGS:
- start_idx = start + g_vsc.num_locals + g_vsc.num_globals;
- num_children = g_vsc.num_regs;
- break;
- default:
- break;
- }
- const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
- for (auto i = start_idx; i < end_idx; ++i) {
- lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
- if (!variable.IsValid())
- break;
- variables.emplace_back(
- CreateVariable(variable, VARIDX_TO_VARREF(i), i, hex));
- }
- } else {
- // We are expanding a variable that has children, so we will return its
- // children.
- const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
- lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(var_idx);
- if (variable.IsValid()) {
- const auto num_children = variable.GetNumChildren();
- const int64_t end_idx = start + ((count == 0) ? num_children : count);
- for (auto i = start; i < end_idx; ++i) {
- lldb::SBValue child = variable.GetChildAtIndex(i);
- if (!child.IsValid())
- break;
- if (child.MightHaveChildren()) {
- const int64_t var_idx = g_vsc.variables.GetSize();
- auto childVariablesReferences = VARIDX_TO_VARREF(var_idx);
- variables.emplace_back(
- CreateVariable(child, childVariablesReferences, var_idx, hex));
- g_vsc.variables.Append(child);
- } else {
- variables.emplace_back(CreateVariable(child, 0, INT64_MAX, hex));
- }
- }
- }
- }
- llvm::json::Object body;
- body.try_emplace("variables", std::move(variables));
- response.try_emplace("body", std::move(body));
- g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-// A request used in testing to get the details on all breakpoints that are
-// currently set in the target. This helps us to test "setBreakpoints" and
-// "setFunctionBreakpoints" requests to verify we have the correct set of
-// breakpoints currently set in LLDB.
-void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Array response_breakpoints;
- for (uint32_t i = 0; g_vsc.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
- auto bp = g_vsc.target.GetBreakpointAtIndex(i);
- AppendBreakpoint(bp, response_breakpoints);
- }
- llvm::json::Object body;
- body.try_emplace("breakpoints", std::move(response_breakpoints));
- response.try_emplace("body", std::move(body));
- 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(continue),
- REQUEST_CALLBACK(configurationDone),
- REQUEST_CALLBACK(disconnect),
- REQUEST_CALLBACK(evaluate),
- REQUEST_CALLBACK(exceptionInfo),
- 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;
-}
-
-} // anonymous namespace
-
-int main(int argc, char *argv[]) {
-
- // Initialize LLDB first before we do anything.
- lldb::SBDebugger::Initialize();
-
- if (argc == 2) {
- const char *arg = argv[1];
-#if !defined(_WIN32)
- if (strcmp(arg, "-g") == 0) {
- printf("Paused waiting for debugger to attach (pid = %i)...\n", getpid());
- pause();
- } else {
-#else
- {
-#endif
- int portno = atoi(arg);
- printf("Listening on port %i...\n", portno);
- int socket_fd = AcceptConnection(portno);
- if (socket_fd >= 0) {
- // We must open two FILE objects, one for reading and one for writing
- // the FILE objects have a mutex in them that won't allow reading and
- // writing to the socket stream.
- g_vsc.in = fdopen(socket_fd, "r");
- g_vsc.out = fdopen(socket_fd, "w");
- if (g_vsc.in == nullptr || g_vsc.out == nullptr) {
- if (g_vsc.log)
- *g_vsc.log << "fdopen failed (" << strerror(errno) << ")"
- << std::endl;
- exit(1);
- }
- } else {
- exit(1);
- }
- }
- }
- auto request_handlers = GetRequestHandlers();
- uint32_t packet_idx = 0;
- while (true) {
- std::string json = g_vsc.ReadJSON();
- if (json.empty())
- break;
-
- 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;
- 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(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;
- }
-
- // We must terminate the debugger in a thread before the C++ destructor
- // chain messes everything up.
- lldb::SBDebugger::Terminate();
- return 0;
-}
diff --git a/tools/lldb-vscode/package.json b/tools/lldb-vscode/package.json
deleted file mode 100644
index aa3de65c172f..000000000000
--- a/tools/lldb-vscode/package.json
+++ /dev/null
@@ -1,242 +0,0 @@
-{
- "name": "lldb-vscode",
- "displayName": "LLDB native Debug stub",
- "version": "0.1.0",
- "publisher": "llvm.org",
- "description": "Debug adapter for LLDB which uses a C++ tool to interface directly with LLDB.",
- "author": {
- "name": "Greg Clayton",
- "email": "clayborg@gmail.com"
- },
- "license": "LLVM",
- "keywords": [
- "multi-root ready"
- ],
- "engines": {
- "vscode": "^1.18.0",
- "node": "^7.9.0"
- },
- "icon": "images/lldb.png",
- "categories": [
- "Debuggers"
- ],
- "private": true,
- "devDependencies": {
- "@types/node": "7.0.43",
- "@types/mocha": "2.2.45",
- "typescript": "2.6.2",
- "mocha": "4.0.1",
- "vscode": "1.1.10",
- "vscode-debugadapter-testsupport": "1.25.0",
- "tslint": "5.8.0",
- "vsce": "1.35.0"
- },
- "contributes": {
- "debuggers": [
- {
- "type": "lldb-vscode",
- "label": "Native LLDB Debugger",
- "enableBreakpointsFor": {
- "languageIds": [
- "ada",
- "arm",
- "asm",
- "c",
- "cpp",
- "crystal",
- "d",
- "fortan",
- "fortran-modern",
- "nim",
- "objective-c",
- "objectpascal",
- "pascal",
- "rust",
- "swift"
- ]
- },
- "program": "./bin/lldb-vscode",
- "configurationAttributes": {
- "launch": {
- "required": [
- "program"
- ],
- "properties": {
- "program": {
- "type": "string",
- "description": "Path to the program to debug."
- },
- "args": {
- "type": [ "array", "string" ],
- "description": "Program arguments.",
- "default": []
- },
- "cwd": {
- "type": "string",
- "description": "Program working directory.",
- "default": "${workspaceRoot}"
- },
- "env": {
- "type": "array",
- "description": "Additional environment variables.",
- "default": []
- },
- "stopOnEntry": {
- "type": "boolean",
- "description": "Automatically stop after launch.",
- "default": false
- },
- "disableASLR": {
- "type": "boolean",
- "description": "Enable or disable Address space layout randomization if the debugger supports it.",
- "default": true
- },
- "disableSTDIO": {
- "type": "boolean",
- "description": "Don't retrieve STDIN, STDOUT and STDERR as the program is running.",
- "default": false
- },
- "shellExpandArguments": {
- "type": "boolean",
- "description": "Expand program arguments as a shell would without actually launching the program in a shell.",
- "default": false
- },
- "detachOnError": {
- "type": "boolean",
- "description": "Detach from the program.",
- "default": false
- },
- "trace": {
- "type": "boolean",
- "description": "Enable logging of the Debug Adapter Protocol.",
- "default": true
- },
- "sourcePath": {
- "type": "string",
- "description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
- },
- "sourceMap": {
- "type": "array",
- "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and desination pathname. Overrides sourcePath.",
- "default": []
- },
- "debuggerRoot": {
- "type": "string",
- "description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
- },
- "initCommands": {
- "type": "array",
- "description": "Initialization commands executed upon debugger startup.",
- "default": []
- },
- "preRunCommands": {
- "type": "array",
- "description": "Commands executed just before the program is launched.",
- "default": []
- },
- "stopCommands": {
- "type": "array",
- "description": "Commands executed each time the program stops.",
- "default": []
- },
- "exitCommands": {
- "type": "array",
- "description": "Commands executed at the end of debugging session.",
- "default": []
- }
- }
- },
- "attach": {
- "properties": {
- "program": {
- "type": "string",
- "description": "Path to the program to attach to."
- },
- "pid": {
- "type": [
- "number",
- "string"
- ],
- "description": "System process ID to attach to."
- },
- "waitFor": {
- "type": "boolean",
- "description": "If set to true, then wait for the process to launch by looking for a process with a basename that matches `program`. No process ID needs to be specified when using this flag.",
- "default": true
- },
- "trace": {
- "type": "boolean",
- "description": "Enable logging of the Debug Adapter Protocol.",
- "default": true
- },
- "sourcePath": {
- "type": "string",
- "description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
- },
- "sourceMap": {
- "type": "array",
- "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and desination pathname. Overrides sourcePath.",
- "default": []
- },
- "debuggerRoot": {
- "type": "string",
- "description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
- },
- "attachCommands": {
- "type": "array",
- "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail.",
- "default": []
- },
- "initCommands": {
- "type": "array",
- "description": "Initialization commands executed upon debugger startup.",
- "default": []
- },
- "preRunCommands": {
- "type": "array",
- "description": "Commands executed just before the program is attached to.",
- "default": []
- },
- "stopCommands": {
- "type": "array",
- "description": "Commands executed each time the program stops.",
- "default": []
- },
- "exitCommands": {
- "type": "array",
- "description": "Commands executed at the end of debugging session.",
- "default": []
- }
- }
- }
- },
- "initialConfigurations": [
- {
- "type": "lldb-vscode",
- "request": "launch",
- "name": "Debug",
- "program": "${workspaceRoot}/<your program>",
- "args": [],
- "env": [],
- "cwd": "${workspaceRoot}"
- }
- ],
- "configurationSnippets": [
- {
- "label": "LLDB: Launch",
- "description": "",
- "body": {
- "type": "lldb-vscode",
- "request": "launch",
- "name": "${2:Launch}",
- "program": "^\"\\${workspaceRoot}/${1:<your program>}\"",
- "args": [],
- "env": [],
- "cwd": "^\"\\${workspaceRoot}\""
- }
- }
- ]
- }
- ]
- }
-}