{"record":{"id":"9dc31e7f344cce70","repo":"NationalSecurityAgency/ghidra","slug":"cannot-read-memory-at-start-x","errorCode":null,"errorMessage":"Cannot read memory at {start:x}","messagePattern":"Cannot read memory at (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py","lineNumber":675,"sourceCode":"\n    if error.Success() and buf is not None:\n        base, addr = trace.extra.require_mm().map(proc, start)\n        if base != addr.space:\n            trace.create_overlay_space(base, addr.space)\n        count = trace.put_bytes(addr, buf)\n        if result is None:\n            pass\n        elif isinstance(count, Future):\n            if count.done():\n                result.PutCString(f\"Wrote {count.result()} bytes\")\n            else:\n                count.add_done_callback(lambda c: check_count(c.result(), len(buf)))\n                result.PutCString(\n                    f\"Wrong {len(buf)} bytes, perhaps in the future\")\n        else:\n            result.PutCString(f\"Wrote {count} bytes\")\n    else:\n        raise RuntimeError(f\"Cannot read memory at {start:x}\")\n\n\ndef eval_address(address: str) -> Optional[int]:\n    try:\n        return util.parse_and_eval(address)\n    except BaseException as e:\n        if \"can't evaluate expressions when the process is running\" not in str(e):\n            raise RuntimeError(f\"Cannot convert '{address}' to address: {e}\")\n        return None\n\n\ndef eval_range(address: str, length: str) -> Tuple[Optional[int], Optional[int]]:\n    start = eval_address(address)\n    if start is None:\n        return None, None\n    try:\n        end = start + util.parse_and_eval(length)\n    except BaseException as e:","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py#L657-L693","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Verify the address is mapped and readable in LLDB first: `memory read --size 1 --count 16 0x<addr>`","Ensure the process is stopped (not running) before putting memory","Re-derive the address from a current symbol or expression instead of a hardcoded value","If page quantization is on, confirm the whole page is readable and not a guard/no-access page"],"exampleFix":"// before\nghidra trace putmem 0xdeadbeef 0x10\n// after\n(lldb) memory read --size 1 --count 16 0x1000   # confirm readable\nghidra trace putmem 0x1000 0x10","handlingStrategy":"validation","validationCode":"import lldb\n\ndef memory_readable(start: int, size: int) -> bool:\n    proc = lldb.debugger.GetTargetAtIndex(0).process\n    if proc is None or not proc.IsValid():\n        return False\n    err = lldb.SBError()\n    buf = proc.ReadMemory(start, size, err)\n    return err.Success() and buf is not None","typeGuard":"import lldb\n\ndef is_readable_region(start: int, size: int) -> bool:\n    proc = lldb.debugger.GetTargetAtIndex(0).process\n    if proc is None:\n        return False\n    info = lldb.SBMemoryRegionInfo()\n    if proc.GetMemoryRegionInfo(start, info).Success():\n        return info.IsReadable()\n    return False","tryCatchPattern":"try:\n    put_bytes(start, end, result, pages)\nexcept RuntimeError as e:\n    if str(e).startswith('Cannot read memory at '):\n        # the address is unmapped/unreadable or the process is not stopped;\n        # re-derive start from a live symbol or skip this range\n        ...\n    raise","preventionTips":["Verify readability with `memory read` before putting memory","Ensure the process is stopped, not running","Derive addresses from current symbols rather than hardcoded values to survive ASLR","Watch for guard/no-access pages when page quantization is enabled"],"tags":["memory","ghidra","lldb","debugging","put"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}