The dynamic table, and the whole stack on genuine material

selfish-elf now reads the table a loader actually reads: both tag conventions, the string and symbol tables, and the vendor import lists. 65 tests across the workspace, clippy clean under -D warnings.

Container::to_elf completes the pair - reassembling a scattered executable is the inverse of building one, and both live in the crate together so neither can drift.

The stack runs end to end on a genuine vendor library:

package -> filesystem -> libc.prx -> container -> ELF -> dynamic table
  49 dynamic entries, legacy convention, 2676 symbols
  libSceFios2, libSceLibcInternalExt, libSceSysmodule, libkernel

Every container the reader had seen before this was one its own writer produced.

Surprise: there are two vendor tag ranges, and each project knew one

The module and library tables have vendor tags in both conventions - different ones. Legacy puts them at 0x0D-0x19, current at 0x43-0x49. A reader built from retail material sees only the high range; a writer targeting loaders emits only the low one.

The first version of this crate used the high numbers for both. Reading a module with 352 import libraries, it reported zero - no error, no malformed data, just an empty result, because that is what looking up the wrong tag number always produces.

Two tests had to be corrected rather than the code: both asserted the conventions share those tags. One is now assert_ne! and tests the distinction rather than restating the bug. (D013)

Neither project could have found this alone. Each side's numbers are right for what it does. Only putting them together shows there are two ranges - which is the clearest justification this repository has produced for its own existence.