Skip to content

Commit 5149cef

Browse files
puremourningvadimcn
authored andcommitted
Evaluate request: return memory reference
This implements 2 things: First, we now return memoory references for all members of an evaluate request's response. This allows for dumping of memory around the results of mundane evaluation, such as variables, structs, etc. Further, any evaluation result which is itself a pointer value gets the contained address as its memory address (as opposed to the load address of the pointer itslef). This in particular allows for dumping of arbitrary memory addresses by simply casting them to (void*) or some equivalent pointer type. This is consistent with other debug adapters.
1 parent 505430f commit 5149cef

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

adapter/codelldb/src/debug_session/variables.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -224,25 +224,7 @@ impl super::DebugSession {
224224
})
225225
};
226226

227-
let mem_ref = match self.client_caps.supports_memory_references {
228-
Some(true) => {
229-
match var.value_type() {
230-
// Assume that the register value is an address, and use that.
231-
// So users can dump memory, e.g. as the SP, RIP+offset, etc.
232-
ValueType::Register => Some(format!("0x{:X}", var.value_as_unsigned(0))),
233-
// TODO: if it's a literal and looks like an address (e.g. some
234-
// sort of integer, use that as the addres)
235-
_ => {
236-
let load_addr = var.load_address();
237-
match load_addr {
238-
lldb::INVALID_ADDRESS => None,
239-
_ => Some(format!("0x{:X}", load_addr)),
240-
}
241-
}
242-
}
243-
}
244-
_ => None,
245-
};
227+
let mem_ref = self.get_mem_ref_for_var(var);
246228

247229
let is_settable = match var.type_().basic_type() {
248230
BasicType::Char
@@ -399,6 +381,34 @@ impl super::DebugSession {
399381
summary
400382
}
401383

384+
// Retrieve the memory reference for a given variable.
385+
fn get_mem_ref_for_var(&self, var: &SBValue) -> Option<String> {
386+
match self.client_caps.supports_memory_references {
387+
Some(true) => {
388+
match var.value_type() {
389+
// If the value is stored in a register, assume it is an address and use it directly.
390+
// This allows users to dump memory by referencing registers like SP or RIP+offset.
391+
ValueType::Register => Some(format!("0x{:X}", var.value_as_unsigned(0))),
392+
_ => {
393+
if var.type_().is_pointer_type() {
394+
// If the value is a pointer type, treat it as a memory address.
395+
// This allows users to dump arbitrary memory addresses, e.g., by using (void*)0x1234.
396+
Some(format!("0x{:X}", var.value_as_unsigned(0)))
397+
} else {
398+
let load_addr = var.load_address();
399+
match load_addr {
400+
lldb::INVALID_ADDRESS => None,
401+
// If the variable has a valid load address, use it as the memory reference.
402+
_ => Some(format!("0x{:X}", load_addr)),
403+
}
404+
}
405+
}
406+
}
407+
}
408+
_ => None,
409+
}
410+
}
411+
402412
pub fn handle_evaluate(&mut self, args: EvaluateArguments) -> Result<ResponseBody, Error> {
403413
let frame = match args.frame_id {
404414
Some(frame_id) => {
@@ -499,6 +509,7 @@ impl super::DebugSession {
499509
result: self.get_var_summary(&sbval, handle.is_some()),
500510
type_: sbval.display_type_name().map(|s| s.to_owned()),
501511
variables_reference: handles::to_i64(handle),
512+
memory_reference: self.get_mem_ref_for_var(&sbval),
502513
..Default::default()
503514
})
504515
}

0 commit comments

Comments
 (0)