[GH-ISSUE #7477] [Design] Admit RISC-V ilp32 and ilp32f ELF in the Ghidra lane with a per-ABI calling-convention policy #4457

Open
opened 2026-10-31 00:49:59 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @Entrpi on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7477

Before submitting

  • I searched the open and closed issues and pull requests for a related discussion.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This discussion does not include credentials, private samples, or sensitive target data.

Decision needed

Should the RISC-V Ghidra lane admit the ilp32 (soft-float) and ilp32f (single-float) ABIs by correcting the calling convention in the bridge? The alternatives are admitting them with a limitation and no correction, or continuing to refuse them.

Decided (31 Oct 2026, by the proposer): option 1. ilp32 ships first in #8229; ilp32f follows as its own PR. Maintainers can still redirect it in #8229's review.

Context and evidence

  • Observed: the lane admits only EF_RISCV_FLOAT_ABI_DOUBLE (src/ghidra/GhidraRiscvProfile.ts:68-72). Unit cases and the real verifier assert the refusal of e_flags 0x1 and 0x3 (GhidraRiscvProfile.test.ts:168-169, scripts/verify-real-ghidra-riscv.mjs:234-236).
  • Observed: Ghidra 12.1.4's generic RV32 language, RISCV:LE:32:default, uses riscv32-fp.cspec, which models ilp32d. The soft-float RV32 languages exist only in old/riscv_deprecated.ldefs, which REA's catalog does not read.
  • Source-derived: ESP-IDF builds ilp32 for ESP32-C2, C3, C5, C6, C61, H2 and H21 (rv32imc or rv32imac). It adds -mabi=ilp32f only for FPU chips such as P4, H4 and S31 (components/soc/project_include.cmake). Their ELFs are refused today.
  • Precedent: MIPS soft-float was handled by correcting the calling convention in the bridge (5e219de44, bridge/ghidra/ReaGhidraMipsSoftFloat.java).

Expected interaction with targets

Read existing files or captured data

Boundary details

Static analysis only. Quad-float, RVE and TSO stay refused. Images that declare Espressif custom extensions (xesploop, xespv, xespdsp) or Zcmp/Zcmt in .riscv.attributes would be limited or refused until their decoding is verified.

Options and tradeoffs

  1. Chosen: a written policy per ABI, applied in the bridge, ilp32 first. The policy covers integer and FP arguments, return values, aggregates, variadics and preserved registers. New lane ids per ABI, coordinated with #4811. Previously refused targets become admitted, and the double-float lane ids stay unchanged.
  2. Admit with a limitation and no correction. This is cheaper, but ABI-dependent results (arguments, returns, aggregates) become unverified, so it is a reduced-capability contract.
  3. Keep refusing.

Verification available so far

I have a prototype or observed results

Success criteria and open questions

  • Extend verify:ghidra:riscv with typed and stripped rv32imc/ilp32 and rv32imafc/ilp32f builds of one source. The source would cover float and double parameters and returns, small and large structs, and a variadic call.
  • Decompiled prototypes and argument storage must match the compiler-generated call sites.
  • Answered: ilp32 first (#8229), and ilp32f as a follow-up PR with its own fixtures.
  • Status: #8229's real Ghidra 12.1.4 runs meet the criteria above for ilp32; the rv32imafc/ilp32f builds come with the ilp32f PR.

References

#4811 (RISC-V PIE), docs/ghidra-riscv.md, and Ghidra 12.1.4 Ghidra/Processors/RISCV/data/languages/riscv32-fp.cspec.

Originally created by @Entrpi on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7477 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related discussion. - [x] I understand the contribution scope must be reviewed before integration; open questions are welcome here. - [x] This discussion does not include credentials, private samples, or sensitive target data. ### Decision needed Should the RISC-V Ghidra lane admit the ilp32 (soft-float) and ilp32f (single-float) ABIs by correcting the calling convention in the bridge? The alternatives are admitting them with a limitation and no correction, or continuing to refuse them. **Decided (31 Oct 2026, by the proposer): option 1.** ilp32 ships first in #8229; ilp32f follows as its own PR. Maintainers can still redirect it in #8229's review. ### Context and evidence - *Observed:* the lane admits only `EF_RISCV_FLOAT_ABI_DOUBLE` (`src/ghidra/GhidraRiscvProfile.ts:68-72`). Unit cases and the real verifier assert the refusal of `e_flags` `0x1` and `0x3` (`GhidraRiscvProfile.test.ts:168-169`, `scripts/verify-real-ghidra-riscv.mjs:234-236`). - *Observed:* Ghidra 12.1.4's generic RV32 language, `RISCV:LE:32:default`, uses `riscv32-fp.cspec`, which models ilp32d. The soft-float RV32 languages exist only in `old/riscv_deprecated.ldefs`, which REA's catalog does not read. - *Source-derived:* ESP-IDF builds ilp32 for ESP32-C2, C3, C5, C6, C61, H2 and H21 (`rv32imc` or `rv32imac`). It adds `-mabi=ilp32f` only for FPU chips such as P4, H4 and S31 (`components/soc/project_include.cmake`). Their ELFs are refused today. - *Precedent:* MIPS soft-float was handled by correcting the calling convention in the bridge (`5e219de44`, `bridge/ghidra/ReaGhidraMipsSoftFloat.java`). ### Expected interaction with targets Read existing files or captured data ### Boundary details Static analysis only. Quad-float, RVE and TSO stay refused. Images that declare Espressif custom extensions (`xesploop`, `xespv`, `xespdsp`) or Zcmp/Zcmt in `.riscv.attributes` would be limited or refused until their decoding is verified. ### Options and tradeoffs 1. *Chosen:* a written policy per ABI, applied in the bridge, ilp32 first. The policy covers integer and FP arguments, return values, aggregates, variadics and preserved registers. New lane ids per ABI, coordinated with #4811. Previously refused targets become admitted, and the double-float lane ids stay unchanged. 2. Admit with a limitation and no correction. This is cheaper, but ABI-dependent results (arguments, returns, aggregates) become unverified, so it is a reduced-capability contract. 3. Keep refusing. ### Verification available so far I have a prototype or observed results ### Success criteria and open questions - Extend `verify:ghidra:riscv` with typed and stripped `rv32imc`/ilp32 and `rv32imafc`/ilp32f builds of one source. The source would cover float and double parameters and returns, small and large structs, and a variadic call. - Decompiled prototypes and argument storage must match the compiler-generated call sites. - Answered: ilp32 first (#8229), and ilp32f as a follow-up PR with its own fixtures. - Status: #8229's real Ghidra 12.1.4 runs meet the criteria above for ilp32; the `rv32imafc`/ilp32f builds come with the ilp32f PR. ### References #4811 (RISC-V PIE), `docs/ghidra-riscv.md`, and Ghidra 12.1.4 `Ghidra/Processors/RISCV/data/languages/riscv32-fp.cspec`.
Author
Owner

@Entrpi commented on GitHub (Oct 28, 2026):

On the open question above, a proposed answer: ship ilp32 first, and ilp32f as a follow-up PR on top. ilp32 alone unblocks ESP32-C2, C3, C5, C6, C61, H2 and H21. ilp32f adds the single-float passing rules for P4, H4 and S31, about 2,000 more lines with their own verification, so each ABI's policy is reviewed against its own evidence. Both are implemented on my fork (ilp32, ilp32f on top) and will open in that order as PR slots free.

<!-- gh-comment-id:6483784691 --> @Entrpi commented on GitHub (Oct 28, 2026): On the open question above, a proposed answer: ship ilp32 first, and ilp32f as a follow-up PR on top. ilp32 alone unblocks ESP32-C2, C3, C5, C6, C61, H2 and H21. ilp32f adds the single-float passing rules for P4, H4 and S31, about 2,000 more lines with their own verification, so each ABI's policy is reviewed against its own evidence. Both are implemented on my fork ([ilp32](https://github.com/morluto/rea/compare/main...Entrpi:rea:feat-ghidra-riscv-ilp32), [ilp32f on top](https://github.com/Entrpi/rea/compare/feat-ghidra-riscv-ilp32...feat-ghidra-riscv-ilp32f)) and will open in that order as PR slots free.
Author
Owner

@Entrpi commented on GitHub (Oct 31, 2026):

Decision: option 1, a written calling-convention policy per ABI, applied in the bridge. ilp32 is open as #8229, verified against real Ghidra 12.1.4 with typed and stripped builds whose prototypes and argument storage match the compiler's call sites. ilp32f (ESP32-P4, H4, S31) follows as its own PR. I've updated the issue body to match; redirect in #8229's review if you disagree.

<!-- gh-comment-id:6536413948 --> @Entrpi commented on GitHub (Oct 31, 2026): Decision: option 1, a written calling-convention policy per ABI, applied in the bridge. ilp32 is open as #8229, verified against real Ghidra 12.1.4 with typed and stripped builds whose prototypes and argument storage match the compiler's call sites. ilp32f (ESP32-P4, H4, S31) follows as its own PR. I've updated the issue body to match; redirect in #8229's review if you disagree.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4457
No description provided.