NationalSecurityAgency/ghidra · error · RuntimeError

No memory mapper

Error message

No memory mapper

What it means

Thrown as a RuntimeError by Extra.require_mm() in the gdb agent when the memory_mapper attribute has not been set (is None). The Extra object is created during start_trace and its memory_mapper is assigned from arch.compute_memory_mapper(language); if start_trace was not called or failed before the assignment, this fires.

Source

Thrown at Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py:80

MEMORY_PATTERN = INFERIOR_PATTERN + '.Memory'
REGION_KEY_PATTERN = '[{start:08x}]'
REGION_PATTERN = MEMORY_PATTERN + REGION_KEY_PATTERN
MODULES_PATTERN = INFERIOR_PATTERN + '.Modules'
MODULE_KEY_PATTERN = '[{modpath}]'
MODULE_PATTERN = MODULES_PATTERN + MODULE_KEY_PATTERN
SECTIONS_ADD_PATTERN = '.Sections'
SECTION_KEY_PATTERN = '[{secname}]'
SECTION_ADD_PATTERN = SECTIONS_ADD_PATTERN + SECTION_KEY_PATTERN


class Extra(object):
    def __init__(self) -> None:
        self.memory_mapper: Optional[arch.DefaultMemoryMapper] = None
        self.register_mapper: Optional[arch.DefaultRegisterMapper] = None

    def require_mm(self) -> arch.DefaultMemoryMapper:
        if self.memory_mapper is None:
            raise RuntimeError("No memory mapper")
        return self.memory_mapper

    def require_rm(self) -> arch.DefaultRegisterMapper:
        if self.register_mapper is None:
            raise RuntimeError("No register mapper")
        return self.register_mapper


class State(object):

    def __init__(self) -> None:
        self.reset_client()

    def require_client(self) -> Client:
        if self.client is None:
            raise gdb.GdbError("Not connected")
        return self.client

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Call ghidra_trace_start (or ensure start_trace completed successfully) before any memory-related command.
  2. Verify STATE.trace is not None and STATE.trace.extra.memory_mapper is set before calling require_mm().
  3. If the trace was disconnected, call ghidra_trace_start again to reinitialize.

Example fix

// before
ghidra_trace_connect('127.0.0.1:12345')
ghidra_trace_putmem('0x400000', 16)  # fails: no trace started
// after
ghidra_trace_connect('127.0.0.1:12345')
ghidra_trace_start('myprogram')
ghidra_trace_putmem('0x400000', 16)
Defensive patterns

Strategy: validation

Validate before calling

def ensure_memory_mapper() -> arch.DefaultMemoryMapper:
    if STATE.trace is None:
        raise RuntimeError('No active trace. Call ghidra_trace_start first.')
    mm = STATE.trace.extra.memory_mapper
    if mm is None:
        raise RuntimeError('Memory mapper not initialized. Trace may have failed to start.')
    return mm

Type guard

def has_memory_mapper() -> bool:
    return (
        STATE.trace is not None
        and STATE.trace.extra is not None
        and STATE.trace.extra.memory_mapper is not None
    )

Try / catch

try:
    STATE.trace.extra.require_mm()
except RuntimeError as e:
    if 'No memory mapper' in str(e):
        ghidra_trace_start()  # reinitialize trace
    raise

Prevention

When it happens

Trigger: Calling any command that needs memory translation (putmem, getmem, set-value with pointers) before ghidra_trace_start has been called, or after STATE.reset_client() cleared the trace. The require_mm() accessor checks for None and raises.

Common situations: Forgetting to call ghidra_trace_start before issuing memory commands; trace was started but create_trace failed, leaving memory_mapper unset; the Extra object was reused or reset incorrectly.

Related errors


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