NationalSecurityAgency/ghidra · error · RuntimeError

Cannot read memory at {start:x}

Error message

Cannot read memory at {start:x}

What it means

Raised inside `put_bytes` (used by putmem, putmem-state, and the put-* hooks) when `proc.ReadMemory(start, size, error)` returns a non-success error or a null buffer. The offending start address is reported in hex. It usually means the address is unmapped or unreadable, or the process is not stopped at a state where that region is accessible.

Source

Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py:675

    if error.Success() and buf is not None:
        base, addr = trace.extra.require_mm().map(proc, start)
        if base != addr.space:
            trace.create_overlay_space(base, addr.space)
        count = trace.put_bytes(addr, buf)
        if result is None:
            pass
        elif isinstance(count, Future):
            if count.done():
                result.PutCString(f"Wrote {count.result()} bytes")
            else:
                count.add_done_callback(lambda c: check_count(c.result(), len(buf)))
                result.PutCString(
                    f"Wrong {len(buf)} bytes, perhaps in the future")
        else:
            result.PutCString(f"Wrote {count} bytes")
    else:
        raise RuntimeError(f"Cannot read memory at {start:x}")


def eval_address(address: str) -> Optional[int]:
    try:
        return util.parse_and_eval(address)
    except BaseException as e:
        if "can't evaluate expressions when the process is running" not in str(e):
            raise RuntimeError(f"Cannot convert '{address}' to address: {e}")
        return None


def eval_range(address: str, length: str) -> Tuple[Optional[int], Optional[int]]:
    start = eval_address(address)
    if start is None:
        return None, None
    try:
        end = start + util.parse_and_eval(length)
    except BaseException as e:

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Verify the address is mapped and readable in LLDB first: `memory read --size 1 --count 16 0x<addr>`
  2. Ensure the process is stopped (not running) before putting memory
  3. Re-derive the address from a current symbol or expression instead of a hardcoded value
  4. If page quantization is on, confirm the whole page is readable and not a guard/no-access page

Example fix

// before
ghidra trace putmem 0xdeadbeef 0x10
// after
(lldb) memory read --size 1 --count 16 0x1000   # confirm readable
ghidra trace putmem 0x1000 0x10
Defensive patterns

Strategy: validation

Validate before calling

import lldb

def memory_readable(start: int, size: int) -> bool:
    proc = lldb.debugger.GetTargetAtIndex(0).process
    if proc is None or not proc.IsValid():
        return False
    err = lldb.SBError()
    buf = proc.ReadMemory(start, size, err)
    return err.Success() and buf is not None

Type guard

import lldb

def is_readable_region(start: int, size: int) -> bool:
    proc = lldb.debugger.GetTargetAtIndex(0).process
    if proc is None:
        return False
    info = lldb.SBMemoryRegionInfo()
    if proc.GetMemoryRegionInfo(start, info).Success():
        return info.IsReadable()
    return False

Try / catch

try:
    put_bytes(start, end, result, pages)
except RuntimeError as e:
    if str(e).startswith('Cannot read memory at '):
        # the address is unmapped/unreadable or the process is not stopped;
        # re-derive start from a live symbol or skip this range
        ...
    raise

Prevention

When it happens

Trigger: `ghidra trace putmem 0xdeadbeef 0x10` on an unmapped address; reading a guard or no-access page; the process is running so the region is unavailable; an address expression that resolved to a now-stale location after ASLR/relocation.

Common situations: Putting memory before the process is loaded or stopped; a hardcoded address from a previous run that no longer maps; ASLR moved the image; reading a protected page.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/9dc31e7f344cce70. Report an issue: GitHub.