summaryrefslogtreecommitdiff
path: root/lldb/tools/lldb-dap/lldb-dap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/tools/lldb-dap/lldb-dap.cpp')
-rw-r--r--lldb/tools/lldb-dap/lldb-dap.cpp115
1 files changed, 88 insertions, 27 deletions
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index ac18e8f24a4e..a167088c8901 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -1561,6 +1561,19 @@ void request_completions(const llvm::json::Object &request) {
// client can use this optional information to
// present the variables in a paged UI and fetch
// them in chunks."
+// },
+// "valueLocationReference": {
+// "type": "integer",
+// "description": "A reference that allows the client to request
+// the location where the returned value is
+// declared. For example, if a function pointer is
+// returned, the adapter may be able to look up the
+// function's location. This should be present only
+// if the adapter is likely to be able to resolve
+// the location.\n\nThis reference shares the same
+// lifetime as the `variablesReference`. See
+// 'Lifetime of Object References' in the
+// Overview section for details."
// }
// "memoryReference": {
// "type": "string",
@@ -1647,16 +1660,19 @@ void request_evaluate(const llvm::json::Object &request) {
VariableDescription desc(value);
EmplaceSafeString(body, "result", desc.GetResult(context));
EmplaceSafeString(body, "type", desc.display_type_name);
- if (value.MightHaveChildren()) {
- auto variableReference = g_dap.variables.InsertVariable(
+ int64_t var_ref = 0;
+ if (value.MightHaveChildren() || ValuePointsToCode(value))
+ var_ref = g_dap.variables.InsertVariable(
value, /*is_permanent=*/context == "repl");
- body.try_emplace("variablesReference", variableReference);
- } else {
+ if (value.MightHaveChildren())
+ body.try_emplace("variablesReference", var_ref);
+ else
body.try_emplace("variablesReference", (int64_t)0);
- }
if (lldb::addr_t addr = value.GetLoadAddress();
addr != LLDB_INVALID_ADDRESS)
body.try_emplace("memoryReference", EncodeMemoryReference(addr));
+ if (ValuePointsToCode(value))
+ body.try_emplace("valueLocationReference", var_ref);
}
}
response.try_emplace("body", std::move(body));
@@ -3770,6 +3786,17 @@ void request_threads(const llvm::json::Object &request) {
// "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."
+// },
+// "valueLocationReference": {
+// "type": "integer",
+// "description": "A reference that allows the client to request the
+// location where the new value is declared. For example, if the new
+// value is function pointer, the adapter may be able to look up the
+// function's location. This should be present only if the adapter
+// is likely to be able to resolve the location.\n\nThis reference
+// shares the same lifetime as the `variablesReference`. See
+// 'Lifetime of Object References' in the Overview section for
+// details."
// }
// },
// "required": [ "value" ]
@@ -3794,7 +3821,6 @@ void request_setVariable(const llvm::json::Object &request) {
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"
@@ -3824,14 +3850,17 @@ void request_setVariable(const llvm::json::Object &request) {
// so always insert a new one to get its variablesReference.
// is_permanent is false because debug console does not support
// setVariable request.
+ int64_t new_var_ref =
+ g_dap.variables.InsertVariable(variable, /*is_permanent=*/false);
if (variable.MightHaveChildren())
- newVariablesReference =
- g_dap.variables.InsertVariable(variable, /*is_permanent=*/false);
- body.try_emplace("variablesReference", newVariablesReference);
-
+ body.try_emplace("variablesReference", new_var_ref);
+ else
+ body.try_emplace("variablesReference", 0);
if (lldb::addr_t addr = variable.GetLoadAddress();
addr != LLDB_INVALID_ADDRESS)
body.try_emplace("memoryReference", EncodeMemoryReference(addr));
+ if (ValuePointsToCode(variable))
+ body.try_emplace("valueLocationReference", new_var_ref);
} else {
EmplaceSafeString(body, "message", std::string(error.GetCString()));
}
@@ -4122,10 +4151,13 @@ void request_variables(const llvm::json::Object &request) {
void request_locations(const llvm::json::Object &request) {
llvm::json::Object response;
FillResponse(request, response);
- auto arguments = request.getObject("arguments");
+ auto *arguments = request.getObject("arguments");
- uint64_t reference_id = GetUnsigned(arguments, "locationReference", 0);
- lldb::SBValue variable = g_dap.variables.GetVariable(reference_id);
+ uint64_t location_id = GetUnsigned(arguments, "locationReference", 0);
+ // We use the lowest bit to distinguish between value location and declaration
+ // location
+ auto [var_ref, is_value_location] = UnpackLocation(location_id);
+ lldb::SBValue variable = g_dap.variables.GetVariable(var_ref);
if (!variable.IsValid()) {
response["success"] = false;
response["message"] = "Invalid variable reference";
@@ -4133,21 +4165,50 @@ void request_locations(const llvm::json::Object &request) {
return;
}
- // Get the declaration location
- lldb::SBDeclaration decl = variable.GetDeclaration();
- if (!decl.IsValid()) {
- response["success"] = false;
- response["message"] = "No declaration location available";
- g_dap.SendJSON(llvm::json::Value(std::move(response)));
- return;
- }
-
llvm::json::Object body;
- body.try_emplace("source", CreateSource(decl.GetFileSpec()));
- if (int line = decl.GetLine())
- body.try_emplace("line", line);
- if (int column = decl.GetColumn())
- body.try_emplace("column", column);
+ if (is_value_location) {
+ // Get the value location
+ if (!variable.GetType().IsPointerType() &&
+ !variable.GetType().IsReferenceType()) {
+ response["success"] = false;
+ response["message"] =
+ "Value locations are only available for pointers and references";
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
+
+ lldb::addr_t addr = variable.GetValueAsAddress();
+ lldb::SBLineEntry line_entry =
+ g_dap.target.ResolveLoadAddress(addr).GetLineEntry();
+
+ if (!line_entry.IsValid()) {
+ response["success"] = false;
+ response["message"] = "Failed to resolve line entry for location";
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
+
+ body.try_emplace("source", CreateSource(line_entry.GetFileSpec()));
+ if (int line = line_entry.GetLine())
+ body.try_emplace("line", line);
+ if (int column = line_entry.GetColumn())
+ body.try_emplace("column", column);
+ } else {
+ // Get the declaration location
+ lldb::SBDeclaration decl = variable.GetDeclaration();
+ if (!decl.IsValid()) {
+ response["success"] = false;
+ response["message"] = "No declaration location available";
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
+
+ body.try_emplace("source", CreateSource(decl.GetFileSpec()));
+ if (int line = decl.GetLine())
+ body.try_emplace("line", line);
+ if (int column = decl.GetColumn())
+ body.try_emplace("column", column);
+ }
response.try_emplace("body", std::move(body));
g_dap.SendJSON(llvm::json::Value(std::move(response)));