Skip to content

Instantly share code, notes, and snippets.

@rprichard
Created February 10, 2021 01:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rprichard/8775d7844228577e40d2fd0776397f47 to your computer and use it in GitHub Desktop.
Save rprichard/8775d7844228577e40d2fd0776397f47 to your computer and use it in GitHub Desktop.
Mach-O doesn't have weak aliases
The linker seems to delete the weak version of _bar because it's overridden by a strong
version, and when it does, it also deletes _foo's instructions, so calling _foo actually
calls an unrelated function, _baz.
$ ./weak-to-weak-alias.sh
=== objdump
a.out: file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000100008010 l O __DATA,__data __dyld_private
0000000100000000 g F __TEXT,__text __mh_execute_header
0000000100003ef6 g F __TEXT,__text _bar
0000000100003ef0 g F __TEXT,__text _baz
0000000100003ef0 gw F __TEXT,__text _foo
0000000100003f00 g F __TEXT,__text _main
0000000000000000 *UND* _printf
0000000000000000 *UND* dyld_stub_binder
Disassembly of section __TEXT,__text:
0000000100003ef0 _foo:
100003ef0: b8 14 00 00 00 movl $20, %eax
100003ef5: c3 retq
0000000100003ef6 _bar:
100003ef6: b8 1e 00 00 00 movl $30, %eax
100003efb: c3 retq
100003efc: 90 nop
100003efd: 90 nop
100003efe: 90 nop
100003eff: 90 nop
0000000100003f00 _main:
100003f00: 55 pushq %rbp
100003f01: 48 89 e5 movq %rsp, %rbp
100003f04: 48 83 ec 10 subq $16, %rsp
100003f08: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
100003f0f: e8 4e 00 00 00 callq 78 <dyld_stub_binder+0x100003f62>
100003f14: 48 8d 3d 6f 00 00 00 leaq 111(%rip), %rdi
100003f1b: 89 c6 movl %eax, %esi
100003f1d: b0 00 movb $0, %al
100003f1f: e8 44 00 00 00 callq 68 <dyld_stub_binder+0x100003f68>
100003f24: 89 45 f8 movl %eax, -8(%rbp)
100003f27: e8 ca ff ff ff callq -54 <_bar>
100003f2c: 48 8d 3d 5f 00 00 00 leaq 95(%rip), %rdi
100003f33: 89 c6 movl %eax, %esi
100003f35: b0 00 movb $0, %al
100003f37: e8 2c 00 00 00 callq 44 <dyld_stub_binder+0x100003f68>
100003f3c: 89 45 f4 movl %eax, -12(%rbp)
100003f3f: e8 ac ff ff ff callq -84 <_foo>
100003f44: 48 8d 3d 4f 00 00 00 leaq 79(%rip), %rdi
100003f4b: 89 c6 movl %eax, %esi
100003f4d: b0 00 movb $0, %al
100003f4f: e8 14 00 00 00 callq 20 <dyld_stub_binder+0x100003f68>
100003f54: 31 c9 xorl %ecx, %ecx
100003f56: 89 45 f0 movl %eax, -16(%rbp)
100003f59: 89 c8 movl %ecx, %eax
100003f5b: 48 83 c4 10 addq $16, %rsp
100003f5f: 5d popq %rbp
100003f60: c3 retq
Disassembly of section __TEXT,__stubs:
0000000100003f62 __stubs:
100003f62: ff 25 98 40 00 00 jmpq *16536(%rip)
100003f68: ff 25 9a 40 00 00 jmpq *16538(%rip)
Disassembly of section __TEXT,__stub_helper:
0000000100003f70 __stub_helper:
100003f70: 4c 8d 1d 99 40 00 00 leaq 16537(%rip), %r11
100003f77: 41 53 pushq %r11
100003f79: ff 25 81 00 00 00 jmpq *129(%rip)
100003f7f: 90 nop
100003f80: 68 00 00 00 00 pushq $0
100003f85: e9 e6 ff ff ff jmp -26 <__stub_helper>
=== Program output
foo=20
bar=30
baz=20
$ ./weak-to-nonweak-alias.sh
=== objdump
a.out: file format Mach-O 64-bit x86-64
SYMBOL TABLE:
0000000100008008 l O __DATA,__data __dyld_private
0000000100000000 g F __TEXT,__text __mh_execute_header
0000000100003f06 g F __TEXT,__text _bar
0000000100003f00 g F __TEXT,__text _baz
0000000100003f00 g F __TEXT,__text _foo
0000000100003f10 g F __TEXT,__text _main
0000000000000000 *UND* _printf
0000000000000000 *UND* dyld_stub_binder
Disassembly of section __TEXT,__text:
0000000100003f00 _foo:
100003f00: b8 14 00 00 00 movl $20, %eax
100003f05: c3 retq
0000000100003f06 _bar:
100003f06: b8 1e 00 00 00 movl $30, %eax
100003f0b: c3 retq
100003f0c: 90 nop
100003f0d: 90 nop
100003f0e: 90 nop
100003f0f: 90 nop
0000000100003f10 _main:
100003f10: 55 pushq %rbp
100003f11: 48 89 e5 movq %rsp, %rbp
100003f14: 48 83 ec 10 subq $16, %rsp
100003f18: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
100003f1f: e8 dc ff ff ff callq -36 <_foo>
100003f24: 48 8d 3d 67 00 00 00 leaq 103(%rip), %rdi
100003f2b: 89 c6 movl %eax, %esi
100003f2d: b0 00 movb $0, %al
100003f2f: e8 3e 00 00 00 callq 62 <dyld_stub_binder+0x100003f72>
100003f34: 89 45 f8 movl %eax, -8(%rbp)
100003f37: e8 ca ff ff ff callq -54 <_bar>
100003f3c: 48 8d 3d 57 00 00 00 leaq 87(%rip), %rdi
100003f43: 89 c6 movl %eax, %esi
100003f45: b0 00 movb $0, %al
100003f47: e8 26 00 00 00 callq 38 <dyld_stub_binder+0x100003f72>
100003f4c: 89 45 f4 movl %eax, -12(%rbp)
100003f4f: e8 ac ff ff ff callq -84 <_foo>
100003f54: 48 8d 3d 47 00 00 00 leaq 71(%rip), %rdi
100003f5b: 89 c6 movl %eax, %esi
100003f5d: b0 00 movb $0, %al
100003f5f: e8 0e 00 00 00 callq 14 <dyld_stub_binder+0x100003f72>
100003f64: 31 c9 xorl %ecx, %ecx
100003f66: 89 45 f0 movl %eax, -16(%rbp)
100003f69: 89 c8 movl %ecx, %eax
100003f6b: 48 83 c4 10 addq $16, %rsp
100003f6f: 5d popq %rbp
100003f70: c3 retq
Disassembly of section __TEXT,__stubs:
0000000100003f72 __stubs:
100003f72: ff 25 88 40 00 00 jmpq *16520(%rip)
Disassembly of section __TEXT,__stub_helper:
0000000100003f78 __stub_helper:
100003f78: 4c 8d 1d 89 40 00 00 leaq 16521(%rip), %r11
100003f7f: 41 53 pushq %r11
100003f81: ff 25 79 00 00 00 jmpq *121(%rip)
100003f87: 90 nop
100003f88: 68 00 00 00 00 pushq $0
100003f8d: e9 e6 ff ff ff jmp -26 <__stub_helper>
=== Program output
foo=20
bar=30
baz=20
#!/bin/bash -e
cat >test1.s <<EOF
.text
.globl _foo
.globl _bar
.weak_definition _bar
_foo:
_bar:
movl \$10, %eax
retq
.globl _baz
_baz:
movl \$20, %eax
retq
EOF
cat >test2.s <<EOF
.globl _bar
_bar:
movl \$30, %eax
retq
EOF
cat >main.c <<EOF
#include <stdio.h>
int foo(void);
int bar(void);
int baz(void);
int main() {
printf("foo=%d\n", foo());
printf("bar=%d\n", bar());
printf("baz=%d\n", baz());
return 0;
}
EOF
clang test1.s test2.s main.c
echo ''
echo === objdump
objdump -td a.out
echo ''
echo === Program output
./a.out
#!/bin/bash -e
cat >test1.s <<EOF
.text
.globl _foo
.weak_definition _foo
_foo:
movl \$10, %eax
retq
.globl _bar
_bar = _foo
.globl _baz
_baz:
movl \$20, %eax
retq
EOF
cat >test2.s <<EOF
.globl _bar
_bar:
movl \$30, %eax
retq
EOF
cat >main.c <<EOF
#include <stdio.h>
int foo(void);
int bar(void);
int baz(void);
int main() {
printf("foo=%d\n", foo());
printf("bar=%d\n", bar());
printf("baz=%d\n", baz());
return 0;
}
EOF
clang test1.s test2.s main.c
echo ''
echo === objdump
objdump -td a.out
echo ''
echo === Program output
./a.out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment