fix(native): retain re-exported Mach-O library dependencies (#516)

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
This commit is contained in:
Rudy Mizrahi Celekli 2026-10-05 02:59:48 -04:00 committed by GitHub
parent 385445804a
commit 4a5673e1dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 202 additions and 1 deletions

View File

@ -139,7 +139,12 @@ const collectDependency = (
fields: Readonly<Record<string, string | number | null>>,
state: ParsedLoadCommands,
): void => {
if (!kind.startsWith("LC_LOAD_") && kind !== "LC_ID_DYLIB") return;
if (
!kind.startsWith("LC_LOAD_") &&
kind !== "LC_ID_DYLIB" &&
kind !== "LC_REEXPORT_DYLIB"
)
return;
state.dependencies.push({
path: stripOffsetSuffix(stringField(fields, "name")),
kind,

View File

@ -0,0 +1,40 @@
import { expect, it } from "vitest";
import { NativeMacOSProvider } from "../../../../src/native/NativeMacOSProvider.js";
import {
NativeFixtureRunner,
nativeFixture,
nativeMachoTarget,
} from "../../../fixtures/nativeCommands.js";
it("retains native re-export dependencies alongside ordinary and identity commands", async () => {
const runner = new NativeFixtureRunner({
otool: await nativeFixture("native-reexport/otool-load.txt"),
});
const client = new NativeMacOSProvider(runner, "darwin").createClient(
nativeMachoTarget("/owned/libOuter.dylib"),
);
const result = await client.execute("inspect_macho", {});
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.result).toMatchObject({
dependencies: {
exhaustive: true,
total: 3,
items: expect.arrayContaining([
expect.objectContaining({
kind: "LC_REEXPORT_DYLIB",
path: "@rpath/libLeaf.dylib",
}),
expect.objectContaining({
kind: "LC_ID_DYLIB",
path: "/owned/libOuter.dylib",
}),
expect.objectContaining({
kind: "LC_LOAD_DYLIB",
path: "/usr/lib/libSystem.B.dylib",
}),
]),
},
});
});

View File

@ -0,0 +1,14 @@
# Source-built re-export load command
Captured from the adjacent C sources using the macOS arm64 host Xcode tools:
```sh
xcrun clang -dynamiclib leaf.c -Wl,-install_name,@rpath/libLeaf.dylib -o libLeaf.dylib
xcrun clang -dynamiclib outer.c -Wl,-reexport_library,libLeaf.dylib -o libOuter.dylib
xcrun otool -l libOuter.dylib > otool-load.txt
```
The temporary outer-library path was replaced with `/owned/libOuter.dylib`.
The load-command fields are otherwise unmodified. The capture retains the real
re-export, ID, and ordinary libSystem dependency. It proves format parsing,
not Hopper or Ghidra behavior.

View File

@ -0,0 +1 @@
int owned_leaf(void) { return 9; }

View File

@ -0,0 +1,140 @@
/owned/libOuter.dylib:
Load command 0
cmd LC_SEGMENT_64
cmdsize 232
segname __TEXT
vmaddr 0x0000000000000000
vmsize 0x0000000000004000
fileoff 0
filesize 16384
maxprot 0x00000005
initprot 0x00000005
nsects 2
flags 0x0
Section
sectname __text
segname __TEXT
addr 0x0000000000000358
size 0x0000000000000008
offset 856
align 2^2 (4)
reloff 0
nreloc 0
flags 0x80000400
reserved1 0
reserved2 0
Section
sectname __unwind_info
segname __TEXT
addr 0x0000000000000360
size 0x0000000000000058
offset 864
align 2^2 (4)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
Load command 1
cmd LC_SEGMENT_64
cmdsize 72
segname __LINKEDIT
vmaddr 0x0000000000004000
vmsize 0x0000000000004000
fileoff 16384
filesize 416
maxprot 0x00000001
initprot 0x00000001
nsects 0
flags 0x0
Load command 2
cmd LC_ID_DYLIB
cmdsize 120
name /owned/libOuter.dylib (offset 24)
time stamp 1 Wed Dec 31 19:00:01 1969
current version 0.0.0
compatibility version 0.0.0
Load command 3
cmd LC_DYLD_CHAINED_FIXUPS
cmdsize 16
dataoff 16384
datasize 48
Load command 4
cmd LC_DYLD_EXPORTS_TRIE
cmdsize 16
dataoff 16432
datasize 32
Load command 5
cmd LC_SYMTAB
cmdsize 24
symoff 16472
nsyms 1
stroff 16488
strsize 16
Load command 6
cmd LC_DYSYMTAB
cmdsize 80
ilocalsym 0
nlocalsym 0
iextdefsym 0
nextdefsym 1
iundefsym 1
nundefsym 0
tocoff 0
ntoc 0
modtaboff 0
nmodtab 0
extrefsymoff 0
nextrefsyms 0
indirectsymoff 0
nindirectsyms 0
extreloff 0
nextrel 0
locreloff 0
nlocrel 0
Load command 7
cmd LC_UUID
cmdsize 24
uuid 6199BBEB-E87C-38C9-9857-9FAB706B2C3F
Load command 8
cmd LC_BUILD_VERSION
cmdsize 32
platform 1
minos 26.0
sdk 26.4
ntools 1
tool 3
version 1266.8
Load command 9
cmd LC_SOURCE_VERSION
cmdsize 16
version 0.0
Load command 10
cmd LC_REEXPORT_DYLIB
cmdsize 48
name @rpath/libLeaf.dylib (offset 24)
time stamp 2 Wed Dec 31 19:00:02 1969
current version 0.0.0
compatibility version 0.0.0
Load command 11
cmd LC_LOAD_DYLIB
cmdsize 56
name /usr/lib/libSystem.B.dylib (offset 24)
time stamp 2 Wed Dec 31 19:00:02 1969
current version 1356.0.0
compatibility version 1.0.0
Load command 12
cmd LC_FUNCTION_STARTS
cmdsize 16
dataoff 16464
datasize 8
Load command 13
cmd LC_DATA_IN_CODE
cmdsize 16
dataoff 16472
datasize 0
Load command 14
cmd LC_CODE_SIGNATURE
cmdsize 16
dataoff 16512
datasize 288

View File

@ -0,0 +1 @@
int owned_outer(void) { return 7; }