[PR #5240] feat(ghidra): admit PlayStation 2 EE executables through ghidra-emotionengine-reloaded #6832

Open
opened 2026-11-01 21:43:21 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5240
Author: @litterboks
Created: 10/19/2026
Status: 🔄 Open

Base: main ← Head: feat/ghidra-ps2-ee-profile


📝 Commits (1)

  • 07c0a78 feat(ghidra): PlayStation 2 EE profile through ghidra-emotionengine-reloaded

📊 Changes

10 files changed (+549 additions, -51 deletions)

View changed files

➕ docs/ghidra-ps2.md (+59 -0)
📝 src/ghidra/GhidraAnalysisProfile.ts (+26 -0)
➕ src/ghidra/GhidraEeExtension.ts (+59 -0)
➕ src/ghidra/GhidraEeProfile.test.ts (+123 -0)
➕ src/ghidra/GhidraEeProfile.ts (+96 -0)
📝 src/ghidra/GhidraLauncher.ts (+35 -0)
📝 src/ghidra/GhidraProvider.ts (+8 -2)
📝 src/ghidra/GhidraProviderClient.ts (+29 -0)
📝 src/ghidra/GhidraPspExtension.ts (+109 -49)
📝 src/ghidra/GhidraPspProfile.ts (+5 -0)

📄 Description

Summary

PlayStation 2 retail executables are MIPS ELF32 files whose header declares the
Emotion Engine (EF_MIPS_MACH_5900). Today every provider refuses them: the
Ghidra lane stops at "Machine-specific MIPS variants, including PSP Allegrex,
need a separately supported processor profile". This adds that profile, built
the same way as the PSP lane: REA pins the language of a caller-installed
extension (ghidra-emotionengine-reloaded,
r5900:LE:32:default) and fingerprints it, but never installs it.

No issue exists for this; the PSP lane (#1330) is the precedent the design follows.

Problem and expected behavior

rea decompile <retail PS2 ELF> sceGsSyncPath --provider ghidra fails with
architecture_unsupported. With the extension installed under
$GHIDRA_INSTALL_DIR/Ghidra/Extensions/ghidra-emotionengine-reloaded, the same
call now resolves lane ps2-elf32-exec-eabi64-r5900-v1 and returns pseudocode
with the extension's MMIO register names and COP2 intrinsics. Without the
extension it fails with EE_EXTENSION_UNAVAILABLE and an installation hint.

Change and scope

  • GhidraEeProfile.ts: admission of exactly the ee-gcc declaration --
    little-endian ELF32 ET_EXEC, EF_MIPS_ARCH_3, ABI EABI64 or none,
    optionally NOREORDER, no other header bits, no ABI flags record, no GNU MIPS
    attributes; pinned language, profile parameters, result limitations.
    Everything else is refused, not inferred.
  • GhidraEeExtension.ts: the extension's fingerprint and resolution.
  • GhidraPspExtension.ts: the Allegrex inspection generalised into a
    processor-extension inspection parameterised by id, label, failure code and
    required files. PSP exports, behaviour and messages are unchanged
    (tests/boundary/filesystem/ghidraPspExtension.test.ts passes unmodified).
  • Wiring in the processor dispatcher, analysis profile, provider host check,
    provider client and launcher (pre-launch re-inspection), mirroring the PSP lane.
  • docs/ghidra-ps2.md.

Not included: IRX modules, relocatable/shared images, ISO containers,
overlays, non-Linux-x64 hosts, producers that write an ABI flags record.

Contract and boundary impact

  • Semantic owner and earliest changed stage: Ghidra provider target admission (ghidraProcessorUnsupportedReason), then analysis-profile resolution.
  • Contribution scope fit and linked maintainer decision: static decompilation of a new processor family through an existing provider; no maintainer decision linked yet -- requested here.
  • CLI and MCP/tool-catalog contract: unchanged; new admitted targets and a new failure code EE_EXTENSION_UNAVAILABLE.
  • Provider, bridge, target-format, or platform compatibility: Ghidra only, Linux x64 only; bridge unchanged.
  • Evidence, artifact, provenance, or reconstruction contract: new profile parameters (mips_support_lane, ee_extension fingerprint, pinned language); results carry three EE limitations.
  • Target selection, authority, upstream behavior, and cleanup details: not applicable (static import, ephemeral project as before).
  • Generated metadata, package, or installation impact: none; the extension stays caller-installed.

Expected effects:

  • 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.

Evidence and regression coverage

  • Tests added or updated: src/ghidra/GhidraEeProfile.test.ts (admission of the ee-gcc declaration, pinned language and parameters, refusal of ASE/other ISA/other ABI/undeclared bits/big-endian/non-EXEC/ABI-flags record/uninspected declaration, generic MIPS and PSP left to their lanes).
  • Base reproduction: on main, the same CLI call returns architecture_unsupported with the "Machine-specific MIPS variants" reason (observed with the published 6.7.0 and the fork's main).
  • User-visible output (abridged, executed against a retail SCES_511.90, e_flags 0x20924000, Ghidra 12.1.4, extension v2.1.38):
analysis_profile.parameters:
  language_id: "r5900:LE:32:default"
  language_selection: provider-pinned-v1
  mips_support_lane: ps2-elf32-exec-eabi64-r5900-v1
  ee_extension: { id: ghidra-emotionengine-reloaded, ghidra_version: 12.1.4, sha256: c339de37... }
pseudo code:
  uint sceGsSyncPath(long param_1)
  ...
    uVar4 = REG_DMAC_1_VIF1_CHCR;
    while ((uVar4 & 0x100) != 0) { ... }
    uVar6 = _cfc2(in_vc13);
  • Remaining proof gaps: only one producer/executable verified; no CI job with the extension installed; the full npm test suite was not run (see below).

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

  • npm run check (typecheck, lint, format, knip, metadata, architecture guards) — passed.
  • npx vitest run src/ghidra/GhidraEeProfile.test.ts src/ghidra/GhidraMipsProfile.test.ts tests/boundary/filesystem/ghidraPspExtension.test.ts — 3 files, 128 tests passed.
  • npm run build — passed.
  • node scripts/rea.mjs decompile <SCES_511.90> sceGsSyncPath --provider ghidra with Ghidra 12.1.4 + extension v2.1.38 — succeeded in 1:51 min (output above).
  • Full npm test / check:pr — not run.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: real Ghidra 12.1.4 on Linux x64 (Bazzite), one target.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: same model as the PSP lane -- installed extension code runs inside Ghidra; REA fingerprints it (content identity, not a signature).

Author readiness

Human owner: @litterboks

  • 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.

🤖 Generated with Claude Code


🔄 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/5240 **Author:** [@litterboks](https://github.com/litterboks) **Created:** 10/19/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/ghidra-ps2-ee-profile` --- ### 📝 Commits (1) - [`07c0a78`](https://github.com/morluto/rea/commit/07c0a78abe8995ba38c080f4e347fab5e023570f) feat(ghidra): PlayStation 2 EE profile through ghidra-emotionengine-reloaded ### 📊 Changes **10 files changed** (+549 additions, -51 deletions) <details> <summary>View changed files</summary> ➕ `docs/ghidra-ps2.md` (+59 -0) 📝 `src/ghidra/GhidraAnalysisProfile.ts` (+26 -0) ➕ `src/ghidra/GhidraEeExtension.ts` (+59 -0) ➕ `src/ghidra/GhidraEeProfile.test.ts` (+123 -0) ➕ `src/ghidra/GhidraEeProfile.ts` (+96 -0) 📝 `src/ghidra/GhidraLauncher.ts` (+35 -0) 📝 `src/ghidra/GhidraProvider.ts` (+8 -2) 📝 `src/ghidra/GhidraProviderClient.ts` (+29 -0) 📝 `src/ghidra/GhidraPspExtension.ts` (+109 -49) 📝 `src/ghidra/GhidraPspProfile.ts` (+5 -0) </details> ### 📄 Description ## Summary PlayStation 2 retail executables are MIPS ELF32 files whose header declares the Emotion Engine (`EF_MIPS_MACH_5900`). Today every provider refuses them: the Ghidra lane stops at "Machine-specific MIPS variants, including PSP Allegrex, need a separately supported processor profile". This adds that profile, built the same way as the PSP lane: REA pins the language of a caller-installed extension ([ghidra-emotionengine-reloaded](https://github.com/chaoticgd/ghidra-emotionengine-reloaded), `r5900:LE:32:default`) and fingerprints it, but never installs it. No issue exists for this; the PSP lane (#1330) is the precedent the design follows. ## Problem and expected behavior `rea decompile <retail PS2 ELF> sceGsSyncPath --provider ghidra` fails with `architecture_unsupported`. With the extension installed under `$GHIDRA_INSTALL_DIR/Ghidra/Extensions/ghidra-emotionengine-reloaded`, the same call now resolves lane `ps2-elf32-exec-eabi64-r5900-v1` and returns pseudocode with the extension's MMIO register names and COP2 intrinsics. Without the extension it fails with `EE_EXTENSION_UNAVAILABLE` and an installation hint. ## Change and scope - `GhidraEeProfile.ts`: admission of exactly the ee-gcc declaration -- little-endian ELF32 `ET_EXEC`, `EF_MIPS_ARCH_3`, ABI `EABI64` or none, optionally `NOREORDER`, no other header bits, no ABI flags record, no GNU MIPS attributes; pinned language, profile parameters, result limitations. Everything else is refused, not inferred. - `GhidraEeExtension.ts`: the extension's fingerprint and resolution. - `GhidraPspExtension.ts`: the Allegrex inspection generalised into a processor-extension inspection parameterised by id, label, failure code and required files. PSP exports, behaviour and messages are unchanged (`tests/boundary/filesystem/ghidraPspExtension.test.ts` passes unmodified). - Wiring in the processor dispatcher, analysis profile, provider host check, provider client and launcher (pre-launch re-inspection), mirroring the PSP lane. - `docs/ghidra-ps2.md`. Not included: IRX modules, relocatable/shared images, ISO containers, overlays, non-Linux-x64 hosts, producers that write an ABI flags record. ## Contract and boundary impact - Semantic owner and earliest changed stage: Ghidra provider target admission (`ghidraProcessorUnsupportedReason`), then analysis-profile resolution. - Contribution scope fit and linked maintainer decision: static decompilation of a new processor family through an existing provider; no maintainer decision linked yet -- requested here. - CLI and MCP/tool-catalog contract: unchanged; new admitted targets and a new failure code `EE_EXTENSION_UNAVAILABLE`. - Provider, bridge, target-format, or platform compatibility: Ghidra only, Linux x64 only; bridge unchanged. - Evidence, artifact, provenance, or reconstruction contract: new profile parameters (`mips_support_lane`, `ee_extension` fingerprint, pinned language); results carry three EE limitations. - Target selection, authority, upstream behavior, and cleanup details: not applicable (static import, ephemeral project as before). - Generated metadata, package, or installation impact: none; the extension stays caller-installed. Expected effects: - [x] 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. ## Evidence and regression coverage - Tests added or updated: `src/ghidra/GhidraEeProfile.test.ts` (admission of the ee-gcc declaration, pinned language and parameters, refusal of ASE/other ISA/other ABI/undeclared bits/big-endian/non-EXEC/ABI-flags record/uninspected declaration, generic MIPS and PSP left to their lanes). - Base reproduction: on `main`, the same CLI call returns `architecture_unsupported` with the "Machine-specific MIPS variants" reason (observed with the published 6.7.0 and the fork's main). - User-visible output (abridged, executed against a retail `SCES_511.90`, `e_flags 0x20924000`, Ghidra 12.1.4, extension v2.1.38): ``` analysis_profile.parameters: language_id: "r5900:LE:32:default" language_selection: provider-pinned-v1 mips_support_lane: ps2-elf32-exec-eabi64-r5900-v1 ee_extension: { id: ghidra-emotionengine-reloaded, ghidra_version: 12.1.4, sha256: c339de37... } pseudo code: uint sceGsSyncPath(long param_1) ... uVar4 = REG_DMAC_1_VIF1_CHCR; while ((uVar4 & 0x100) != 0) { ... } uVar6 = _cfc2(in_vc13); ``` - Remaining proof gaps: only one producer/executable verified; no CI job with the extension installed; the full `npm test` suite was not run (see below). 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 - `npm run check` (typecheck, lint, format, knip, metadata, architecture guards) — passed. - `npx vitest run src/ghidra/GhidraEeProfile.test.ts src/ghidra/GhidraMipsProfile.test.ts tests/boundary/filesystem/ghidraPspExtension.test.ts` — 3 files, 128 tests passed. - `npm run build` — passed. - `node scripts/rea.mjs decompile <SCES_511.90> sceGsSyncPath --provider ghidra` with Ghidra 12.1.4 + extension v2.1.38 — succeeded in 1:51 min (output above). - Full `npm test` / `check:pr` — not run. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: real Ghidra 12.1.4 on Linux x64 (Bazzite), one target. - Package or release metadata impact: none. - Security, privacy, process, or containment review: same model as the PSP lane -- installed extension code runs inside Ghidra; REA fingerprints it (content identity, not a signature). ## Author readiness Human owner: @litterboks - [ ] 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. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <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#6832
No description provided.