[PR #1374] [MERGED] fix(ghidra): verify dense jump tables on an optimized fixture #2836

Closed
opened 2026-10-17 21:10:50 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1374
Author: @BaaRai
Created: 10/9/2026
Status: ✅ Merged
Merged: 10/9/2026
Merged by: @morluto

Base: main ← Head: fix/real-ghidra-dense-jump-table-source


📝 Commits (1)

  • 9c49bd3 fix(ghidra): verify dense jump tables on an optimized fixture

📊 Changes

2 files changed (+53 additions, -20 deletions)

View changed files

📝 scripts/verify-real-ghidra-function.mjs (+22 -8)
📝 scripts/verify-real-ghidra.mjs (+31 -12)

📄 Description

Summary

The real-Ghidra host lane demanded dense jump-table evidence from the -O0 debug fixture. GCC 16 and later lower dense switches to compare chains at -O0 (empirically: rea_ghidra_inventory_dense_switch compiles to a cmpl/je/ja tree with no indirect jump), so on those hosts both dense oracles failed against a correct provider and a correct Ghidra 12.1.4 analysis. The lane now compiles the same inventory source once more at -O2 as a dedicated jump-table fixture variant and runs the strict dense oracles there; the debug fixture keeps its complete generic dossier shape and all its -O0-specific oracles.

Problem and expected behavior

Smallest trigger: npm run verify:ghidra with cc = GCC 16.2 (reproduced on Kali rolling, glibc 2.43, node 24.19, Ghidra 12.1.4, JDK 21). Two sites rejected the run:

  • scripts/verify-real-ghidra.mjs verifyNativeApiCli: The shipped inspect-native-api CLI did not preserve complete dense jump-table output with "jump_tables": [] from the -O0 debug build.
  • scripts/verify-real-ghidra-assertions.mjs assertDenseSwitchDossier (via verifyDebugFunctionOperations): Ghidra dense jump-table completeness drifted: [].

Violated invariant: the dense-table oracle must observe a fixture that actually contains a table. Switch lowering is a host-toolchain decision: -O0 compare-chain expansion (GCC 16) versus table expansion (older GCC at -O0, and all tested compilers at -O2, where the same source produces lea table(%rip); movslq (%rdx,%rdi,4); add; jmp *%rax). The dedicated verify:ghidra:switch lane already compiles at -O2 for exactly this reason; the inventory lane was the inconsistent one.

Change and scope

  • scripts/verify-real-ghidra.mjs: build rea-ghidra-inventory-jump from the same source with -O2 -g -fno-inline (plus the lane's -fno-pie -no-pie on ELF), verify it as the jump-table variant, route verifyNativeApiCli and the new verifyJumpTableDenseSwitch probe to it, and report it in the fixtures list and native_api_cli summary.
  • scripts/verify-real-ghidra-function.mjs: verifyDebugFunctionOperations now asserts the dense-switch dossier's complete generic shape (address, assembly, multi-block) on every platform, since -O0 codegen is toolchain-dependent; the new exported verifyJumpTableDenseSwitch carries the strict assertDenseSwitchDossier against the optimized fixture.

Not included: no product, bridge, provider, or contract changes; the debug fixture's build flags are untouched; cross-format and AArch64 lanes are unchanged (crossArm64Elf keeps its existing -O2 cross builds).

Contract and boundary impact

  • Semantic owner and earliest changed stage: verifier scripts only; no runtime stage changes.
  • CLI and MCP/tool-catalog contract: none.
  • Provider, bridge, target-format, or platform compatibility: improves host-lane portability across GCC versions; no provider or bridge change.
  • Evidence, artifact, provenance, or reconstruction contract: not applicable.
  • Process execution, authorization, cleanup, or containment impact: not applicable.
  • Generated metadata, package, or installation impact: not applicable.

Evidence and regression coverage

  • Tests added or updated: none; this lane is the executable evidence and has no mocked mirror.
  • Base reproduction and other evidence: executed runs on Kali rolling with GHIDRA_INSTALL_DIR at Ghidra 12.1.4 and JDK 21:
    • Base a9f5dad5: the lane fails at the CLI dense-table oracle (jump_tables: [] from the -O0 debug fixture), and after that is bypassed, again at the dossier oracle.
    • This change: the full host lane completes with exit 0 and ok: true, four fixtures (debug, stripped, type-layout, jump-table), native_api_cli.mappings_returned = 40, the dense default-target oracle verified (mov eax, -1 at the default address), residual_unknowns = 0, and cleanup: complete.
    • Compiler-behavior evidence: the same source at -O0 shows zero indirect jumps through tables in the disassembly while -O2 shows the 40-entry relative table; the debug fixture's generic dossier assertions still pass at both optimization levels.
  • User-visible CLI/MCP output: not applicable.

🔄 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/1374 **Author:** [@BaaRai](https://github.com/BaaRai) **Created:** 10/9/2026 **Status:** ✅ Merged **Merged:** 10/9/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/real-ghidra-dense-jump-table-source` --- ### 📝 Commits (1) - [`9c49bd3`](https://github.com/morluto/rea/commit/9c49bd35ce570c214c941302292070a46a647f23) fix(ghidra): verify dense jump tables on an optimized fixture ### 📊 Changes **2 files changed** (+53 additions, -20 deletions) <details> <summary>View changed files</summary> 📝 `scripts/verify-real-ghidra-function.mjs` (+22 -8) 📝 `scripts/verify-real-ghidra.mjs` (+31 -12) </details> ### 📄 Description ## Summary The real-Ghidra host lane demanded dense jump-table evidence from the `-O0` debug fixture. GCC 16 and later lower dense switches to compare chains at `-O0` (empirically: `rea_ghidra_inventory_dense_switch` compiles to a `cmpl/je/ja` tree with no indirect jump), so on those hosts both dense oracles failed against a correct provider and a correct Ghidra 12.1.4 analysis. The lane now compiles the same inventory source once more at `-O2` as a dedicated `jump-table` fixture variant and runs the strict dense oracles there; the debug fixture keeps its complete generic dossier shape and all its `-O0`-specific oracles. ## Problem and expected behavior Smallest trigger: `npm run verify:ghidra` with `cc` = GCC 16.2 (reproduced on Kali rolling, glibc 2.43, node 24.19, Ghidra 12.1.4, JDK 21). Two sites rejected the run: - `scripts/verify-real-ghidra.mjs` `verifyNativeApiCli`: `The shipped inspect-native-api CLI did not preserve complete dense jump-table output` with `"jump_tables": []` from the `-O0` debug build. - `scripts/verify-real-ghidra-assertions.mjs` `assertDenseSwitchDossier` (via `verifyDebugFunctionOperations`): `Ghidra dense jump-table completeness drifted: []`. Violated invariant: the dense-table oracle must observe a fixture that actually contains a table. Switch lowering is a host-toolchain decision: `-O0` compare-chain expansion (GCC 16) versus table expansion (older GCC at `-O0`, and all tested compilers at `-O2`, where the same source produces `lea table(%rip); movslq (%rdx,%rdi,4); add; jmp *%rax`). The dedicated `verify:ghidra:switch` lane already compiles at `-O2` for exactly this reason; the inventory lane was the inconsistent one. ## Change and scope - `scripts/verify-real-ghidra.mjs`: build `rea-ghidra-inventory-jump` from the same source with `-O2 -g -fno-inline` (plus the lane's `-fno-pie -no-pie` on ELF), verify it as the `jump-table` variant, route `verifyNativeApiCli` and the new `verifyJumpTableDenseSwitch` probe to it, and report it in the fixtures list and `native_api_cli` summary. - `scripts/verify-real-ghidra-function.mjs`: `verifyDebugFunctionOperations` now asserts the dense-switch dossier's complete generic shape (address, assembly, multi-block) on every platform, since `-O0` codegen is toolchain-dependent; the new exported `verifyJumpTableDenseSwitch` carries the strict `assertDenseSwitchDossier` against the optimized fixture. Not included: no product, bridge, provider, or contract changes; the debug fixture's build flags are untouched; cross-format and AArch64 lanes are unchanged (`crossArm64Elf` keeps its existing `-O2` cross builds). ## Contract and boundary impact - Semantic owner and earliest changed stage: verifier scripts only; no runtime stage changes. - CLI and MCP/tool-catalog contract: none. - Provider, bridge, target-format, or platform compatibility: improves host-lane portability across GCC versions; no provider or bridge change. - Evidence, artifact, provenance, or reconstruction contract: not applicable. - Process execution, authorization, cleanup, or containment impact: not applicable. - Generated metadata, package, or installation impact: not applicable. ## Evidence and regression coverage - Tests added or updated: none; this lane is the executable evidence and has no mocked mirror. - Base reproduction and other evidence: executed runs on Kali rolling with `GHIDRA_INSTALL_DIR` at Ghidra 12.1.4 and JDK 21: - Base a9f5dad5: the lane fails at the CLI dense-table oracle (`jump_tables: []` from the `-O0` debug fixture), and after that is bypassed, again at the dossier oracle. - This change: the full host lane completes with exit 0 and `ok: true`, four fixtures (debug, stripped, type-layout, jump-table), `native_api_cli.mappings_returned = 40`, the dense default-target oracle verified (`mov eax, -1` at the default address), `residual_unknowns = 0`, and `cleanup: complete`. - Compiler-behavior evidence: the same source at `-O0` shows zero indirect jumps through tables in the disassembly while `-O2` shows the 40-entry relative table; the debug fixture's generic dossier assertions still pass at both optimization levels. - User-visible CLI/MCP output: not applicable. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:10:50 +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#2836
No description provided.