diff options
Diffstat (limited to 'lldb/tools/lldb-dap/lldb-dap.cpp')
| -rw-r--r-- | lldb/tools/lldb-dap/lldb-dap.cpp | 115 |
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))); |
