NationalSecurityAgency/ghidra · error · RuntimeError
Expression {expression} does not have an address
Error message
Expression {expression} does not have an address What it means
Thrown by ghidra_trace_putval when the evaluated value's SBValue.addr is not valid. putval only makes sense for values that live in memory (their bytes can be copied into the trace); pure registers and compile-time constants have no address, so the command refuses them.
Source
Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py:775
args = shlex.split(command)
if len(args) == 1:
expression = args[0]
pages = True
elif len(args) == 2:
expression = args[0]
pages = (util.get_eval(args[2]).unsigned != 0)
else:
raise RuntimeError("Usage: ghidra trace putval EXPRESSION [PAGES]")
STATE.require_tx()
try:
value = util.get_eval(expression)
address = value.addr
except BaseException as e:
raise RuntimeError(f"Could not evaluate {expression}: {e}")
if not address.IsValid():
raise RuntimeError(f"Expression {expression} does not have an address")
start = int(address)
end = start + start + value.size
return put_bytes(start, end, result, pages)
def putmem_state(address: str, length: str, state: str,
pages: bool = True) -> None:
trace = STATE.require_trace()
trace.validate_state(state)
start, end = eval_range(address, length)
if start is None or end is None:
return
if pages:
start, end = quantize_pages(start, end)
proc = util.get_process()
base, addr = trace.extra.require_mm().map(proc, start)
if base != addr.space:
trace.create_overlay_space(base, addr.space)View on GitHub (pinned to d5f144c24d)
Solutions
- Use a memory-resident expression: a global variable, a dereferenced pointer, or a stack object.
- To record registers, use 'ghidra trace putreg' instead of putval.
- Take the address explicitly if you meant the storage: 'putval &myvar'.
Example fix
// before ghidra trace putval 0xdeadbeef // after ghidra trace putval global_buffer
Defensive patterns
Strategy: type-guard
Validate before calling
from ghidralldb import util
def has_memory_address(expr: str) -> bool:
try:
return util.get_eval(expr).addr.IsValid()
except BaseException:
return False Type guard
def is_memory_resident(value: 'lldb.SBValue') -> bool:
return bool(value.addr.IsValid()) Try / catch
value = util.get_eval(expression)
if not value.addr.IsValid():
# fall back to recording via putreg if it is a register
ghidra_trace_putreg(debugger, '<group>', result, internal_dict) Prevention
- Use putval only for memory-resident values (globals, dereferenced pointers, stack objects).
- Use putreg for registers, not putval.
- Take the address explicitly (&var) when you mean the storage.
When it happens
Trigger: Passing an immediate/constant expression (e.g. 'putval 42'), a register-only value, or an rvalue whose address LLDB cannot materialize. value.addr.IsValid() returns false for these.
Common situations: User treats putval as 'record any value' rather than 'record a memory-resident value'; trying to record a register (use putreg instead); passing a literal number.
Related errors
- Cannot convert '{length}' to length: {e}
- Could not evaluate {expression}: {e}
- Usage: ghidra trace putmem ADDRESS LENGTH [PAGES]
- Usage: ghidra trace putval EXPRESSION [PAGES]
- Usage: ghidra trace putmem ADDRESS LENGTH STATE [PAGES]
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/0dde18ac01d39143.
Report an issue: GitHub.