NationalSecurityAgency/ghidra · error · RuntimeError
No register mapper
Error message
No register mapper
What it means
Raised by Extra.require_rm in the Ghidra LLDB agent when register_mapper has not been set on the trace's Extra object. The register mapper translates register names and byte values between Ghidra and LLDB; without it, register read/write trace operations cannot proceed. RuntimeError signals a missing precondition — the mapper must be constructed (DefaultRegisterMapper with valid byte_order) and assigned before any register operation.
Source
Thrown at Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py:87
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 RuntimeError("Not connected")
return self.client
def require_no_client(self) -> None:
if self.client is not None:
raise RuntimeError("Already connected")
def reset_client(self) -> None:View on GitHub (pinned to d5f144c24d)
Solutions
- Ensure the activate/environment step assigns trace.extra.register_mapper (with a validated byte_order) before any register method runs.
- Lazily initialize register_mapper in require_rm using the detected endianness.
- Order commands so register operations occur only after target launch and arch/endianness detection.
- Verify byte_order normalization (see error 191) so mapper construction does not silently fail.
Example fix
// before
rv = frame.trace.extra.require_rm().map_value_back(proc, name, value)
// after
extra = frame.trace.extra
if extra.register_mapper is None:
extra.register_mapper = arch.DefaultRegisterMapper(normalized_byte_order)
rv = extra.require_rm().map_value_back(proc, name, value) Defensive patterns
Strategy: validation
Validate before calling
extra = trace.extra
if extra.register_mapper is None:
extra.register_mapper = arch.DefaultRegisterMapper(normalized_byte_order)
rv = extra.require_rm().map_value_back(proc, name, value) Type guard
def register_mapper_ready(extra) -> bool:
return extra.register_mapper is not None Try / catch
try:
rm = trace.extra.require_rm()
except RuntimeError:
trace.extra.register_mapper = arch.DefaultRegisterMapper(detected_endianness())
rm = trace.extra.require_rm() Prevention
- ensure activate sets register_mapper with validated byte_order
- lazily initialize register_mapper in require_rm
- verify endianness detection does not return an invalid value
When it happens
Trigger: Calling trace.extra.require_rm() before the agent initialized register_mapper — e.g. a register method fired during startup before the register mapper was assigned, or arch/endianness detection failed and the assignment was skipped. Reached by methods that read/translate register values.
Common situations: Trace-activate step that sets register_mapper did not complete (target not launched, arch detection failed); endianness detection returned an invalid value causing mapper construction to be skipped; ordering bug where a register method runs before activate.
Related errors
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/cab3dbda9bdab6b6.
Report an issue: GitHub.