* feat(ghidra): admit bounded PSP ELF through installed Allegrex Build on merged generic MIPS without weakening its policy. Bind caller-installed processor files into the analysis profile, check them again before launch, force and verify PSP language selection, retain limitations, and extend the public CLI/MCP verifier with source-owned PSP and target-switching checks. Local actual focused Vitest: 102 passed, one existing permission skip. Hosted static and real-provider results are pending. * fix(ghidra): validate PSPSDK ABI records in PSP admission * test(ghidra): bind PSP ABI verification to snapshot profiles * test(ghidra): declare independent PSP ABI reader contract * test(ghidra): retain the PSP fixture discriminated type * test(ghidra): contextually type PSP metadata as the MIPS target variant * test(ghidra): keep carved firmware checks scoped to generic MIPS fixtures * style(ghidra): format PSP language-override guard * style(test): format PSP language override regressions * fix(ghidra): bound PSP extension enumeration before allocation --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
106 lines
5.7 KiB
Markdown
106 lines
5.7 KiB
Markdown
# PSP static ELF analysis through Ghidra
|
|
|
|
This specialization builds on [generic MIPS support](ghidra-mips.md) for
|
|
[#1330](https://github.com/morluto/rea/issues/1330). It reuses REA's existing
|
|
CLI/MCP, Ghidra bridge, Evidence and snapshot workflows. Allegrex instructions,
|
|
PSP loading and calling conventions remain owned by
|
|
[ghidra-allegrex](https://github.com/kotcrab/ghidra-allegrex).
|
|
|
|
## Initial boundary
|
|
|
|
The initial profile is limited to Linux x64, little-endian ELF32 `ET_EXEC`,
|
|
`EM_MIPS` and the PSPSDK declaration `e_flags=0x10a23001`. Those bits declare
|
|
MIPS II, Allegrex, EABI32 and NOREORDER; they are not proof of every instruction's
|
|
semantics. The profile also requires an inspected version-0 MIPS ABI flags
|
|
record declaring ISA level 2/revision 0, 32-bit GPR and CPR1, no CPR2,
|
|
single-precision hard float (`fpAbi=2`), no ISA extension or ASEs,
|
|
`flags1=1` and `flags2=0`. These are the declarations independently reported by
|
|
PSPDEV v20261001's GNU readelf 2.44 and its 24-byte section dump. Missing,
|
|
uninspected, contradictory and other producer declarations are refused.
|
|
The PSP profile is not an exception to the generic MIPS32r2/o32 policy; that
|
|
separate gate is unchanged. Profile revision v2 records this corrected boundary.
|
|
|
|
PRX, relocatable/shared images, PBP/ISO/CSO containers, runtime emulation and live
|
|
code overlays are outside this first profile. Other hosts and flag combinations
|
|
are not silently admitted. File names do not identify a PSP target.
|
|
|
|
## Bring your own compatible extension
|
|
|
|
Install the extension in the selected Ghidra distribution at
|
|
`$GHIDRA_INSTALL_DIR/Ghidra/Extensions/ghidra-allegrex`, with its
|
|
`Module.manifest`, `extension.properties`, language files and loader JARs.
|
|
User-home installations are not searched because REA uses an isolated analysis
|
|
home. REA never downloads, installs, rebuilds or vendors the extension.
|
|
|
|
The published compatibility experiment used Ghidra **12.1.3**, extension
|
|
**v21.4**, PSPDEV **v20261001** and JDK 21. New public-provider results must be
|
|
reported separately from that historical bridge experiment. The extension's
|
|
`version` property declares its compatible **Ghidra version**, not its release
|
|
tag; the property must match the selected installation. Other same-version
|
|
builds are not described as independently verified merely because they pass
|
|
this metadata check. A malformed or unloadable extension still fails real import.
|
|
|
|
REA fingerprints installed extension files before resolving the analysis
|
|
profile and checks that identity again immediately before launch. Symlinks,
|
|
nonregular files, missing components and incompatible metadata are refused.
|
|
Inspection is bounded to 1,024 entries, 16 directory levels and 64 MiB, with
|
|
streamed file hashing and 64 KiB properties. Rebuilds or content changes yield a
|
|
different profile; an old snapshot is not silently reused with the new profile.
|
|
This is content identity, not a signature or a sandbox for installed code.
|
|
Do not modify the Ghidra installation while a session is running.
|
|
|
|
## Ordinary public interfaces
|
|
|
|
```bash
|
|
rea analyze /absolute/path/to/psp.elf --provider ghidra --json
|
|
rea function /absolute/path/to/psp.elf function_name --provider ghidra --json
|
|
```
|
|
|
|
MCP uses `open_binary` with an absolute path and `provider_id: "ghidra"`, then
|
|
ordinary inventory and function operations. The loader is explicitly
|
|
`PspElfLoader`, language `Allegrex:LE:32:default`, compiler `default`. The
|
|
handshake must confirm the language and compiler before serving observations.
|
|
Missing prerequisites return `PSP_EXTENSION_UNAVAILABLE` with an installation
|
|
remedy; no provider fallback or automatic installation occurs.
|
|
|
|
Evidence retains the `mips` architecture family and its PSP-specific profile,
|
|
including extension content identity. It also carries the VFPU and static-only
|
|
limitations. The extension does not model VFPU prefix effects completely;
|
|
nonempty decompiled code is not proof of correct vector behavior. Existing
|
|
session-local metadata editing does not change executable bytes or turn a
|
|
snapshot into a persistent Ghidra project.
|
|
|
|
## Verification
|
|
|
|
Use the existing real MIPS verifier with its PSP option. Required tools are
|
|
caller-supplied `make`, `psp-config`, `psp-gcc`, `psp-readelf`, `psp-objdump`,
|
|
`PSPDEV`, `GHIDRA_INSTALL_DIR` and a compatible `JAVA_HOME`.
|
|
|
|
```bash
|
|
npm run build:cached
|
|
node scripts/verify-real-ghidra-mips.mjs --psp
|
|
# In a disposable installation without Allegrex, test actual public refusals:
|
|
node scripts/verify-real-ghidra-mips.mjs --psp-missing-extension
|
|
# Generic MIPS must remain generic with Allegrex installed:
|
|
npm run verify:ghidra:mips
|
|
```
|
|
|
|
The generic verifier also exercises a section-truncated firmware fixture. That
|
|
check uses generic MIPS symbols and language expectations and runs only in generic
|
|
mode; the PSP report explicitly records carved-PSP coverage as not run.
|
|
|
|
The maintained PSP fixture builds from `tests/conformance/psp/`, never executes,
|
|
and is independent of commercial game data. PSP GNU tools supply ELF/ABI,
|
|
raw ABI-record, symbol and encoding observations; REA's parsed target and saved
|
|
snapshot must agree with the independent ABI declaration. Public CLI/MCP must
|
|
recover known functions, a direct
|
|
call, the immediate `0x1234`, BITREV, a global word and a marker. The verifier
|
|
checks observed loader/language, original bytes, Evidence, snapshot reopening,
|
|
and an A-B-A target switch with different global contents at the same address.
|
|
A snapshot for A must not open B. Cleanup must finish before success is reported.
|
|
|
|
These checks are selected static facts, not full behavioral equivalence, VFPU
|
|
semantics or arbitrary PSP compatibility. Independently published PSP binaries
|
|
are supplemental calibration targets after payload classification and license
|
|
review; unsupported PRX/PBP must not count as a successful static-ELF case.
|