DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=./foo/my.dylib ./bar/exec returns 1 w/o 运行 我的可执行文件

DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=./foo/my.dylib ./bar/exec returns 1 w/o running my executable

在 macOS 10.12.6 上,我有一个共享库和一个可执行文件(都是我自己构建的,SIP 不应该应用 AFAIK),我想为可执行文件预加载库。它失败了,return 代码为 1,否则静默:

$ ./bar/exec
<does stuff>
$ DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=./foo/my.dylib ./bar/exec
<returns immediately>
$ echo $?
1
# 1 is not an explicitly returned value from ./bar/exec

如果我添加 DYLD_PRINT_LIBRARIESDYLD_PRINT_LIBRARIES_POST_LAUNCH 选项,如 man dyld 中所述,它们都表明库和可执行文件都已成功加载:

...
dyld: loaded: /full/path/to/exec
dyld: loaded: ./foo/my.dylib
...

如果我尝试 运行 在 dtruss 或 lldb 中预加载可执行文件,它 运行s,没有预加载库。这可能是有道理的,因为这些工具受 SIP 保护。

我该如何调试它?

更新

感谢@macmoonshine,我能够通过从 LLDB 本身而不是 LLDB 设置预加载环境,在 lldb 下重现 return 代码 1 出口:

(lldb) env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=./foo/my.dylib
(lldb) run
...
Process 24130 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x00007fffc8aac310 libsystem_kernel.dylib`__exit
...
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
  * frame #0: 0x00007fffc8aac310 libsystem_kernel.dylib`__exit
    frame #1: 0x000000010008ebac my.dylib`my_init at my.c:86 [opt]
    frame #2: 0x0000000100018a1b dyld`ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 385
    frame #3: 0x0000000100018c1e dyld`ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 40
    frame #4: 0x00000001000144aa dyld`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 338
    frame #5: 0x0000000100013524 dyld`ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 138
    frame #6: 0x00000001000135b9 dyld`ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 75
    frame #7: 0x0000000100005434 dyld`dyld::initializeMainExecutable() + 125
    frame #8: 0x00000001000098c6 dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 3966
    frame #9: 0x0000000100004249 dyld`dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) + 470
    frame #10: 0x0000000100004036 dyld`_dyld_start + 54

这是调试的开始。

您可以在 lldb 中 运行 您的代码,您可以在其中使用 env 命令设置环境:

env DYLD_FORCE_FLAT_NAMESPACE=1
env DYLD_INSERT_LIBRARIES=./foo/my.dylib
run

使用 lldb 你可以 运行 你的程序直到它崩溃。如果异常存在exit()(或_exit()),则应设置符号断点b exitb _exit。所以你有机会在失败的地方获得回溯。