I am trying to re-create the Launchpad executable and so far everything seems right except I get this warning when I run ld
:
Assembling/Linking with:
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
Here is my code (sorry NASM guys, AT&T syntax here):
.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 $0x2000001, %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
I have updated to the latest version of of both xcode and the command line tools, I have tried changing _start
to _main
, I have tried to link libSystem.B.dyld directly (both with and without the '.dyld' extension):
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
To which I get:
ld: warning: directory not found for option '-L/usr/lib/ -llibSystem.B.dyld'
or
ld: warning: directory not found for option '-l/usr/lib/libSystem.B.dyld'
or
ld: warning: library not found for option '-l/usr/lib/libSystem.B.dyld'
Depending which one I try.
I even tried using ld
directly from the /Applications/Xcode.app/Contents/Developer/usr/bin
directory to see if there was a symlink issue between new and legacy
I used lldb to dump the symtab of libSystem.dyld and sure enough the line that contains:
`[ 108] 108 X Undefined 0x0000000000000000 0x0000000000000000 0x00010000 dyld_stub_binder`
Which means it has a and index
/user id
of 108
, the X
means it is externally defined (probably is libSystem.B), type
of Undefined
, 'File Address/Value' of '0x0' no Load Address
, and a flag of 0x00010000
.
I loaded the Launchpad executable in Hopper to see what it was going on but it wasn't of much help (except that it told me dyld_stub_binder was in libSystem.B.dyld).
Not sure if this is pertinent but in the actual Launchpad header contains:
; 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 ; '.'
In the _stub_helper
section (which looks like some sort of infinite-ish loop completely skipping the middle 4 instructions):
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
In the __DATA__nl_symbol_ptr
section :
0000000100001000 dq dyld_stub_binder ; DATA XREF=0x100000f89
0000000100001008 dq 0x0000000000000000 ; DATA XREF=0x100000f80
In the External Symbols
segment:
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 ; '.'
What is more interesting is that if I compile with gcc:
gcc -arch x86_64 -e _start -framework Foundation -framework ApplicationServices lp.s
It will build with no problems however will segfault at some point during runtime. I say at some point because if I load it with lldb a.out
and do the run
command, it executes just as it should, no segfault. So it is hard to find out what is going on where exactly.My hunch is that lldb
is pointing my application to the correctdyld_stub_binder
but I could be wrong.
However it runs perfectly fine if I run sudo ./myfile
on the gcc
build. What is gcc
doing that ld
is not? Or is it something in the as
command?
I am still relatively new to using core macOS assembly so any pointers would be helpful!
P.S. I did also try -no_weak_imports
but that did not work either
Your ld myprogram.o -arch x86_64 -macosx_version_min 10.12 -e _start -framework Foundation -framework ApplicationServices -o myprogram
is missing -l
search option for libSystem.B
library.
Add either of these:
-lsystem.b
-lsystem
-lc
-lm
-ld
All are synonyms which will solve missing LC_LOAD_DYLIB(libSystem.B.dylib)
load command. Btw your program works :-)