[PR #1950] [MERGED] feat(ghidra): admit relocatable MIPS32r2 ELF objects #4932

Closed
opened 2026-10-31 00:57:06 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1950
Author: @AurelioB
Created: 10/11/2026
Status: ✅ Merged
Merged: 10/11/2026
Merged by: @morluto

Base: main ← Head: feat/mips-relocatable


📝 Commits (6)

  • b992aa6 feat(ghidra): admit soft-float MIPS32r2 ELF with integer-register float storage
  • 5965eae fix(ghidra): model soft-float MIPS as a prototype for every typed callable
  • c5d346c test(ghidra): pin ODDSPREG acceptance for soft-float MIPS ABI records
  • 4019966 feat(ghidra): admit relocatable MIPS32r2 ELF objects
  • 1b2b98e fix(ghidra): verify every MIPS HI16 and archive-typed soft-float externals
  • b200b6d fix(ci): merge main and deduplicate MIPS fixture verification

📊 Changes

13 files changed (+1343 additions, -110 deletions)

View changed files

📝 docs/ghidra-mips.md (+50 -7)
📝 package.json (+1 -0)
➕ scripts/verify-real-ghidra-mips-relocatable.mjs (+333 -0)
📝 src/ghidra/GhidraMipsProfile.test.ts (+105 -72)
📝 src/ghidra/GhidraMipsProfile.ts (+21 -3)
📝 src/ghidra/GhidraProviderClient.ts (+2 -0)
➕ tests/conformance/c/mips-relocatable.c (+53 -0)
📝 tests/conformance/ghidra/mips-checks.d.mts (+1 -0)
📝 tests/conformance/ghidra/mips-checks.mjs (+32 -12)
📝 tests/conformance/ghidra/mips-fixture.mjs (+66 -16)
➕ tests/conformance/ghidra/mips-relocatable-checks.d.mts (+69 -0)
➕ tests/conformance/ghidra/mips-relocatable-checks.mjs (+346 -0)
➕ tests/conformance/ghidra/mips-relocatable-checks.test.ts (+264 -0)

📄 Description

Stacked on #1949 (soft-float), because kernel modules are soft-float. Until #1949 merges this PR also shows its commits; review only this PR's own two, feat(ghidra): admit relocatable MIPS32r2 ELF objects (4019966b) and fix(ghidra): verify every MIPS HI16 and archive-typed soft-float externals (1b2b98ed).

Closes #1938.

Behavior

  • Admission: ELF32 o32 MIPS32r2 ET_REL alongside ET_EXEC. ET_DYN and PRX stay refused.
  • Profile: relocatable targets commit mips_support_lane: elf32-rel-o32-arch32r2-standard-v1; executables keep elf32-exec-o32-arch32r2-standard-v3.
  • Session limitations for relocatable targets: addresses are Ghidra analysis coordinates, undefined symbols live in the EXTERNAL block, and inspect_native_load_image relocation statuses (HI16 → PARTIAL).
  • Soft-float relocatable objects (kernel modules) get #1949's __rea_soft_float prototype, including archive-typed externals such as powf.

Verification

Host: Linux x64, Ghidra 12.1.4, OpenJDK 21.0.12, Clang 21, GNU readelf.

  • New npm run verify:ghidra:mips-relocatable (real Ghidra): LE and BE -c -G0 -fno-builtin objects, plus an LE soft-float -mlong-calls variant matching Linux module flags. GNU readelf supplies sections, symbols and REL entries; for every relocation in an allocated section the lane reads the loaded word via read_bytes and requires S + A (S from Ghidra's list_segments/EXTERNAL placement, A from original bytes). Each HI16 waits for the next LO16 of its symbol, which checks the effective address it forms with every HI16 it resolves; later LO16s reuse those HI16s; a HI16 left unresolved fails. Coverage is asserted: shared HI16, LO16 ≥ 0x8000 carry, external code and data, R_MIPS_32, R_MIPS_26 only without long calls. The fixture calls powf, typed by Ghidra's C library archive: every variant must decompile powf(1.5,2.5) without FPU inputs, and the soft-float variant must report that the soft-float prototype covered it (with externals left out it decompiles as powf(param_1,param_2)). Plus direct calls, snapshot lane/type/policy, Evidence limitation, CLI evidence and unchanged source bytes. All 3 fixtures passed, process lineage verified.
  • npm run verify:ghidra:mips (executables, 4 fixtures) passes on this branch.
  • npm run test:fast: 393 files, 4620 passed, 3 skipped. check:fast, oxfmt --check . and test discovery clean.
  • Unit: admission/lane/limitation tests, readelf REL parser, and the relocation assertion's negative cases (missing carry, wrong jump target, rewritten opcode, unrelocated word, failed/missing Ghidra relocation, wrong file offset, empty-section symbol counted as unplaced, a bad earlier HI16 hidden behind a later HI16 and an intervening R_MIPS_26, an unresolved HI16).
  • Real modules (not committed): the same assertion over 30 soft-float X1600 .ko files on the final commit: 30/30 passed, 54,972 relocations matched, 93 references to empty sections counted as unplaced, 0 failed Ghidra statuses. 24 of the 30 modules contain several HI16s resolved by one LO16, which the first revision did not fully check. The largest module's load image and name inventory exceed the MCP stdio budget and were read from the session's exported evidence bundle.

Not run: Windows lanes (MIPS is not admitted on Windows P0); --psp.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1950 **Author:** [@AurelioB](https://github.com/AurelioB) **Created:** 10/11/2026 **Status:** ✅ Merged **Merged:** 10/11/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `feat/mips-relocatable` --- ### 📝 Commits (6) - [`b992aa6`](https://github.com/morluto/rea/commit/b992aa67058a21daca0bf1fba002f15c371256b1) feat(ghidra): admit soft-float MIPS32r2 ELF with integer-register float storage - [`5965eae`](https://github.com/morluto/rea/commit/5965eae85b45b9db601984487ff7346129c1a141) fix(ghidra): model soft-float MIPS as a prototype for every typed callable - [`c5d346c`](https://github.com/morluto/rea/commit/c5d346c029c4e952caf6c40c42ba87e58715281d) test(ghidra): pin ODDSPREG acceptance for soft-float MIPS ABI records - [`4019966`](https://github.com/morluto/rea/commit/4019966b341fa405152685c933d21ef2e0adf932) feat(ghidra): admit relocatable MIPS32r2 ELF objects - [`1b2b98e`](https://github.com/morluto/rea/commit/1b2b98edf92e1f1be9ab29a3c19376582cf7478c) fix(ghidra): verify every MIPS HI16 and archive-typed soft-float externals - [`b200b6d`](https://github.com/morluto/rea/commit/b200b6d81b5beead0ecd83af8641142ede74061e) fix(ci): merge main and deduplicate MIPS fixture verification ### 📊 Changes **13 files changed** (+1343 additions, -110 deletions) <details> <summary>View changed files</summary> 📝 `docs/ghidra-mips.md` (+50 -7) 📝 `package.json` (+1 -0) ➕ `scripts/verify-real-ghidra-mips-relocatable.mjs` (+333 -0) 📝 `src/ghidra/GhidraMipsProfile.test.ts` (+105 -72) 📝 `src/ghidra/GhidraMipsProfile.ts` (+21 -3) 📝 `src/ghidra/GhidraProviderClient.ts` (+2 -0) ➕ `tests/conformance/c/mips-relocatable.c` (+53 -0) 📝 `tests/conformance/ghidra/mips-checks.d.mts` (+1 -0) 📝 `tests/conformance/ghidra/mips-checks.mjs` (+32 -12) 📝 `tests/conformance/ghidra/mips-fixture.mjs` (+66 -16) ➕ `tests/conformance/ghidra/mips-relocatable-checks.d.mts` (+69 -0) ➕ `tests/conformance/ghidra/mips-relocatable-checks.mjs` (+346 -0) ➕ `tests/conformance/ghidra/mips-relocatable-checks.test.ts` (+264 -0) </details> ### 📄 Description Stacked on #1949 (soft-float), because kernel modules are soft-float. Until #1949 merges this PR also shows its commits; review only this PR's own two, `feat(ghidra): admit relocatable MIPS32r2 ELF objects` (4019966b) and `fix(ghidra): verify every MIPS HI16 and archive-typed soft-float externals` (1b2b98ed). Closes #1938. ## Behavior - Admission: ELF32 o32 MIPS32r2 `ET_REL` alongside `ET_EXEC`. `ET_DYN` and PRX stay refused. - Profile: relocatable targets commit `mips_support_lane: elf32-rel-o32-arch32r2-standard-v1`; executables keep `elf32-exec-o32-arch32r2-standard-v3`. - Session limitations for relocatable targets: addresses are Ghidra analysis coordinates, undefined symbols live in the `EXTERNAL` block, and `inspect_native_load_image` relocation statuses (HI16 → `PARTIAL`). - Soft-float relocatable objects (kernel modules) get #1949's `__rea_soft_float` prototype, including archive-typed externals such as `powf`. ## Verification Host: Linux x64, Ghidra 12.1.4, OpenJDK 21.0.12, Clang 21, GNU readelf. - New `npm run verify:ghidra:mips-relocatable` (real Ghidra): LE and BE `-c -G0 -fno-builtin` objects, plus an LE soft-float `-mlong-calls` variant matching Linux module flags. GNU readelf supplies sections, symbols and REL entries; for every relocation in an allocated section the lane reads the loaded word via `read_bytes` and requires `S + A` (S from Ghidra's `list_segments`/`EXTERNAL` placement, A from original bytes). Each HI16 waits for the next LO16 of its symbol, which checks the effective address it forms with every HI16 it resolves; later LO16s reuse those HI16s; a HI16 left unresolved fails. Coverage is asserted: shared HI16, LO16 ≥ 0x8000 carry, external code and data, `R_MIPS_32`, `R_MIPS_26` only without long calls. The fixture calls `powf`, typed by Ghidra's C library archive: every variant must decompile `powf(1.5,2.5)` without FPU inputs, and the soft-float variant must report that the soft-float prototype covered it (with externals left out it decompiles as `powf(param_1,param_2)`). Plus direct calls, snapshot lane/type/policy, Evidence limitation, CLI evidence and unchanged source bytes. All 3 fixtures passed, process lineage verified. - `npm run verify:ghidra:mips` (executables, 4 fixtures) passes on this branch. - `npm run test:fast`: 393 files, 4620 passed, 3 skipped. `check:fast`, `oxfmt --check .` and test discovery clean. - Unit: admission/lane/limitation tests, readelf REL parser, and the relocation assertion's negative cases (missing carry, wrong jump target, rewritten opcode, unrelocated word, failed/missing Ghidra relocation, wrong file offset, empty-section symbol counted as unplaced, a bad earlier HI16 hidden behind a later HI16 and an intervening `R_MIPS_26`, an unresolved HI16). - Real modules (not committed): the same assertion over 30 soft-float X1600 `.ko` files on the final commit: 30/30 passed, 54,972 relocations matched, 93 references to empty sections counted as unplaced, 0 failed Ghidra statuses. 24 of the 30 modules contain several HI16s resolved by one LO16, which the first revision did not fully check. The largest module's load image and name inventory exceed the MCP stdio budget and were read from the session's exported evidence bundle. Not run: Windows lanes (MIPS is not admitted on Windows P0); `--psp`. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:57:06 +00:00
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#4932
No description provided.