Files
rea/docs/ghidra-ppc.md
Ariel Fikru Avicenna cab78de506 feat(ghidra): analyze GameCube/Wii DOL executables through Ghidra (#6240)
* feat(domain): parse and validate GameCube/Wii DOL headers

Add a pure parser for the 0x100-byte DOL header (7 text and 11 data
slots, BSS, entry point). Used slots must lie after the header and
inside the file and the 0x80000000..0x81800000 load window; text slots
are 4-byte aligned; sections may not overlap in memory or in the file;
the entry point must be inside a text section. BSS may overlap data
sections, as .sdata/.sdata2 do in shipped DOLs.

Refs #1741

* feat(binary): admit caller-selected GameCube/Wii DOL targets

* feat(ghidra): import GameCube/Wii DOL targets through a section-map pre-script

* test(ghidra): cover DOL launcher arguments, attestation and raw profile digests

* test(ghidra): add the real verify:ghidra:dol lane and DOL docs

* fix(ghidra): read only the DOL header and section ranges instead of the whole file

* test(ghidra): derive DOL lane addresses from readelf and admit Gekko from the install catalog

* fix(ghidra): attest DOL block permissions, space, overlay and load state

* fix(ghidra): keep load-image permissions optional for older inspections

* fix(contracts): accept DOL targets in binary_session output

* fix(ghidra): adapt the DOL lane to the current upstream address schema

Validate DOL load-image coordinates with the upstream observed-address
schema, drop a duplicate import left by the rebase, and re-pin the raw
profile digests to the unmodified upstream resolver.

* fix(ghidra): preserve bridge inventory symbol provenance

* fix(ghidra): align DOL verification with shared workflow contracts

* feat(domain): parse and validate GameCube/Wii DOL headers

Add a pure parser for the 0x100-byte DOL header (7 text and 11 data
slots, BSS, entry point). Used slots must lie after the header and
inside the file and the 0x80000000..0x81800000 load window; text slots
are 4-byte aligned; sections may not overlap in memory or in the file;
the entry point must be inside a text section. BSS may overlap data
sections, as .sdata/.sdata2 do in shipped DOLs.

Refs #1741

* feat(binary): admit caller-selected GameCube/Wii DOL targets

* feat(ghidra): import GameCube/Wii DOL targets through a section-map pre-script

* test(ghidra): cover DOL launcher arguments, attestation and raw profile digests

* test(ghidra): add the real verify:ghidra:dol lane and DOL docs

* fix(ghidra): read only the DOL header and section ranges instead of the whole file

* test(ghidra): derive DOL lane addresses from readelf and admit Gekko from the install catalog

* fix(ghidra): attest DOL block permissions, space, overlay and load state

* fix(ghidra): keep load-image permissions optional for older inspections

* fix(contracts): accept DOL targets in binary_session output

* fix(ghidra): adapt the DOL lane to the current upstream address schema

Validate DOL load-image coordinates with the upstream observed-address
schema, drop a duplicate import left by the rebase, and re-pin the raw
profile digests to the unmodified upstream resolver.

* docs(ghidra): qualify the DOL memory window

* refactor(ghidra): own DOL BSS ranges in the parsed header

* docs(ghidra): record real DOL workflows and task costs

* docs(ghidra): record final DOL integration verification

* fix(mcp): share the native procedure search row contract

* docs(ghidra): record public procedure search verification

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 17:56:31 +08:00

4.4 KiB

PowerPC ELF analysis through Ghidra

This lane extends native ELF analysis to 32-bit big-endian PowerPC; it does not execute PowerPC code. It is the first milestone of #1741. GameCube/Wii DOL executables are covered by GameCube DOL analysis. PPC64 and other PowerPC variants remain separate follow-ups.

Admission boundary

ELF EM_PPC (20) is retained as the provider-neutral powerpc family. The target also retains class, byte order, e_type and raw e_flags. Recognition does not mean every provider or PowerPC variant is supported. EM_PPC64 (21) is not recognized as this family.

The Ghidra lane admits ELF32 ET_EXEC, big endian. ELF64, little-endian, relocatable and shared objects are refused with a specific unsupported constraint. EF_PPC_EMB declares an embedded variant and is refused; the remaining e_flags bits only declare relocation conventions and do not change instruction decoding.

Bound language

Ghidra's ELF loader selects PowerPC:BE:32:e500:default for a plain EM_PPC header with e_flags 0. e500 is the embedded Book-E variant whose SPE unit replaces the classic floating-point unit, so it misinterprets ordinary 750-family code. Nothing in the header distinguishes the two.

The lane therefore imports with PowerPC:BE:32:default and compiler spec default, commits that choice in the analysis profile as language_selection: "provider-pinned-v1", and checks the language Ghidra reports after import. A different language set through REA_GHIDRA_LANGUAGE_ID (and optionally REA_GHIDRA_COMPILER_SPEC_ID) replaces the lane default and is admitted against the installed language catalog as usual; for example PowerPC:BE:32:e500 for genuine e500 code.

PowerPC header facts are committed in the analysis profile so interpretation changes invalidate profile-bound snapshots. The support-lane identity is versioned independently of file identity. Evidence, lifecycle outputs and saved snapshots preserve the powerpc family. Hopper and IDA adapters do not implicitly gain PowerPC support. Windows Ghidra P0 remains PE x86/x86-64 only.

Use

With a caller-installed Ghidra and compatible JDK on a supported Linux/macOS host:

rea analyze /absolute/path/to/ppc.elf --provider ghidra --json
rea function /absolute/path/to/ppc.elf function_name --provider ghidra --json

MCP uses the existing tools, including open_binary with an absolute path and provider_id: "ghidra". No PowerPC-specific tool catalog or emulator is introduced.

Verification

The source-owned freestanding fixture is tests/conformance/c/ppc.c. The optional cross-target lane requires a caller-supplied Clang with the PowerPC target, LLD, GNU readelf, Ghidra and its compatible JDK; ordinary host-native checks do not acquire these tools. REA_PPC_CLANG selects Clang and REA_PPC_READELF selects GNU readelf (for example /opt/homebrew/opt/binutils/bin/readelf on macOS). These are test-time prerequisites, not REA runtime providers.

GHIDRA_INSTALL_DIR=/absolute/path/to/ghidra npm run verify:ghidra:ppc

The lane compiles the fixture for a 750-family core (-mcpu=750) and never executes it. GNU readelf independently supplies header facts and symbol addresses, compared with the production REA target resolver before provider startup. Its version, bounded command output and selected tool path are retained in the verification report. The parser deliberately recognizes only this fixture's GNU output, rejecting missing, ambiguous or unexpected fields rather than substituting defaults.

Existing public MCP operations check Ghidra's observed language and compiler specification and loaded-file hashes; an e500 import fails the lane. The source-owned ppc-probe.S supplies fixed addi and conditional-branch encodings: verification checks bytes, length, immediate and direct destination, independent of decompiler variable names. Global and string bytes are checked at independently reported symbol addresses.

CLI/MCP discovery and decompilation, direct calls, target/profile/Evidence identity, snapshot round-trip and final process cleanup remain covered. Pseudocode presence is a liveness check, not proof of semantic equivalence. Instruction decoding and reader agreement do not establish runtime or complete floating-point semantics. Parser/profile tests are narrower checks, not substitutes for this real-provider run. Report the actual lanes run and leave unexecuted verification pending.