NationalSecurityAgency/ghidra · error · RuntimeError

No register mapper

Error message

No register mapper

What it means

Raised as RuntimeError by Extra.require_rm() when STATE.trace.extra.register_mapper is None. The register mapper is assigned in start_trace(); register operations invoked before that (or on an unwired extra) fail here.

Source

Thrown at Ghidra/Debug/Debugger-agent-drgn/src/main/py/src/ghidradrgn/commands.py:94

        self.code = code

    def __str__(self) -> str:
        return repr(self.code)


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 RuntimeError("Not connected")
        return self.client

    def require_no_client(self) -> None:
        if self.client != None:
            raise RuntimeError("Already connected")

    def reset_client(self) -> None:

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Confirm ghidra_trace_start() completed and set extra.register_mapper.
  2. Guard: if trace.extra.register_mapper is None: report 'start trace first'.
  3. Validate compute_register_mapper() returns a mapper for the detected language.

Example fix

// before
rm = trace.extra.require_rm()  # RuntimeError
// after
if trace.extra.register_mapper is None:
    raise RuntimeError("call ghidra_trace_start before register ops")
rm = trace.extra.require_rm()
Defensive patterns

Strategy: validation

Validate before calling

trace = STATE.require_trace()
if trace.extra.register_mapper is None:
    raise RuntimeError('call ghidra_trace_start before register operations')
rm = trace.extra.require_rm()

Type guard

def has_register_mapper(trace) -> bool:
    return getattr(getattr(trace, 'extra', None), 'register_mapper', None) is not None

Try / catch

try:
    rm = trace.extra.require_rm()
except RuntimeError as e:
    if 'No register mapper' in str(e):
        ghidra_trace_start(); rm = trace.extra.require_rm()
    else:
        raise

Prevention

When it happens

Trigger: Issuing a register read/write before ghidra_trace_start(); a Trace[Extra] whose register_mapper was never populated.

Common situations: Register op dispatched before trace start; arch.compute_register_mapper() returned None-equivalent; start_trace() failed after memory_mapper was set.

Related errors


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