riscv64: widen feq/flt results before assigning them to an Ity_I32 temp - #95
riscv64: widen feq/flt results before assigning them to an Ity_I32 temp#95zardus wants to merge 1 commit into
Conversation
dis_RV64F and dis_RV64D allocate the result of feq.s/flt.s and feq.d/flt.d in an Ity_I32 temporary but assign the Ity_I1 output of Iop_CmpEQ32 to it directly, so the IR sanity checker rejects the block with IRStmt.Put.Tmp: tmp and expr do not match and libVEX panics. The fle arm of the same switch already wraps its comparisons in Iop_1Uto32; do the same for feq and flt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Full lift of the data = open("binaries/tests/riscv/autotalent-autotalent.so", "rb").read()[0x2390:0x2394]
irsb = pyvex.lift(data, 0x402390, pyvex.ARCH_RISCV64_LE)
print("size=%d jumpkind=%s statements=%d" % (irsb.size, irsb.jumpkind, len(irsb.statements)))
irsb.pp()Before — libVEX panics on its own sanity check and pyvex hands back a vex 875f7c9After — the comparison is widened at vex c2409bb |
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
Instruction census over every RISC-V object in
Every one of the 50 is a Caveats: the complete workspace gate did not run — this machine's shared toolchain is pinned by other work, and entering the devshell would reinstall its editables. What ran is pyvex's own suite against both vex revisions, the build, and the census. valgrind's own regression suite was not run; this repository carries no test harness for it. |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
feq.s,flt.s,feq.dandflt.demit IR that libVEX's own sanity checkerrejects, so every block containing one panics instead of lifting. Lifting the
four bytes
d3a5d8a1—feq.s a1, fa7, ft9, at0x402390inbinaries/tests/riscv/autotalent-autotalent.so— gives:Consumers never see that message. pyvex converts the panic into a fabricated
zero-length
Ijk_NoDecodeblock, so the bytes are reported as undecodable andthe enclosing function is cut short at the comparison. Over the six RISC-V
objects committed to
angr/binariesthis silently loses 50 instructions,25 of them in
autotalent-autotalent.soalone.Root cause
dis_RV64Fanddis_RV64Dboth hold the comparison result inIRTemp res = newTemp(irsb, Ity_I32)and then assign theIty_I1output ofIop_CmpEQ32straight into it:The
flearm two cases below is already correct — it wraps both comparisons inunop(Iop_1Uto32, ...)before combining them withIop_Or32— which is whyfle.sandfle.dlift whilefeqandfltdo not.This is a regression from 7576d04 ("riscv: fix instructions that use the
unsupported Ity_1 data type"), which widened
restoIty_I32and convertedonly the
flearm.Fix
Wrap the
feqandfltarms inunop(Iop_1Uto32, ...), matching the form theflearm already uses. Four hunks, two indis_RV64Fand two indis_RV64D,in
priv/guest_riscv64_toIR.c.feq.s a1, fa7, ft9then lifts to a normalfour-byte
Ijk_Boringblock of 13 statements.Nothing else changes: the
flearms are untouched, and therd == 0path neverreached the bad assignment.
Testing
angr/vexhas no test suite of its own, so the regression lives in the pairedpyvex pull request, which pins this commit and asserts that every
feq/fltencoding in a committed gcc-built RISC-V object lifts to a real block. It fails
against vex master with
pyvex failed to decode 25 float comparisonsand passeshere. A capstone linear disassembly of
.textre-lifted instruction byinstruction puts the six RISC-V fixtures in
angr/binariesat 50 unliftableinstructions before this change and 0 after.
Validation: #95 (comment)
sync: angr/pyvex#578
session: sharpen