xref: /llvm-project/lld/test/MachO/weak-reference.s (revision 0d30e92f59589de44a185c53671b7fe2e83cd2ae)
1# REQUIRES: x86
2# RUN: rm -rf %t; split-file %s %t
3# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/libfoo.s -o %t/libfoo.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/strongref.s -o %t/strongref.o
5# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
6# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/invalid.s -o %t/invalid.o
7# RUN: %lld -lSystem -dylib %t/libfoo.o -o %t/libfoo.dylib
8
9# RUN: %lld -lSystem %t/test.o %t/libfoo.dylib -o %t/test
10# RUN: %lld -fixup_chains -lSystem %t/test.o %t/libfoo.dylib -o %t/chained
11# RUN: llvm-objdump --macho --syms --bind --lazy-bind %t/test | FileCheck %s --check-prefixes=SYMS,BIND
12# RUN: llvm-objdump --macho --syms --dyld-info %t/chained | FileCheck %s --check-prefixes=CHAINED
13## llvm-objdump doesn't print out all the flags info for lazy & weak bindings,
14## so we use obj2yaml instead to test them.
15# RUN: obj2yaml %t/test | FileCheck %s --check-prefix=YAML
16
17# RUN: %lld -lSystem %t/libfoo.dylib %t/test.o -o %t/test
18# RUN: llvm-objdump --macho --syms --bind --lazy-bind %t/test | FileCheck %s --check-prefixes=SYMS,BIND
19# RUN: obj2yaml %t/test | FileCheck %s --check-prefix=YAML
20
21# SYMS:     SYMBOL TABLE:
22# SYMS-DAG: 0000000000000000  w  *UND* _foo
23# SYMS-DAG: 0000000000000000  w  *UND* _foo_fn
24# SYMS-DAG: 0000000000000000  w  *UND* _foo_tlv
25# SYMS-DAG: 0000000000000000  w  *UND* _weak_foo
26# SYMS-DAG: 0000000000000000  w  *UND* _weak_foo_fn
27
28# BIND:      Bind table:
29# BIND-NEXT: segment       section          address         type     addend dylib   symbol
30# BIND-DAG:  __DATA        __data           0x{{[0-9a-f]+}} pointer       0 libfoo  _foo (weak_import)
31# BIND-DAG:  __DATA_CONST  __got            0x{{[0-9a-f]+}} pointer       0 libfoo  _foo (weak_import)
32# BIND-DAG:  __DATA        __thread_ptrs    0x{{[0-9a-f]+}} pointer       0 libfoo  _foo_tlv (weak_import)
33# BIND-DAG:  __DATA        __data           0x{{[0-9a-f]+}} pointer       0 libfoo  _weak_foo (weak_import)
34# BIND-DAG:  __DATA        __la_symbol_ptr  0x{{[0-9a-f]+}} pointer       0 libfoo  _weak_foo_fn (weak_import)
35# BIND:      Lazy bind table:
36# BIND-NEXT: segment       section          address                         dylib   symbol
37# BIND-DAG:  __DATA        __la_symbol_ptr  0x{{[0-9a-f]+}}                  libfoo  _foo_fn
38
39# CHAINED:      dyld information:
40# CHAINED-NEXT: segment      section       address pointer type  addend dylib    symbol/vm address
41# CHAINED-DAG:  __DATA_CONST __got             {{.*}}      bind  0x0    libfoo   _foo (weak import)
42# CHAINED-DAG:  __DATA       __data            {{.*}}      bind  0x0    libfoo   _foo (weak import)
43# CHAINED-DAG:  __DATA       __thread_ptrs     {{.*}}      bind  0x0    libfoo   _foo_tlv (weak import)
44# CHAINED-DAG:  __DATA_CONST __got             {{.*}}      bind  0x0    libfoo   _foo_fn (weak import)
45# CHAINED-DAG:  __DATA       __data            {{.*}}      bind  0x0    weak     _weak_foo (weak import)
46# CHAINED-DAG:  __DATA_CONST __got             {{.*}}      bind  0x0    weak     _weak_foo_fn (weak import)
47
48# YAML-LABEL: WeakBindOpcodes:
49# YAML:        - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
50# YAML-NEXT:     Imm:             0
51# YAML-NEXT:     Symbol:          _weak_foo_fn
52# YAML:        - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
53# YAML-NEXT:     Imm:             0
54# YAML-NEXT:     Symbol:          _weak_foo
55# YAML-LABEL: LazyBindOpcodes:
56# YAML:        - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
57# YAML-NEXT:     Imm:             1
58# YAML-NEXT:     Symbol:          _foo_fn
59
60## Check that if both strong & weak references are present in inputs, the weak
61## reference takes priority. NOTE: ld64 actually emits a strong reference if
62## the reference is to a function symbol or a TLV. I'm not sure if there's a
63## good reason for that, so I'm deviating here for a simpler implementation.
64# RUN: %lld -lSystem %t/test.o %t/strongref.o %t/libfoo.dylib -o %t/with-strong
65# RUN: %lld -fixup_chains -lSystem %t/test.o %t/strongref.o %t/libfoo.dylib -o %t/with-strong-chained
66# RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND
67# RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED
68# RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML
69# RUN: %lld -lSystem %t/strongref.o %t/test.o %t/libfoo.dylib -o %t/with-strong
70# RUN: %lld -fixup_chains -lSystem %t/strongref.o %t/test.o %t/libfoo.dylib -o %t/with-strong-chained
71# RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND
72# RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED
73# RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML
74# RUN: %lld -lSystem %t/libfoo.dylib %t/strongref.o %t/test.o -o %t/with-strong
75# RUN: %lld -fixup_chains -lSystem %t/libfoo.dylib %t/strongref.o %t/test.o -o %t/with-strong-chained
76# RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND
77# RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED
78# RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML
79# RUN: %lld -lSystem %t/libfoo.dylib %t/test.o %t/strongref.o -o %t/with-strong
80# RUN: %lld -fixup_chains -lSystem %t/libfoo.dylib %t/test.o %t/strongref.o -o %t/with-strong-chained
81# RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND
82# RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED
83# RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML
84# RUN: %lld -lSystem %t/test.o %t/libfoo.dylib %t/strongref.o -o %t/with-strong
85# RUN: %lld -fixup_chains -lSystem %t/test.o %t/libfoo.dylib %t/strongref.o -o %t/with-strong-chained
86# RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND
87# RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED
88# RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML
89# RUN: %lld -lSystem %t/strongref.o %t/libfoo.dylib %t/test.o -o %t/with-strong
90# RUN: %lld -fixup_chains -lSystem %t/strongref.o %t/libfoo.dylib %t/test.o -o %t/with-strong-chained
91# RUN: llvm-objdump --macho --bind %t/with-strong | FileCheck %s --check-prefix=STRONG-BIND
92# RUN: llvm-objdump --macho --dyld-info %t/with-strong-chained | FileCheck %s --check-prefix=STRONG-CHAINED
93# RUN: obj2yaml %t/with-strong | FileCheck %s --check-prefix=STRONG-YAML
94
95# STRONG-BIND:      Bind table:
96# STRONG-BIND-NEXT: segment       section          address         type       addend dylib   symbol
97# STRONG-BIND-DAG:  __DATA        __data           0x{{[0-9a-f]+}} pointer         0 libfoo  _foo{{$}}
98# STRONG-BIND-DAG:  __DATA        __data           0x{{[0-9a-f]+}} pointer         0 libfoo  _foo{{$}}
99# STRONG-BIND-DAG:  __DATA_CONST  __got            0x{{[0-9a-f]+}} pointer         0 libfoo  _foo{{$}}
100# STRONG-BIND-DAG:  __DATA        __thread_ptrs    0x{{[0-9a-f]+}} pointer         0 libfoo  _foo_tlv{{$}}
101# STRONG-BIND-DAG:  __DATA        __data           0x{{[0-9a-f]+}} pointer         0 libfoo  _weak_foo{{$}}
102# STRONG-BIND-DAG:  __DATA        __data           0x{{[0-9a-f]+}} pointer         0 libfoo  _weak_foo{{$}}
103# STRONG-BIND-DAG:  __DATA        __la_symbol_ptr  0x{{[0-9a-f]+}} pointer         0 libfoo  _weak_foo_fn{{$}}
104
105# STRONG-CHAINED:      dyld information:
106# STRONG-CHAINED-NEXT: segment      section      address pointer type  addend dylib   symbol/vm address
107# STRONG-CHAINED-DAG:  __DATA_CONST __got            {{.*}}      bind  0x0    weak    _weak_foo_fn{{$}}
108# STRONG-CHAINED-DAG:  __DATA_CONST __got            {{.*}}      bind  0x0    libfoo  _foo_fn{{$}}
109# STRONG-CHAINED-DAG:  __DATA_CONST __got            {{.*}}      bind  0x0    libfoo  _foo{{$}}
110# STRONG-CHAINED-DAG:  __DATA       __data           {{.*}}      bind  0x0    libfoo  _foo{{$}}
111# STRONG-CHAINED-DAG:  __DATA       __data           {{.*}}      bind  0x0    libfoo  _foo{{$}}
112# STRONG-CHAINED-DAG:  __DATA       __data           {{.*}}      bind  0x0    weak    _weak_foo{{$}}
113# STRONG-CHAINED-DAG:  __DATA       __data           {{.*}}      bind  0x0    weak    _weak_foo{{$}}
114# STRONG-CHAINED-DAG:  __DATA       __thread_ptrs    {{.*}}      bind  0x0    libfoo  _foo_tlv{{$}}
115
116# STRONG-YAML-LABEL: WeakBindOpcodes:
117# STRONG-YAML:        - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
118# STRONG-YAML-NEXT:     Imm:             0
119# STRONG-YAML-NEXT:     Symbol:          _weak_foo_fn
120# STRONG-YAML:        - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
121# STRONG-YAML-NEXT:     Imm:             0
122# STRONG-YAML-NEXT:     Symbol:          _weak_foo
123# STRONG-YAML-LABEL: LazyBindOpcodes:
124# STRONG-YAML:        - Opcode:          BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
125# STRONG-YAML-NEXT:     Imm:             0
126# STRONG-YAML-NEXT:     Symbol:          _foo_fn
127
128## Weak references must still be satisfied at link time.
129# RUN: not %lld -lSystem %t/invalid.o -o /dev/null 2>&1 | FileCheck %s \
130# RUN:   --check-prefix=INVALID -DDIR=%t
131# INVALID: error: undefined symbol: _missing
132
133#--- libfoo.s
134.globl _foo, _foo_fn, _weak_foo, _weak_foo_fn
135.weak_definition _weak_foo, _weak_foo_fn
136_foo:
137_foo_fn:
138_weak_foo:
139_weak_foo_fn:
140
141.section __DATA,__thread_vars,thread_local_variables
142.globl _foo_tlv
143_foo_tlv:
144
145#--- test.s
146.globl _main
147.weak_reference _foo_fn, _foo, _weak_foo, _weak_foo_fn, _foo_tlv
148
149_main:
150  mov _foo@GOTPCREL(%rip), %rax
151  mov _foo_tlv@TLVP(%rip), %rax
152  callq _foo_fn
153  callq _weak_foo_fn
154  ret
155
156.data
157  .quad _foo
158  .quad _weak_foo
159
160#--- strongref.s
161.globl _strongref
162_strongref:
163  mov _foo@GOTPCREL(%rip), %rax
164  mov _foo_tlv@TLVP(%rip), %rax
165  callq _foo_fn
166  callq _weak_foo_fn
167  ret
168
169.data
170  .quad _foo
171  .quad _weak_foo
172
173#--- invalid.s
174.globl _main
175.weak_reference _missing
176_main:
177  callq _missing
178  ret
179