Loader requirements

What a loader has to handle to run an obSCEne module, written from the module side. It applies to any loader that runs one; none of it is specific to a single emulator.

Module and payload shapes

Two formats share a file extension:

module payload
e_type 0xFE10 (executable) / 0xFE18 (library) ET_DYN (3)
Dynamic tags DT_SCE_*, 0x610000xx standard DT_*
Tables live in PT_SCE_DYNLIBDATA ordinary sections
Symbol names <nid>#<lib>#<mod> plain
Dependencies DT_SCE_NEEDED_MODULE DT_NEEDED

They are separate formats, not variations on one. e_type alone tells them apart and is available before anything else is parsed, so a loader decides once at load and dispatches to one of two code paths. Branching inside shared code leaves every later function re-deriving which format it is in. MODULE-FORMAT.md has the table conventions.

Dynamic table order

Four tags carry a string-table offset in their value rather than a pointer: the module's own name, its exported library, and the name of every module and library it imports from.

A loader that resolves those offsets while walking the table faults on a module that declares them before DT_SCE_STRTAB. Two ways to handle it:

Relocation table pointers

DT_SCE_JMPREL holds an offset and DT_SCE_PLTRELSZ a size. Swapped, offset + size sums to the same place, so consistency arithmetic cannot catch it, and relocations are read from the start of the vendor segment, which is the string table. A relocation type that looks like ASCII points at a table pointer that is really a length.

Error reporting

A loader that faults on a malformed module and one that faults inside a correct one produce the same output:

LoadModuleToMemory: program entry addr ...: 0x00000000051d5000
Unhandled Exception code 0xc0000005

That is a fault inside the loader with the module's entry point printed one line above, and it reads as "it started and crashed". A refusal that names the field and the expectation turns a bisection into a bug report:

Attempting to add too many segments!
Unable to find library and module
Not implemented (jmprel_type != DT_RELA)
Not implemented (program->dynamic_info->jmprela_table == nullptr)

Loader checklist

What obSCEne provides

A module that resolves its imports by NID and calls platform functions one at a time, announcing each before the call. A try record with no matching res names the call that did not return. OUTPUT.md is the report format.

obscene-tool diff compares two runs and reports what got worse. A run where everything fails and nothing changed is a clean exit.

make module builds it; ARTIFACTS.md lists every build and its loader.