Skip to main content
Print

PSP PRX Relocation and GP/Import/Export Identity

Type: REFERENCE   Status: MAINTAINED   Scope: PRX segments, PSPREL/PSPREL2 relocation layers, module metadata, GP-relative state, NID stubs, and address identity.   Last reviewed: 2026-08-11

PRX translation is a provenance problem before it is a code-generation problem. One value can be a file offset, a segment-relative virtual address, a relocated guest address, a module-relative identity, or a final host pointer. Losing those distinctions makes imports, callbacks, and relocation diagnostics impossible to audit.

Public PRX structure

The PSP Developer Wiki PRX File Format documents the PSP-specific PT_SCE_PSPREL and PT_SCE_PSPREL2 segments, module header fields, segment addresses/sizes, entry and module-info offsets, and BSS size. It explicitly notes that PSPREL2 is compressed and that the page documents the first revision only; that limitation matters for a fail-closed parser.

The PSPDEV PRX module guide provides the exact public build-side relationship between export tables, NIDs, resident data, import stubs, module_start/module_stop, and psp-fixup-imports. The surviving YAPSPD documentation is useful historical context for ELF/PRX sections, but should not override a current source or a contradicted field description.

file bytes -> ELF/PRX segments -> module-relative identity<br>                                   |<br>relocations: HI16/LO16, jump/data, GP-relative, import stubs<br>                                   |<br>relocated guest address -> canonical (module, offset) -> host target
Source-owned relocation identity flow. Every conversion is explicit and reversible for diagnostics.

Module info, GP, and NID tables

Keep module info, segment bases, GP value, import/export bounds, and BSS as structured metadata. A .lib.stub record couples a library name, flags/count, entry size, NID table address, and stub code/table address; NID entries and stubs are positional only after the spans and entry sizes pass checked validation. Exports are evidence of an interface, not automatically clean function starts.

$gp is PSP small-data state. It is not the host compiler’s global pointer. A module transition, callback, thread entry, or import call can require a different GP context. Preserve module ownership through the call boundary.

Fail-closed relocation handling

Parse with checked arithmetic: segment index, record count, compressed-stream limits, patch width, target range, HI16/LO16 pairing, and import/export span must all be validated before a write. Keep raw encoded value, relocated guest target, canonical module identity, and host target as separate fields. A malformed or ambiguous record should remain visible as a diagnostic, not be guessed into a function.

Nakagawa’s current importer and code-generation implementation are anchored in tools/imports.py and tools/codegen.py. These commit-pinned links are implementation citations, not claims that every PRX feature is supported by the runtime.

Safe parser tests

Start with synthetic ELF/PRX records: one valid HI16/LO16 pair, one jump relocation, one GP-relative relocation, one import table with a mismatched span, one BSS overflow, and one compressed stream that ends mid-record. Assert rejection before mutation and preserve a diagnostic that names the module-relative identity. Keep retail modules and decrypted bytes out of public artifacts.

Sources

Table of Contents