告诉 'ld' dyld_stub_binder 不再在 libSystem.dyld 中,而是在 libSystem.B.dyld 中

Tell 'ld' dyld_stub_binder is no longer in libSystem.dyld but in libSystem.B.dyld

我正在尝试 re-create Launchpad 可执行文件,到目前为止一切似乎都正确,除了我在 运行 ld:

时收到此警告

Assembling/Linking 与:

as myprogram.s -o myprogram.o
ld myprogram.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -o myprogram

ld: symbol dyld_stub_binder not found (normally in libSystem.dylib).  Needed to perform lazy binding to function _CoreDockSendNotification for architecture x86_64

这是我的代码(抱歉 NASM 伙计们,这里是 AT&T 语法):

.section __DATA, __const
.section __TEXT, __text
.globl _start
_start:
pushq %rbp
movq %rbp, %rsp
lea lpToggle_cfstring_(%rip), %rdi
xor %esi, %esi
callq _CoreDockSendNotification
mov %rax, %r14
xor %rdi, %rdi
mov [=15=]x2000001, %rax
syscall

.section __TEXT,__cstring,cstring_literals
lpToggle: .asciz    "com.apple.launchpad.toggle"
.section __DATA,__cfstring
lpToggle_cfstring_:
    .quad   ___CFConstantStringClassReference
    .long   1992                    
    .space  4
    .quad   lpToggle
    .quad   26 

我已经更新到最新版本的 xcode 和命令行工具,我尝试将 _start 更改为 _main,我尝试 link libSystem.B.dyld 直接(有和没有 '.dyld' 扩展名):

ld lp.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -L/usr/lib/ -llibSystem.B.dyld -o lp

ld lp.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -llibSystem.B.dyld -o lp

ld lp.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -o lp -l/usr/lib/libSystem.B.dyld

ld lp.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -o lp -libSystem.B.dyld

我得到:

ld: warning: directory not found for option '-L/usr/lib/ -llibSystem.B.dyld'

ld: warning: directory not found for option '-l/usr/lib/libSystem.B.dyld'

ld: warning: library not found for option '-l/usr/lib/libSystem.B.dyld'

取决于我尝试哪一个。

我什至尝试直接从 /Applications/Xcode.app/Contents/Developer/usr/bin 目录使用 ld 来查看新旧

之间是否存在 symlink 问题

我使用 lldb 转储了 libSystem.dyld 的符号表,果然包含以下行:

`[  108] 108 X Undefined 0x0000000000000000 0x0000000000000000 0x00010000 dyld_stub_binder`

表示它有一个和108index/user idX表示它是外部定义的(可能是libSystem.B), Undefinedtype,'0x0' 的 'File Address/Value' 没有 Load Address,以及 0x00010000 的标志。

我在 Hopper 中加载了 Launchpad 可执行文件以查看它发生了什么,但没有太大帮助(除了它告诉我 dyld_stub_binder 在 libSystem.B.dyld 中)。

不确定这是否相关,但在实际的 Launchpad header 中包含:

                         ; Load Command 4
                         ; 
    0000000100000410     struct __macho_dyld_info_command {
                             LC_DYLD_INFO_ONLY,   // LC_DYLD_INFO or LC_DYLD_INFO_ONLY
                             0x30,                // sizeof(struct dyld_info_command)
                             0x2000,              // file offset to rebase info 
                             0x8,                 // size of rebase info  
                             0x2008,              // file offset to binding info  
                             0x40,                // size of binding info 
                             0x0,                 // file offset to weak binding info  
                             0x0,                 // size of weak binding info 
                             0x2048,              // file offset to lazy binding info
                             0x20,                // size of lazy binding infs
                             0x2068,              // file offset to lazy binding info
                             0x20                 // size of lazy binding infs
                         }


                        ;Load command 7

00000001000004a8         struct __macho_dylinker_command {
                             LC_LOAD_DYLINKER,  // LC_ID_DYLINKER, LC_LOAD_DYLINKER or LC_DYLD_ENVIRONMENT
                             0x20,  // includes pathname string
                             0xc    // dynamic linker's path name (should be 12)
                         }
00000001000004b4         db         "/usr/lib/dyld", 0
00000001000004c2         db  0x00 ; '.'
00000001000004c3         db  0x00 ; '.'
00000001000004c4         db  0x00 ; '.'
00000001000004c5         db  0x00 ; '.'
00000001000004c6         db  0x00 ; '.'
00000001000004c7         db  0x00 ; '.'   

_stub_helper 部分(看起来像某种 infinite-ish 循环,完全跳过了中间的 4 条指令):

0000000100000f80   lea,  qword [dyld_stub_binder_100001000+8]; CODE XREF=0x100000f95
0000000100000f87   push  r11
0000000100000f89   jmp   qword [dyld_stub_binder_100001000] ; dyld_stub_binder
0000000100000f8f   db         0x90
0000000100000f90   push       0x0
0000000100000f95   jmp        0x100000f80

__DATA__nl_symbol_ptr 部分:

0000000100001000         dq  dyld_stub_binder  ; DATA XREF=0x100000f89
0000000100001008         dq  0x0000000000000000 ; DATA XREF=0x100000f80

External Symbols 段中:

                 dyld_stub_binder:
0000000100005010         db  0x00 ; '.' ; in /usr/lib/libSystem.B.dylib, CODE XREF=0x100000f89DATA XREF=dyld_stub_binder_100001000
0000000100005011         db  0x00 ; '.'
0000000100005012         db  0x00 ; '.'
0000000100005013         db  0x00 ; '.'
0000000100005014         db  0x00 ; '.'
0000000100005015         db  0x00 ; '.'
0000000100005016         db  0x00 ; '.'
0000000100005017         db  0x00 ; '.'

更有趣的是如果我用gcc编译:

gcc -arch x86_64 -e _start -framework Foundation -framework ApplicationServices lp.s

它将毫无问题地构建,但在 运行 时间的某个时候会出现段错误。我说在某些时候是因为如果我用 lldb a.out 加载它并执行 run 命令,它会正常执行,没有段错误。所以很难找出到底发生了什么。我的直觉是 lldb 将我的应用程序指向 正确的 dyld_stub_binder但我可能是错的。

然而,如果我 运行 sudo ./myfilegcc 版本上 运行 完全没问题。 gcc 在做什么而 ld 不是?还是 as 命令中的内容?

我对使用核心 macOS 程序集还是比较陌生,所以任何指示都会有所帮助!

P.S。我也尝试了 -no_weak_imports 但那也不起作用

您的 ld myprogram.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -o myprogram 缺少 -l libSystem.B 库的搜索选项。
添加以下任一项:

-lsystem.b
-lsystem
-lc
-lm
-ld

所有都是同义词,可以解决缺少的 LC_LOAD_DYLIB(libSystem.B.dylib) 加载命令。顺便说一句,你的程序有效:-)