Repository navigation
feat(nid): patch NIDs in Mach-O libraries - #2247
Merged
Merged
Conversation
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.
Open
9 tasks done
9 tasks done
This was referenced Oct 9, 2026
Contributor
|
Native Windows run, since no Windows results were posted. Setup: Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Head
🤖 Addressed by Claude Code |
Collaborator
|
Checked the build and ctest scoped to |
SleglJan
pushed a commit
to SleglJan/AnyPS5
that referenced
this pull request
Oct 10, 2026
feat(nid): patch NIDs in Mach-O libraries
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
nid_patcherturns the_nid_postfixnames of a library into NIDs for ELF and PE. This adds Mach-O, so that a library built on macOS gets its NIDs too. It is the piece of the macOS port thatninja libsneeds there; the build changes that use it come in separate PRs. Nothing changes for ELF and PE.__LINKEDIT, which has to end the file, and a signed image is refused._nid_postfixor_nid_no_patchkeep their names, because dyld coalesces those across images by name..prxdylib that are guest facing (a_nid_postfixname or ansceprefix) are patched in place. A name that would grow, or that shares storage with another import, is an error. An image that uses bind opcodes instead of chained fixups is refused.--preserve-exportsreads a reference Mach-O the way it reads ELF and PE references.Tested
nid_patcher_macho: builds small Mach-O dylibs byte by byte and runsnid_patcheron them. It checks the rebuilt export trie (including a weak export that must stay), the patched and untouched chained imports, a trie that grows and is appended to__LINKEDIT,--preserve-exports, and the three refusals (signed image, bind opcodes, an import NID longer than its name). It needs no macOS. I also ran it against two copies of the patcher with a deliberate break each (no import patching, weak exports patched), and both fail it.cmp, and the port'spatched_librariestest loads them all.ctest, run by manual dispatch on my fork: https://github.com/mugurc/AnyPS5/actions/runs/37931715161 (Linux 508 of 508, Windows 517 of 517,nid_patcher_machoincluded). The relinker jobs on a pull request do not buildnid_patcher, so they do not cover this change.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)