[PR #2362] feat(ghidra): admit plain MIPS32 PIC shared images #5188

Open
opened 2026-10-31 01:04:39 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2362
Author: @AurelioB
Created: 10/12/2026
Status: 🔄 Open

Base: main ← Head: feat/mips32-shared


📝 Commits (10+)

  • 37f8aba feat(ghidra): admit plain MIPS32 PIC shared images
  • 4a046ed test(ghidra): cover MIPS link-base selection from file headers
  • 87d9661 style(ghidra): format link-base regression scenarios
  • 37cf638 test(ghidra): require zero-valued local GOT coverage
  • 59ca13d fix: reconcile PR #2362 with pinned main and preserve review fixes
  • 763e8bf test(ghidra): cover TPREL32 in the shared lane and drop duplicated session suites
  • af38cd3 Merge remote-tracking branch 'upstream/main' into feat/mips32-shared
  • 36f5a3e Merge remote-tracking branch 'upstream/main' into feat/mips32-shared
  • de8409e Merge branch 'main' into feat/mips32-shared
  • 5b51d83 Merge commit 'e049ef70f' into feat/mips32-shared

📊 Changes

22 files changed (+1650 additions, -40 deletions)

View changed files

📝 docs/ghidra-mips.md (+66 -2)
📝 package.json (+1 -0)
➕ scripts/verify-real-ghidra-mips32-shared.mjs (+350 -0)
📝 src/application/MipsElfSharedLoad.ts (+25 -2)
📝 src/domain/binaryTargetTypes.ts (+7 -0)
📝 src/ghidra/GhidraClient.ts (+3 -0)
📝 src/ghidra/GhidraClientTypes.ts (+2 -0)
📝 src/ghidra/GhidraLauncher.ts (+40 -9)
📝 src/ghidra/GhidraMipsProfile.test.ts (+199 -1)
📝 src/ghidra/GhidraMipsProfile.ts (+99 -16)
📝 src/ghidra/GhidraProviderClient.ts (+23 -0)
📝 src/ghidra/GhidraSessionValues.test.ts (+18 -0)
📝 src/ghidra/GhidraSessionValues.ts (+3 -0)
📝 tests/boundary/filesystem/mipsSharedLoad.test.ts (+52 -0)
📝 tests/boundary/providers/ghidra/ghidraLauncher.test.ts (+49 -0)
➕ tests/conformance/c/mips-shared.c (+41 -0)
📝 tests/conformance/ghidra/mips-checks.d.mts (+1 -1)
📝 tests/conformance/ghidra/mips-checks.mjs (+15 -9)
📝 tests/conformance/ghidra/mips-fixture.mjs (+45 -0)
➕ tests/conformance/ghidra/mips-shared-checks.d.mts (+74 -0)

...and 2 more files

📄 Description

Summary

Fixes #2338.

Ghidra refuses ordinary MIPS32 PIC shared libraries and ET_DYN executables (o32, MIPS32r2, no ASE flag): "This Ghidra MIPS lane supports ET_EXEC and ET_REL only". On one real MIPS32r2 Linux firmware root filesystem, that is 87 of its 225 MIPS ELF files. This PR adds a bounded lane, elf32-dyn-o32-arch32r2-standard-v1, that admits them and loads each image at its own ELF link base, so the GOT is read exactly as stored.

Problem and expected behavior

  • Use case: analyze firmware shared objects (for example libdsd2pcm.so, libdl-2.22.so) with the same Ghidra provider used for the firmware's executables and kernel modules.
  • Why Ghidra's default placement is wrong for these files:
    • Ghidra moves a shared object linked at 0 to 0x10000.
    • MIPS_ElfExtension.fixupGot then shifts local GOT entries only when they are nonzero (adjustTableEntryIfNonZero).
    • GOT page entries for page 0 hold 0, and GNU-ld libraries call static functions in their first 64 KiB through them. Those calls therefore decompile to wrong addresses: libdl _DT_INIT showed (*(code *)0xcf0)() when the target was at 0x10cf0.
  • Expected behavior: load at the link base, so no entry moves; every GOT entry is then correct as stored, and addresses match readelf/objdump.

Change and scope

  • Admission (GhidraMipsProfile.ts):
    • Requires complete dynamic-relocation inspection and the executable lane's ABI-flags requirements.
    • Allowed relocation types: R_MIPS_NONE, R_MIPS_REL32 (symbol-bearing included; plain MIPS32 has no MIPS16 mode-tag hazard), and the TLS loader slots DTPMOD32/DTPREL32/TPREL32.
    • TLS slots stay unapplied (UNSUPPORTED), and every analysis result carries a limitation saying so.
    • Refused: other relocation types, images without an ABI flags record, and images ending in an Android prelink trailer (Ghidra would prefer the trailer's base over PT_LOAD).
  • Load facts (MipsElfSharedLoad.ts): records source facts only: every PT_LOAD virtual address with its program-header index, and any Android prelink trailer. Ghidra's own image-base rule (the lowest PT_LOAD among the first 20 program headers, as ElfHeader.getImageBase() computes it, else 0) is applied in GhidraMipsProfile.ts.
  • Placement:
    • The profile commits elf_image_base, and the launcher passes -loader ElfLoader -loader-imagebase <base>.
    • The client refuses a committed profile whose image base differs from the target.
    • The bridge handshake must report the same image base.
    • The image base is refused together with PSP, DOS, raw-binary and GameCube DOL imports.
  • Out of scope: n32/n64, microMIPS, recordless images, resolving imports across images, and the MIPS16 shared lane (#1851, unchanged).

Follow the contribution scope.
Unresolved scope, authority, side effects, or required verification block
integration. Link the required maintainer scope decision for new providers or
capabilities involving target execution, injection, mutation, or protection
recovery; ordinary fixes within existing boundaries may state "not applicable".
Draft PRs may leave the scope decision pending and the readiness and merge checklists
unchecked. Maintainers can help resolve open questions.

Contract and boundary impact

  • Semantic owner and earliest changed stage: readMipsElfSharedLoad produces the new provider-neutral loadAddresses/prelinkBase facts. Consumers: GhidraMipsProfile (admission, Ghidra's image-base rule and the elf_image_base commitment), GhidraLauncher (ElfLoader arguments), GhidraProviderClient (commitment check) and GhidraSessionValues (handshake image base). No path is superseded.
  • Contribution scope fit and linked maintainer decision: not applicable. It extends the existing read-only Ghidra MIPS lanes to another ELF type; no target execution, injection, mutation or protection recovery.
  • CLI and MCP/tool-catalog contract: no new tools or arguments. Admitted MIPS32 ET_DYN targets now open, and their results carry the new lane, profile fields and limitations.
  • Provider, bridge, target-format, or platform compatibility: Ghidra only (ElfLoader with -loader-imagebase); no bridge source changes. Other targets get unchanged import arguments.
  • Evidence, artifact, provenance, or reconstruction contract: for this lane the analysis profile adds a top-level elf_image_base (offset, selection: elf-link-base-v1), so profile-bound snapshots are invalidated when it changes. Results carry the new lane id and placement, GOT and TLS limitations.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: adds the verify:ghidra:mips32-shared script to package.json; no generated metadata changes.

Expected effects (check known effects; use documentation-only on its own).
Unchecked items do not establish absence; leave uncertainties visible.

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

The process launched is the existing headless Ghidra import, now with -loader ElfLoader -loader-imagebase for this lane; target code is never run.

Evidence and regression coverage

  • Tests added or updated:
    • New real-Ghidra lane verify:ghidra:mips32-shared:
      • LLD fixtures (tests/conformance/c/mips-shared.c) laid out like GNU ld output: text in page 0, GOT-indirect jalr $25, and a call through a zero-valued local GOT page entry.
      • An independent GNU readelf oracle (mips-shared-checks.mjs) checks every relocated and GOT word through read_bytes: REL32 (local, defined, external), every local GOT entry including zero, every global GOT entry (defined, EXTERNAL, lazy-binding stub), and TLS slots UNSUPPORTED with unchanged bytes.
      • The decompiled entry function must name the static function and the import, reach __tls_get_addr, and contain no (*(code *)0x…) or PTR_ calls.
    • Unit and boundary tests:
      • admission and refusals;
      • the reader keeping every PT_LOAD with its header index (including one past header 20), and Ghidra's base rule in the profile (index 19 counted, index 20 ignored, no qualifying load gives 0);
      • prelink facts;
      • the profile commitment and mismatch refusal;
      • launcher arguments and their conflict guards, including the GameCube DOL case (fails with that guard removed);
      • the handshake image-base check.
  • Base reproduction or other evidence:
    • On main (1173c0a9d), the firmware's 87 ET_DYN files are refused by the "ET_EXEC and ET_REL only" rule.
    • Before the link-base change, libdl _DT_INIT decompiled to (*(code *)0xcf0)() (target 0x10cf0) and libdsd2pcm _init to (*(code *)0x45e0)().
  • User-visible CLI/MCP output (rea function <lib> <fn> --provider ghidra --json on d175f675b):
    • libdsd2pcm.so _init: FUN_000045e0(); iVar1 = FUN_00015030();, lane elf32-dyn-o32-arch32r2-standard-v1, elf_image_base 0x0.
    • libdl-2.22.so _DT_INIT (0xad0): FUN_00000cf0(); FUN_00001d50();.
    • Both call targets match the values computed from each file's own GOT words.
  • Remaining proof gaps:
    • Earlier head only: a firmware corpus run (throwaway harness, not committed) checked 85 of the 87 libraries with the same oracle: 34232 REL32, 13329 local and 17082 global GOT entries, 40 TLS slots, all matching. The other 2 lack an ABI flags record and are refused. It was not repeated on d175f675b.
    • Only images loaded at their own link base are verified; prelinked images are refused rather than placed.
    • TLS accesses are not resolved to variables.

For boundary fixes, identify the applicable boundary regressions
and lifecycle regressions
covered by the evidence above, and explain relevant gaps.

The changed boundaries are profile commitment, the handshake and launcher arguments. A mismatched committed profile, a session placed at a different base, and an image base combined with another loader are each refused, with tests above. There are no lifecycle changes.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

All on d175f675b (merge of main 1173c0a9d plus the review fix), Linux x64, Node 24.22.1 (.nvmrc), Ghidra 12.1.4, JDK 21, GNU readelf 2.46:

  • npx tsc --noEmit -p .: passed.
  • npx oxfmt --check .: passed.
  • npm run check:fast: passed.
  • npm run verify:test-discovery: passed.
  • npm run test:fast: 18946 passed, 14 skipped, 0 failed.
  • npm run verify:ghidra:mips32-shared: passed for LE, BE and soft-float LE; delta 0x0, got_local 2, got_local_zero 1, tls 3.
  • npm run verify:ghidra:mips-relocatable: passed.
  • npm run verify:ghidra:mips-shared (MIPS16; GNU binutils 2.45.90 with --hash-style=sysv): 4 admitted controls passed, 4 refused as expected.
  • npm run verify:ghidra:mips: fails, but not because of this PR. The carved fixture is refused at target resolution ("truncated ELF section header table"), and main 1173c0a9d fails identically. This PR doesn't touch that lane.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Previously refused targets are newly admitted; other targets' import arguments and profiles are unchanged.
  • Real Hopper/Ghidra, browser, or OS coverage: real Ghidra 12.1.4 on Linux x64 (above). macOS and Windows not run.
  • Package or release metadata impact: one new verify:ghidra:mips32-shared script.
  • Security, privacy, process, or containment review: read-only analysis; no target execution. The new launcher argument is a bare 32-bit hex value validated before use.

Author readiness

Human owner: @AurelioB

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 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/2362 **Author:** [@AurelioB](https://github.com/AurelioB) **Created:** 10/12/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/mips32-shared` --- ### 📝 Commits (10+) - [`37f8aba`](https://github.com/morluto/rea/commit/37f8aba263f4fdd641b6f2fb60984e6b31b2128e) feat(ghidra): admit plain MIPS32 PIC shared images - [`4a046ed`](https://github.com/morluto/rea/commit/4a046ed0f65c5427427d846f8f13216bca58e79a) test(ghidra): cover MIPS link-base selection from file headers - [`87d9661`](https://github.com/morluto/rea/commit/87d966118ee9e8808d91371d1e6305bdffc725bd) style(ghidra): format link-base regression scenarios - [`37cf638`](https://github.com/morluto/rea/commit/37cf63861f48a847d620658c6e6685a136ee0890) test(ghidra): require zero-valued local GOT coverage - [`59ca13d`](https://github.com/morluto/rea/commit/59ca13d1354b5c2534bf32e3016e551596085f23) fix: reconcile PR #2362 with pinned main and preserve review fixes - [`763e8bf`](https://github.com/morluto/rea/commit/763e8bf29b6d93841d8e59ae172c4908bd99990b) test(ghidra): cover TPREL32 in the shared lane and drop duplicated session suites - [`af38cd3`](https://github.com/morluto/rea/commit/af38cd3fcb068a37cdb34e75a5eed3885f914274) Merge remote-tracking branch 'upstream/main' into feat/mips32-shared - [`36f5a3e`](https://github.com/morluto/rea/commit/36f5a3ee497e4a067df70bc41c833e9642952cab) Merge remote-tracking branch 'upstream/main' into feat/mips32-shared - [`de8409e`](https://github.com/morluto/rea/commit/de8409e31f0284214296dbd0d0fdbc4e90cd5e2d) Merge branch 'main' into feat/mips32-shared - [`5b51d83`](https://github.com/morluto/rea/commit/5b51d834c969e2781b46d47176eaa124a59fd184) Merge commit 'e049ef70f' into feat/mips32-shared ### 📊 Changes **22 files changed** (+1650 additions, -40 deletions) <details> <summary>View changed files</summary> 📝 `docs/ghidra-mips.md` (+66 -2) 📝 `package.json` (+1 -0) ➕ `scripts/verify-real-ghidra-mips32-shared.mjs` (+350 -0) 📝 `src/application/MipsElfSharedLoad.ts` (+25 -2) 📝 `src/domain/binaryTargetTypes.ts` (+7 -0) 📝 `src/ghidra/GhidraClient.ts` (+3 -0) 📝 `src/ghidra/GhidraClientTypes.ts` (+2 -0) 📝 `src/ghidra/GhidraLauncher.ts` (+40 -9) 📝 `src/ghidra/GhidraMipsProfile.test.ts` (+199 -1) 📝 `src/ghidra/GhidraMipsProfile.ts` (+99 -16) 📝 `src/ghidra/GhidraProviderClient.ts` (+23 -0) 📝 `src/ghidra/GhidraSessionValues.test.ts` (+18 -0) 📝 `src/ghidra/GhidraSessionValues.ts` (+3 -0) 📝 `tests/boundary/filesystem/mipsSharedLoad.test.ts` (+52 -0) 📝 `tests/boundary/providers/ghidra/ghidraLauncher.test.ts` (+49 -0) ➕ `tests/conformance/c/mips-shared.c` (+41 -0) 📝 `tests/conformance/ghidra/mips-checks.d.mts` (+1 -1) 📝 `tests/conformance/ghidra/mips-checks.mjs` (+15 -9) 📝 `tests/conformance/ghidra/mips-fixture.mjs` (+45 -0) ➕ `tests/conformance/ghidra/mips-shared-checks.d.mts` (+74 -0) _...and 2 more files_ </details> ### 📄 Description ## Summary Fixes #2338. Ghidra refuses ordinary MIPS32 PIC shared libraries and `ET_DYN` executables (o32, MIPS32r2, no ASE flag): "This Ghidra MIPS lane supports ET_EXEC and ET_REL only". On one real MIPS32r2 Linux firmware root filesystem, that is 87 of its 225 MIPS ELF files. This PR adds a bounded lane, `elf32-dyn-o32-arch32r2-standard-v1`, that admits them and loads each image at its own ELF link base, so the GOT is read exactly as stored. ## Problem and expected behavior - **Use case:** analyze firmware shared objects (for example `libdsd2pcm.so`, `libdl-2.22.so`) with the same Ghidra provider used for the firmware's executables and kernel modules. - **Why Ghidra's default placement is wrong for these files:** - Ghidra moves a shared object linked at 0 to `0x10000`. - `MIPS_ElfExtension.fixupGot` then shifts local GOT entries only when they are nonzero (`adjustTableEntryIfNonZero`). - GOT page entries for page 0 hold 0, and GNU-ld libraries call static functions in their first 64 KiB through them. Those calls therefore decompile to wrong addresses: libdl `_DT_INIT` showed `(*(code *)0xcf0)()` when the target was at `0x10cf0`. - **Expected behavior:** load at the link base, so no entry moves; every GOT entry is then correct as stored, and addresses match readelf/objdump. ## Change and scope - **Admission** (`GhidraMipsProfile.ts`): - Requires complete dynamic-relocation inspection and the executable lane's ABI-flags requirements. - Allowed relocation types: `R_MIPS_NONE`, `R_MIPS_REL32` (symbol-bearing included; plain MIPS32 has no MIPS16 mode-tag hazard), and the TLS loader slots `DTPMOD32`/`DTPREL32`/`TPREL32`. - TLS slots stay unapplied (`UNSUPPORTED`), and every analysis result carries a limitation saying so. - Refused: other relocation types, images without an ABI flags record, and images ending in an Android prelink trailer (Ghidra would prefer the trailer's base over `PT_LOAD`). - **Load facts** (`MipsElfSharedLoad.ts`): records source facts only: every `PT_LOAD` virtual address with its program-header index, and any Android prelink trailer. Ghidra's own image-base rule (the lowest `PT_LOAD` among the first 20 program headers, as `ElfHeader.getImageBase()` computes it, else 0) is applied in `GhidraMipsProfile.ts`. - **Placement:** - The profile commits `elf_image_base`, and the launcher passes `-loader ElfLoader -loader-imagebase <base>`. - The client refuses a committed profile whose image base differs from the target. - The bridge handshake must report the same image base. - The image base is refused together with PSP, DOS, raw-binary and GameCube DOL imports. - **Out of scope:** n32/n64, microMIPS, recordless images, resolving imports across images, and the MIPS16 shared lane (#1851, unchanged). Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). Unresolved scope, authority, side effects, or required verification block integration. Link the required maintainer scope decision for new providers or capabilities involving target execution, injection, mutation, or protection recovery; ordinary fixes within existing boundaries may state "not applicable". Draft PRs may leave the scope decision pending and the readiness and merge checklists unchecked. Maintainers can help resolve open questions. ## Contract and boundary impact - Semantic owner and earliest changed stage: `readMipsElfSharedLoad` produces the new provider-neutral `loadAddresses`/`prelinkBase` facts. Consumers: `GhidraMipsProfile` (admission, Ghidra's image-base rule and the `elf_image_base` commitment), `GhidraLauncher` (ElfLoader arguments), `GhidraProviderClient` (commitment check) and `GhidraSessionValues` (handshake image base). No path is superseded. - Contribution scope fit and linked maintainer decision: not applicable. It extends the existing read-only Ghidra MIPS lanes to another ELF type; no target execution, injection, mutation or protection recovery. - CLI and MCP/tool-catalog contract: no new tools or arguments. Admitted MIPS32 `ET_DYN` targets now open, and their results carry the new lane, profile fields and limitations. - Provider, bridge, target-format, or platform compatibility: Ghidra only (`ElfLoader` with `-loader-imagebase`); no bridge source changes. Other targets get unchanged import arguments. - Evidence, artifact, provenance, or reconstruction contract: for this lane the analysis profile adds a top-level `elf_image_base` (`offset`, `selection: elf-link-base-v1`), so profile-bound snapshots are invalidated when it changes. Results carry the new lane id and placement, GOT and TLS limitations. - Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: adds the `verify:ghidra:mips32-shared` script to `package.json`; no generated metadata changes. Expected effects (check known effects; use documentation-only on its own). Unchecked items do not establish absence; leave uncertainties visible. - [x] Read existing files or captured data. - [x] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. The process launched is the existing headless Ghidra import, now with `-loader ElfLoader -loader-imagebase` for this lane; target code is never run. ## Evidence and regression coverage - **Tests added or updated:** - New real-Ghidra lane `verify:ghidra:mips32-shared`: - LLD fixtures (`tests/conformance/c/mips-shared.c`) laid out like GNU ld output: text in page 0, GOT-indirect `jalr $25`, and a call through a zero-valued local GOT page entry. - An independent GNU readelf oracle (`mips-shared-checks.mjs`) checks every relocated and GOT word through `read_bytes`: REL32 (local, defined, external), every local GOT entry including zero, every global GOT entry (defined, EXTERNAL, lazy-binding stub), and TLS slots `UNSUPPORTED` with unchanged bytes. - The decompiled entry function must name the static function and the import, reach `__tls_get_addr`, and contain no `(*(code *)0x…)` or `PTR_` calls. - Unit and boundary tests: - admission and refusals; - the reader keeping every `PT_LOAD` with its header index (including one past header 20), and Ghidra's base rule in the profile (index 19 counted, index 20 ignored, no qualifying load gives 0); - prelink facts; - the profile commitment and mismatch refusal; - launcher arguments and their conflict guards, including the GameCube DOL case (fails with that guard removed); - the handshake image-base check. - **Base reproduction or other evidence:** - On `main` (`1173c0a9d`), the firmware's 87 `ET_DYN` files are refused by the "ET_EXEC and ET_REL only" rule. - Before the link-base change, libdl `_DT_INIT` decompiled to `(*(code *)0xcf0)()` (target `0x10cf0`) and libdsd2pcm `_init` to `(*(code *)0x45e0)()`. - **User-visible CLI/MCP output** (`rea function <lib> <fn> --provider ghidra --json` on `d175f675b`): - `libdsd2pcm.so` `_init`: `FUN_000045e0(); iVar1 = FUN_00015030();`, lane `elf32-dyn-o32-arch32r2-standard-v1`, `elf_image_base` `0x0`. - `libdl-2.22.so` `_DT_INIT` (`0xad0`): `FUN_00000cf0(); FUN_00001d50();`. - Both call targets match the values computed from each file's own GOT words. - **Remaining proof gaps:** - **Earlier head only:** a firmware corpus run (throwaway harness, not committed) checked 85 of the 87 libraries with the same oracle: 34232 REL32, 13329 local and 17082 global GOT entries, 40 TLS slots, all matching. The other 2 lack an ABI flags record and are refused. It was not repeated on `d175f675b`. - Only images loaded at their own link base are verified; prelinked images are refused rather than placed. - TLS accesses are not resolved to variables. For boundary fixes, identify the applicable [boundary regressions](https://github.com/morluto/rea/blob/main/docs/testing.md#boundary-regressions) and [lifecycle regressions](https://github.com/morluto/rea/blob/main/docs/testing.md#lifecycle-regressions) covered by the evidence above, and explain relevant gaps. The changed boundaries are profile commitment, the handshake and launcher arguments. A mismatched committed profile, a session placed at a different base, and an image base combined with another loader are each refused, with tests above. There are no lifecycle changes. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed All on `d175f675b` (merge of `main` `1173c0a9d` plus the review fix), Linux x64, Node 24.22.1 (`.nvmrc`), Ghidra 12.1.4, JDK 21, GNU readelf 2.46: - `npx tsc --noEmit -p .`: passed. - `npx oxfmt --check .`: passed. - `npm run check:fast`: passed. - `npm run verify:test-discovery`: passed. - `npm run test:fast`: 18946 passed, 14 skipped, 0 failed. - `npm run verify:ghidra:mips32-shared`: passed for LE, BE and soft-float LE; `delta 0x0`, `got_local 2`, `got_local_zero 1`, `tls 3`. - `npm run verify:ghidra:mips-relocatable`: passed. - `npm run verify:ghidra:mips-shared` (MIPS16; GNU binutils 2.45.90 with `--hash-style=sysv`): 4 admitted controls passed, 4 refused as expected. - `npm run verify:ghidra:mips`: fails, but not because of this PR. The carved fixture is refused at target resolution ("truncated ELF section header table"), and `main` `1173c0a9d` fails identically. This PR doesn't touch that lane. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Previously refused targets are newly admitted; other targets' import arguments and profiles are unchanged. - Real Hopper/Ghidra, browser, or OS coverage: real Ghidra 12.1.4 on Linux x64 (above). macOS and Windows not run. - Package or release metadata impact: one new `verify:ghidra:mips32-shared` script. - Security, privacy, process, or containment review: read-only analysis; no target execution. The new launcher argument is a bare 32-bit hex value validated before use. ## Author readiness Human owner: @AurelioB - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#5188
No description provided.