Files
AnyPS5/core/libs/nid/src/BinaryPatcherFactory.cpp
T
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

20 lines
768 B
C++

#include <nid/BinaryPatcherFactory.hpp>
#include <nid/ElfPatcher.hpp>
#include <nid/MachONidPatcher.hpp>
#include <nid/PeNidPatcher.hpp>
#include <stdexcept>
namespace Nid {
std::unique_ptr<IBinaryPatcher> MakePatcher(const std::vector<std::uint8_t>& binary) {
if (binary.size() >= 4 && binary[0] == 0x7f && binary[1] == 'E' && binary[2] == 'L' && binary[3] == 'F')
return std::make_unique<ElfNidPatcher>();
if (binary.size() >= 2 && binary[0] == 'M' && binary[1] == 'Z')
return std::make_unique<PeNidPatcher>();
if (binary.size() >= 4 && binary[0] == 0xcf && binary[1] == 0xfa && binary[2] == 0xed && binary[3] == 0xfe)
return std::make_unique<MachONidPatcher>();
throw std::runtime_error("unrecognized binary format");
}
}