Skip to content

Commit 26d5c6f

Browse files
committed
Updating Variable::memoryReference to be an lldb::addr_t and creating a new helper for decoding memory references from JSON objects.
1 parent a1ba628 commit 26d5c6f

File tree

8 files changed

+129
-11
lines changed

8 files changed

+129
-11
lines changed

lldb/tools/lldb-dap/Handler/VariablesRequestHandler.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,11 @@ VariablesRequestHandler::Run(const VariablesArguments &arguments) const {
123123
if (!variable.IsValid())
124124
break;
125125

126-
int64_t var_ref =
126+
int64_t frame_var_ref =
127127
dap.variables.InsertVariable(variable, /*is_permanent=*/false);
128128
variables.emplace_back(CreateVariable(
129-
variable, var_ref, hex, dap.configuration.enableAutoVariableSummaries,
129+
variable, frame_var_ref, hex,
130+
dap.configuration.enableAutoVariableSummaries,
130131
dap.configuration.enableSyntheticChildDebugging,
131132
variable_name_counts[GetNonNullVariableName(variable)] > 1));
132133
}

lldb/tools/lldb-dap/JSONUtils.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,42 @@ DecodeMemoryReference(llvm::StringRef memoryReference) {
120120
return addr;
121121
}
122122

123+
bool DecodeMemoryReference(const llvm::json::Value &v, llvm::StringLiteral key,
124+
lldb::addr_t &out, llvm::json::Path path,
125+
bool required) {
126+
const llvm::json::Object *v_obj = v.getAsObject();
127+
if (!v_obj) {
128+
path.report("expected object");
129+
return false;
130+
}
131+
132+
const llvm::json::Value *mem_ref_value = v_obj->get(key);
133+
if (!mem_ref_value) {
134+
if (!required)
135+
return true;
136+
137+
path.field(key).report("missing value");
138+
return false;
139+
}
140+
141+
const std::optional<llvm::StringRef> mem_ref_str =
142+
mem_ref_value->getAsString();
143+
if (!mem_ref_str) {
144+
path.field(key).report("expected string");
145+
return false;
146+
}
147+
148+
const std::optional<lldb::addr_t> addr_opt =
149+
DecodeMemoryReference(*mem_ref_str);
150+
if (!addr_opt) {
151+
path.field(key).report("malformed memory reference");
152+
return false;
153+
}
154+
155+
out = *addr_opt;
156+
return true;
157+
}
158+
123159
std::vector<std::string> GetStrings(const llvm::json::Object *obj,
124160
llvm::StringRef key) {
125161
std::vector<std::string> strs;

lldb/tools/lldb-dap/JSONUtils.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,30 @@ std::string EncodeMemoryReference(lldb::addr_t addr);
138138
std::optional<lldb::addr_t>
139139
DecodeMemoryReference(llvm::StringRef memoryReference);
140140

141+
/// Decodes a memory reference from the given json value.
142+
///
143+
/// \param[in] v
144+
/// A JSON value that we expected to contain the memory reference.
145+
///
146+
/// \param[in] key
147+
/// The key of the memory reference.
148+
///
149+
/// \param[out] out
150+
/// The memory address, if successfully decoded.
151+
///
152+
/// \param[in] path
153+
/// The path for reporting errors.
154+
///
155+
/// \param[in] required
156+
/// Indicates if the key is required to be present, otherwise report an error
157+
/// if the key is missing.
158+
///
159+
/// \return
160+
/// Returns \b true if the address was decoded successfully.
161+
bool DecodeMemoryReference(const llvm::json::Value &v, llvm::StringLiteral key,
162+
lldb::addr_t &out, llvm::json::Path path,
163+
bool required);
164+
141165
/// Extract an array of strings for the specified key from an object.
142166
///
143167
/// String values in the array will be extracted without any quotes

lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Protocol/ProtocolTypes.h"
1010
#include "JSONUtils.h"
1111
#include "ProtocolUtils.h"
12+
#include "lldb/lldb-defines.h"
1213
#include "lldb/lldb-types.h"
1314
#include "llvm/ADT/StringExtras.h"
1415
#include "llvm/ADT/StringRef.h"
@@ -992,8 +993,9 @@ json::Value toJSON(const Variable &V) {
992993
result.insert({"namedVariables", V.namedVariables});
993994
if (V.indexedVariables)
994995
result.insert({"indexedVariables", V.indexedVariables});
995-
if (!V.memoryReference.empty())
996-
result.insert({"memoryReference", V.memoryReference});
996+
if (V.memoryReference != LLDB_INVALID_ADDRESS)
997+
result.insert(
998+
{"memoryReference", EncodeMemoryReference(V.memoryReference)});
997999
if (V.declarationLocationReference)
9981000
result.insert(
9991001
{"declarationLocationReference", V.declarationLocationReference});
@@ -1012,10 +1014,11 @@ bool fromJSON(const json::Value &Param, Variable &V, json::Path Path) {
10121014
O.mapOptional("evaluateName", V.evaluateName) &&
10131015
O.mapOptional("namedVariables", V.namedVariables) &&
10141016
O.mapOptional("indexedVariables", V.indexedVariables) &&
1015-
O.mapOptional("memoryReference", V.memoryReference) &&
10161017
O.mapOptional("declarationLocationReference",
10171018
V.declarationLocationReference) &&
1018-
O.mapOptional("valueLocationReference", V.valueLocationReference);
1019+
O.mapOptional("valueLocationReference", V.valueLocationReference) &&
1020+
DecodeMemoryReference(Param, "memoryReference", V.memoryReference,
1021+
Path, /*required=*/false);
10191022
}
10201023

10211024
} // namespace lldb_dap::protocol

lldb/tools/lldb-dap/Protocol/ProtocolTypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ struct Variable {
897897
///
898898
/// This attribute may be returned by a debug adapter if corresponding
899899
/// capability `supportsMemoryReferences` is true.
900-
std::string memoryReference;
900+
lldb::addr_t memoryReference = LLDB_INVALID_ADDRESS;
901901

902902
/// A reference that allows the client to request the location where the
903903
/// variable is declared. This should be present only if the adapter is likely

lldb/tools/lldb-dap/ProtocolUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ Variable CreateVariable(lldb::SBValue v, int64_t var_ref, bool format_hex,
299299
var.valueLocationReference = PackLocation(var_ref, true);
300300

301301
if (lldb::addr_t addr = v.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS)
302-
var.memoryReference = EncodeMemoryReference(addr);
302+
var.memoryReference = addr;
303303

304304
return var;
305305
}

lldb/unittests/DAP/JSONUtilsTest.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "JSONUtils.h"
10-
#include "lldb/API/SBModule.h"
11-
#include "lldb/API/SBTarget.h"
10+
#include "lldb/lldb-defines.h"
1211
#include "llvm/Support/JSON.h"
12+
#include "llvm/Testing/Support/Error.h"
1313
#include "gtest/gtest.h"
1414
#include <optional>
1515

@@ -182,3 +182,57 @@ TEST(JSONUtilsTest, GetStrings_NestedArray) {
182182
ASSERT_EQ(result.size(), 1UL);
183183
EXPECT_EQ(result[0], "string");
184184
}
185+
186+
TEST(JSONUtilsTest, DecodeMemoryReference) {
187+
EXPECT_EQ(DecodeMemoryReference(""), std::nullopt);
188+
EXPECT_EQ(DecodeMemoryReference("123"), std::nullopt);
189+
EXPECT_EQ(DecodeMemoryReference("0o123"), std::nullopt);
190+
EXPECT_EQ(DecodeMemoryReference("0b1010101"), std::nullopt);
191+
EXPECT_EQ(DecodeMemoryReference("0x123"), 291u);
192+
193+
{
194+
addr_t addr = LLDB_INVALID_ADDRESS;
195+
json::Path::Root root;
196+
EXPECT_TRUE(DecodeMemoryReference(json::Object{{"mem_ref", "0x123"}},
197+
"mem_ref", addr, root,
198+
/*required=*/true));
199+
EXPECT_EQ(addr, 291u);
200+
}
201+
202+
{
203+
addr_t addr = LLDB_INVALID_ADDRESS;
204+
json::Path::Root root;
205+
EXPECT_TRUE(DecodeMemoryReference(json::Object{}, "mem_ref", addr, root,
206+
/*required=*/false));
207+
}
208+
209+
{
210+
addr_t addr = LLDB_INVALID_ADDRESS;
211+
json::Path::Root root;
212+
EXPECT_FALSE(DecodeMemoryReference(json::Object{}, "mem_ref", addr, root,
213+
/*required=*/true));
214+
EXPECT_THAT_ERROR(root.getError(),
215+
FailedWithMessage("missing value at (root).mem_ref"));
216+
}
217+
218+
{
219+
addr_t addr = LLDB_INVALID_ADDRESS;
220+
json::Path::Root root;
221+
EXPECT_FALSE(DecodeMemoryReference(json::Object{{"mem_ref", 123}},
222+
"mem_ref", addr, root,
223+
/*required=*/true));
224+
EXPECT_THAT_ERROR(root.getError(),
225+
FailedWithMessage("expected string at (root).mem_ref"));
226+
}
227+
228+
{
229+
addr_t addr = LLDB_INVALID_ADDRESS;
230+
json::Path::Root root;
231+
EXPECT_FALSE(DecodeMemoryReference(json::Object{{"mem_ref", "123"}},
232+
"mem_ref", addr, root,
233+
/*required=*/true));
234+
EXPECT_THAT_ERROR(
235+
root.getError(),
236+
FailedWithMessage("malformed memory reference at (root).mem_ref"));
237+
}
238+
}

lldb/unittests/DAP/ProtocolTypesTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ TEST(ProtocolTypesTest, Variable) {
919919
var.evaluateName = "my_name";
920920
var.namedVariables = 7;
921921
var.indexedVariables = 7;
922-
var.memoryReference = "0x123";
922+
var.memoryReference = 291u;
923923
var.declarationLocationReference = 24;
924924
var.valueLocationReference = 100;
925925

0 commit comments

Comments
 (0)