Repository navigation
Support MIPSN32 in the lifter - #576
Conversation
lifters are registered by architecture name, so an architecture whose name libvex.py does not list gets no lifter at all and every block comes back Ijk_NoDecode. MIPSN32 -- the n32 and O64 ABIs, a 64-bit MIPS instruction stream in an ELFCLASS32 container -- needs the same LibVEXLifter as MIPS64, which it then dispatches through its own vex_arch of VexArchMIPS64. PyvexArch gains the matching entry so the standalone arch objects cover it too, which is what lets this be tested without archinfo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/pyvex_576 |
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
Reproducer, no fixture and no angr needed. The three words are the start of a non-leaf n32 prologue — import pyvex
data = bytes.fromhex("27bdffe0" "ffbc0008" "3c1c0002")
kw = {"data": data, "mem_addr": 0x10000110, "num_inst": 3, "opt_level": 0}
sorted(set(pyvex.IRSB(arch=pyvex.ARCH_MIPS32_BE, **kw).tyenv.types)) # ['Ity_I32']
sorted(set(pyvex.IRSB(arch=pyvex.ARCH_MIPSN32_BE, **kw).tyenv.types)) # ['Ity_I32', 'Ity_I64']The 32-bit guest decodes the Caveats: this is a focused pyvex record, not the cross-repository workspace gate — no angr, cle or archinfo suite was run against it. Merge order, and what an incomplete chain doesThe four pull requests in this chain are Merging the loader and the architecture definition ahead of the lifter is the dangerous Measured 2026-08-28, at the heads under review, one process per object:
Population: 16 ELF objects, every one Over the fourteen MIPS III objects, of 261,039 line addresses:
Method notes: each arm asserts the resolved Objects, Public reproducer for the ordering, on the fixtures in
|
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Full lifted IR for Before — pyvex master (bdd5441, the merge base)After — n32 lifts 11 instructions over 44 bytes, statement for statement identical to the with this change (2bf2cff) |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
MIPS n32 lifts nothing.
mainat0x10000110in the chain's n32 fixturen32_be_staticis 18 instructions of ordinary MIPS64 code, and every block of it comes back undecodable:The same bytes with
ArchMIPS64givesize=44 instructions=11 jumpkind=Ijk_Call. Nothing is recovered for an n32 or O64 object: no blocks, so no functions, no calls and no data references.Root cause
LibVEXLifteris selected by architecture name, not byvex_arch, andMIPSN32is not inLIBVEX_SUPPORTED_ARCHESinpyvex/lifting/libvex.py. The name misses, no libVEX lifter is registered for the architecture, and the block falls through toIjk_NoDecodewith size 0 even thougharch.vex_archalready readsVexArchMIPS64.Falling back to
MIPS32is not a repair. It lifts the same 44 bytes, butsd $gp, 8($sp)— the 64-bit spill in a non-leaf n32 prologue, at0x10000114— silently becomes a 4-byte store:Ity_I64appears nowhere in theMIPS32type environment, so the 32-bit guest reports a block that decodes cleanly and stores the wrong width.Fix
Add
MIPSN32toLIBVEX_SUPPORTED_ARCHESand to thePyvexArchguest and instruction-pointer tables, mapped toVexArchMIPS64, and exportARCH_MIPSN32_BE/ARCH_MIPSN32_LE. n32 and O64 differ from MIPS64 in pointer width, not in the instruction set, so the correct guest is the one that already exists; no new VEX guest is added andlibpyvex.sois byte-identical either side of this change (sha2569e5b9532fde21223…on both, in the before/after capture). The architecture's word size stays 32 whilevex_archisVexArchMIPS64, which is the whole of what n32 means here. After:statement for statement identical to the
ArchMIPS64lift of the same bytes.Testing
tests/test_mipsn32.pylifts that prologue and pins that n32 decodes exactly asARCH_MIPS64_BEdoes — same statement list — thatIty_I64is present for n32 and absent forARCH_MIPS32_BE, and thatARCH_MIPSN32_BE.bitsis 32 while itsvex_archequals the 64-bit architecture's. On the merge base it is 1 failed,AttributeError: module 'pyvex' has no attribute 'ARCH_MIPSN32_BE'; at this head, 1 passed.These four must land together: with the loader and the architecture definition ahead of the lifter,
MIPSN32resolves and reaches a lifter with no entry for it, and recovery on the affected objects drops to zero blocks. Merge order: archinfo 375, then pyvex 576, then cle 795, then angr 6982.Validation: #576 (comment)
sync: angr/archinfo#375
session: mega-corpus