Commit Graph
5 Commits
Author SHA1 Message Date
MarcZX10 3948547d77 fix(nid): cap Mach-O export trie nesting depth
ParseTrieNode recursed once per trie level with no limit. A chain of single-child nodes about 200k levels deep (roughly 1 MB of trie) overflowed the stack, so nid_patcher crashed instead of reporting a malformed image.

Throw a runtime_error once the depth passes 1024 levels. Every level adds at least one byte to the exported name, so the bound only rejects names longer than 1024 bytes, which no real export has.
2026-11-02 08:53:33 +00:00
MarcZX10 0eb797bed8 refactor(nid): pass export trie depth through ParseTrieNode
ParseTrieNode recursed once per trie level without carrying how deep it was. Thread a depth argument through the recursion so the next change can bound it. Behaviour is unchanged.
2026-11-02 08:53:33 +00:00
JJenkxandClaude Opus 5.5 bf9079e1cb fix(nid): rebuild Mach-O library import names when a NID is longer
A library's chained import names were rewritten in place, so an import
whose NID is longer than its name failed: _sceNetRecv is 11 bytes, its
NID with the underscore 12. When any selected import would grow, the
library now goes through the symbol-pool rebuild that --exec mode
already uses; libraries whose NIDs all fit keep the in-place path and
their size. Signed images still refuse to grow linkedit data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 14:19:37 -04:00
boykopovar 1cf017b189 feat(nid): add executable import patching with optional sce filter 2026-10-25 15:03:02 +03:00
mugurc f3c514744b feat(nid): patch NIDs in Mach-O libraries
nid_patcher turns the _nid_postfix names of a library into NIDs for ELF
and PE. A library built on macOS is a Mach-O dylib, whose exports are in
a dyld export trie and whose imports are in the chained fixups, so it
gets its own patcher.

- The export trie is read, every exported C name (without Mach-O's
  leading underscore) is resolved to its NID, and the trie is rebuilt the
  way ld64 lays it out: the offsets are uleb128, so the layout is repeated
  until it is stable. A trie that no longer fits is appended to
  __LINKEDIT, which has to end the file, and a signed image is refused.
- Weak definitions that are not marked _nid_postfix or _nid_no_patch keep
  their names: dyld coalesces those across images by name.
- In the chained imports, names bound to a .prx dylib that are guest
  facing (a _nid_postfix name or an sce prefix) are patched in place; a
  name that would grow, or that shares storage with another import, is an
  error. Images that use bind opcodes instead of chained fixups are
  refused.
- ExportExclusions reads the exports of a reference Mach-O, so the
  exclusion list works for libraries built on macOS as well.
2026-10-09 15:40:29 +03:00