Skip to content

Debugger (gdb): ghidragdb misplaces MIPS $8-$15 register values under the n32/n64 ABI (name mismatch with O32 SLEIGH) #9412

Description

@retrocpugeek

Describe the bug

ghidragdb maps target registers to Ghidra registers by name (Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/arch.py, DefaultRegisterMapper.map_name). Ghidra's MIPS SLEIGH always names general registers $8$15 with the O32 convention (t0t7). gdb, however, renames that band per the selected ABI: under n32/n64 the registers are a4a7 ($8$11) and t0t3 ($12$15).

So under an n-ABI, gdb's t3 is $15 while Ghidra's t3 is $11. With no translation, every value in $8$15 is stored under the wrong Ghidra register:

  • a value in $11 (gdb a7) is stored under Ghidra's t3,
  • gdb's t3 ($15) is stored under Ghidra's t7.

Register hovers, the Decompiler's variable values, and register writes are all wrong for that band. For example, a loop counter the decompiler placed in $11 reads back the unrelated $15 (which often looks like a pointer). o32/o64 are unaffected — gdb already uses t0t7 there, matching Ghidra.

To Reproduce

  1. Connect Ghidra's Debugger (gdb) to a big-endian MIPS64 target using the n64 ABI ((gdb) show mips abi reports n64).
  2. Stop in a function that uses the $8$15 band, e.g. a loop counter in $11.
  3. Hover the corresponding Decompiler variable (or inspect the register): the value shown is from the wrong physical register ($15 instead of $11).

Concretely, at an addiu a7,a7,1 loop increment, gdb shows $a7=$11 going 0 -> 1 while $t3=$15 holds a stable pointer; Ghidra displays the pointer for the counter variable and vice-versa.

Expected behavior

Under n32/n64, ghidragdb should translate the $8$15 band so values land in the Ghidra register the SLEIGH language expects, in both directions:

  • gdb a4a7 ($8$11) -> Ghidra t0t3
  • gdb t0t3 ($12$15) -> Ghidra t4t7

Environment

  • Ghidra 12.1.2
  • gdb-multiarch 17.1; big-endian MIPS64 (n64) target

Note

Forcing gdb to the o32/o64 ABI to realign the names is not a viable workaround: it changes gdb's address handling and breaks breakpoints on 64-bit targets. The reconciliation has to happen in ghidragdb.

Suggested fix

Add a MIPS RegisterMapper in ghidragdb/arch.py (paralleling Intel_x86_64_RegisterMapper) that detects the n-ABI at runtime and remaps the $8$15 band, registered for the 64-bit MIPS languages. It is a no-op under o32/o64. Pull request to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions