[Bug] MIPS N32 ABI has 32-bit registers
GEF+GDB version
GEF: (Standalone)
Blob Hash(/home/justin/.gef-2026.01.py): b87f503eb86896f7ae452e886619cc6d7adbd594
SHA256(/home/justin/.gef-2026.01.py): c2afbb821ce8e1b4909a70b2aff33eb526f114e0cfb3340fb9b7dbf8b1da3f1c
GDB: 17.1
GDB-Python: 3.13Operating System
Kali Linux WSL
Describe the issue you encountered
MIPS64 has two main ABIs used - N32 and N64. Both have 64-bit registers, but N32 has a 32-bit address space. When using gef-remote with the proper QEMU options, the N64 ABI is treated correctly, and it's detected as MIPS64. However, binaries with the N32 ABI is detected as MIPS32, and thus 32-bit registers are incorrectly used.
Do you read the docs and look at previously closed issues/PRs for similar cases?
Yes
Architecture impacted
- X86
- X64
- ARM
- ARM64
- MIPS
- MIPS64
- PPC
- PPC64
- RISCV
Describe your issue. Without a proper reproduction step-by-step, your issue will be ignored.
(qemu) gef➤ show architecture
The target architecture is set to "auto" (currently "mips:isa64r2").
(qemu) gef➤ set $s0 = 0x1122334455667788
(qemu) gef➤ i r $s0
s0: 0x1122334455667788
(qemu) gef➤ context
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────── registers ────
$zero: 0x0
$at : 0x0
$v0 : 0x0
$v1 : 0x0
$a0 : 0x0
$a1 : 0x0
$a2 : 0x0
$a3 : 0x0
$t0 : 0x0
$t1 : 0x0
$t2 : 0x0
$t3 : 0x0
$s0 : 0x55667788 # only last 4 bytes are shown
$s1 : 0x0
$s2 : 0x0
$s3 : 0x0
$s4 : 0x0
$s5 : 0x0
$s6 : 0x0
$s7 : 0x0
$t8 : 0x0
$t9 : 0x0
$k0 : 0x0
$k1 : 0x0
$s8 : 0x0
$pc : 0x013abd10 → <__start+0000> move t9, ra
$sp : 0x0138aea0 → 0x00000001
$hi : 0x0
$lo : 0x0
$fir : 0x7f0000
$ra : 0x0
$gp : 0x0
───────────────────────────────────────────────────────────────────────────────── stack ────
[!] Command 'dereference' failed to execute properly, reason: Bad register
────────────────────────────────────────────────────────────────────── code:mips:MIPS32 ────
0x13abd04 nop
0x13abd08 nop
0x13abd0c nop
→ 0x13abd10 <__start+0000> move t9, ra
0x13abd14 <__start+0004> bal 0x13abd1c <__start+12>
0x13abd18 <__start+0008> nop
0x13abd1c <__start+000c> move s2, gp
0x13abd20 <__start+0010> lui gp, 0x3
0x13abd24 <__start+0014> addiu gp, gp, -15612
─────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, stopped 0x13abd10 in __start (), reason: SIGTRAP
───────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x13abd10 → __start()
────────────────────────────────────────────────────────────────────────────────────────────The register output only displays the least significant 32 bits of each register (s0 should be 0x1122334455667788, which i r correctly displays). I'm not sure if the stack dereferencing failing is related to it or not, but I'm pretty sure GEF treats it as MIPS32 due to the code:mips:MIPS32 title.
I'm fairly sure this is a bug in GEF, as following the same steps for a MIPS64 N64 binary correctly shows the 64-bit register
Minimalist test case
My preferred method of compiling, hosting, and connecting to these MIPS binaries with QEMU is through some containers I've posted on DockerHub (mips-compile and mips-pwn). For example, use the following C code (poc.c):
int main(){ return 0; }Compile it with the commands (uses MIPS64, big endian, Release 2, with both ABIs):
# for the n32 ABI
docker run -it --rm -v ${PWD}:/workdir legoclones/mips-compile:mips64r2-glibc-n32 mips64-linux-gcc poc.c -o poc_n32
# for the n64 ABI
docker run -it --rm -v ${PWD}:/workdir legoclones/mips-compile:mips64r2-glibc-n64 mips64-linux-gcc poc.c -o poc_n64To emulate it with QEMU and expose the user mode GDB stub:
# n32 ABI
docker run -i --rm -v ./:/target/ctf -p 1234:1234 --name poc_n32 legoclones/mips-pwn:mips64r2-glibc-n32 chroot /target /qemu -g 1234 /ctf/poc_n32
# n64 ABI
docker run -i --rm -v ./:/target/ctf -p 1234:1234 --name poc_n64 legoclones/mips-pwn:mips64r2-glibc-n64 chroot /target /qemu -g 1234 /ctf/poc_n64To connect to the GDB stub in another terminal:
# n32 ABI
gdb -q ./poc_n32 -ex "gef-remote localhost 1234 --qemu-user --qemu-binary ./poc_n32"
# n64 ABI
gdb -q ./poc_n64 -ex "gef-remote localhost 1234 --qemu-user --qemu-binary ./poc_n64"I've also attached the compiled binaries if you'd like: gef_poc.zip
Additional context?
No response
Source: hugsy/gef