1# RUN: rm -rf %t && mkdir -p %t
2# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/macho_reloc.o %s
3# RUN: llvm-jitlink -noexec -slab-allocate 100Kb -slab-address 0xfff00000 \
4# RUN:    -define-abs external_data=0x1 -define-abs external_func=0x2 \
5# RUN:    -check=%s %t/macho_reloc.o
6#
7# Test standard MachO relocations. Simulates slab allocation in the top 1Mb of
8# memory and places external symbols in the lowest page to prevent GOT and stub
9# elimination.
10
11        .section        __TEXT,__text,regular,pure_instructions
12
13# Check that common symbols work.
14# jitlink-check: *{4}common_symbol = 0
15# jitlink-check: common_symbol[1:0] = 0
16.comm   common_symbol,4,2
17
18        .align  4, 0x90
19Lanon_func:
20        retq
21
22        .globl  named_func
23        .align  4, 0x90
24named_func:
25        xorq    %rax, %rax
26        retq
27
28# Check X86_64_RELOC_BRANCH handling with a call to a local function.
29#
30# jitlink-check: decode_operand(test_local_call, 0) = named_func - next_pc(test_local_call)
31        .globl  test_local_call
32        .align  4, 0x90
33test_local_call:
34        callq   named_func
35        retq
36
37        .globl  _main
38        .align  4, 0x90
39_main:
40        retq
41
42# Check X86_64_RELOC_GOTPCREL handling with a load from an external symbol.
43# Validate both the reference to the GOT entry, and also the content of the GOT
44# entry.
45#
46# jitlink-check: decode_operand(test_gotld, 4) = got_addr(macho_reloc.o, external_data) - next_pc(test_gotld)
47# jitlink-check: *{8}(got_addr(macho_reloc.o, external_data)) = external_data
48        .globl  test_gotld
49        .align  4, 0x90
50test_gotld:
51        movq    external_data@GOTPCREL(%rip), %rax
52        retq
53
54
55# Check X86_64_RELOC_GOTPCREL handling with cmp instructions, which have
56# negative addends.
57#
58# jitlink-check: decode_operand(test_gotcmpq, 3) = got_addr(macho_reloc.o, external_data) - next_pc(test_gotcmpq)
59        .globl  test_gotcmpq
60        .align  4, 0x90
61test_gotcmpq:
62        cmpq    $0, external_data@GOTPCREL(%rip)
63        retq
64
65# Check that calls to external functions trigger the generation of stubs and GOT
66# entries.
67#
68# jitlink-check: decode_operand(test_external_call, 0) = stub_addr(macho_reloc.o, external_func) - next_pc(test_external_call)
69# jitlink-check: *{8}(got_addr(macho_reloc.o, external_func)) = external_func
70        .globl  test_external_call
71        .align  4, 0x90
72test_external_call:
73        callq   external_func
74        retq
75
76# Check signed relocation handling:
77#
78# X86_64_RELOC_SIGNED / Extern -- movq address of linker global
79# X86_64_RELOC_SIGNED1 / Extern -- movb immediate byte to linker global
80# X86_64_RELOC_SIGNED2 / Extern -- movw immediate word to linker global
81# X86_64_RELOC_SIGNED4 / Extern -- movl immediate long to linker global
82#
83# X86_64_RELOC_SIGNED / Anon -- movq address of linker private into register
84# X86_64_RELOC_SIGNED1 / Anon -- movb immediate byte to linker private
85# X86_64_RELOC_SIGNED2 / Anon -- movw immediate word to linker private
86# X86_64_RELOC_SIGNED4 / Anon -- movl immediate long to linker private
87signed_reloc_checks:
88        .globl signed
89# jitlink-check: decode_operand(signed, 4) = named_data - next_pc(signed)
90signed:
91        movq named_data(%rip), %rax
92
93        .globl signed1
94# jitlink-check: decode_operand(signed1, 3) = named_data - next_pc(signed1)
95signed1:
96        movb $0xAA, named_data(%rip)
97
98        .globl signed2
99# jitlink-check: decode_operand(signed2, 3) = named_data - next_pc(signed2)
100signed2:
101        movw $0xAAAA, named_data(%rip)
102
103        .globl signed4
104# jitlink-check: decode_operand(signed4, 3) = named_data - next_pc(signed4)
105signed4:
106        movl $0xAAAAAAAA, named_data(%rip)
107
108        .globl signedanon
109# jitlink-check: decode_operand(signedanon, 4) = section_addr(macho_reloc.o, __data) - next_pc(signedanon)
110signedanon:
111        movq Lanon_data(%rip), %rax
112
113        .globl signed1anon
114# jitlink-check: decode_operand(signed1anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed1anon)
115signed1anon:
116        movb $0xAA, Lanon_data(%rip)
117
118        .globl signed2anon
119# jitlink-check: decode_operand(signed2anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed2anon)
120signed2anon:
121        movw $0xAAAA, Lanon_data(%rip)
122
123        .globl signed4anon
124# jitlink-check: decode_operand(signed4anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed4anon)
125signed4anon:
126        movl $0xAAAAAAAA, Lanon_data(%rip)
127
128
129
130        .section        __DATA,__data
131
132# Storage target for non-extern X86_64_RELOC_SIGNED_(1/2/4) relocs.
133        .p2align  3
134Lanon_data:
135        .quad   0x1111111111111111
136
137# Check X86_64_RELOC_SUBTRACTOR Quad/Long in anonymous storage with anonymous
138# minuend: "LA: .quad LA - B + C". The anonymous subtrahend form
139# "LA: .quad B - LA + C" is not tested as subtrahends are not permitted to be
140# anonymous.
141#
142# Note: +8 offset in expression below to accounts for sizeof(Lanon_data).
143# jitlink-check: *{8}(section_addr(macho_reloc.o, __data) + 8) = (section_addr(macho_reloc.o, __data) + 8) - named_data - 2
144        .p2align  3
145Lanon_minuend_quad:
146        .quad Lanon_minuend_quad - named_data - 2
147
148# Note: +16 offset in expression below to accounts for sizeof(Lanon_data) + sizeof(Lanon_minuend_long).
149# jitlink-check: *{4}(section_addr(macho_reloc.o, __data) + 16) = ((section_addr(macho_reloc.o, __data) + 16) - named_data - 2)[31:0]
150        .p2align  2
151Lanon_minuend_long:
152        .long Lanon_minuend_long - named_data - 2
153
154# Named quad storage target (first named atom in __data).
155        .globl named_data
156        .p2align  3
157named_data:
158        .quad   0x2222222222222222
159
160# An alt-entry point for named_data
161        .globl named_data_alt_entry
162        .p2align  3
163        .alt_entry named_data_alt_entry
164named_data_alt_entry:
165        .quad   0
166
167# Check X86_64_RELOC_UNSIGNED / quad / extern handling by putting the address of
168# a local named function into a quad symbol.
169#
170# jitlink-check: *{8}named_func_addr_quad = named_func
171        .globl  named_func_addr_quad
172        .p2align  3
173named_func_addr_quad:
174        .quad   named_func
175
176# Check X86_64_RELOC_UNSIGNED / long / extern handling by putting the address of
177# an external function (defined to reside in the low 4Gb) into a long symbol.
178#
179# jitlink-check: *{4}named_func_addr_long = external_func
180        .globl  named_func_addr_long
181        .p2align  2
182named_func_addr_long:
183        .long   external_func
184
185# Check X86_64_RELOC_UNSIGNED / quad / non-extern handling by putting the
186# address of a local anonymous function into a quad symbol.
187#
188# jitlink-check: *{8}anon_func_addr_quad = section_addr(macho_reloc.o, __text)
189        .globl  anon_func_addr_quad
190        .p2align  3
191anon_func_addr_quad:
192        .quad   Lanon_func
193
194# X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend
195#
196# jitlink-check: *{8}anon_minuend_quad1 = section_addr(macho_reloc.o, __data) - anon_minuend_quad1 + 2
197# Only the form "B: .quad LA - B + C" is tested. The form "B: .quad B - LA + C" is
198# invalid because the subtrahend can not be local.
199        .globl  anon_minuend_quad1
200        .p2align  3
201anon_minuend_quad1:
202        .quad Lanon_data - anon_minuend_quad1 + 2
203
204# jitlink-check: *{4}anon_minuend_long1 = (section_addr(macho_reloc.o, __data) - anon_minuend_long1 + 2)[31:0]
205        .globl  anon_minuend_long1
206        .p2align  2
207anon_minuend_long1:
208        .long Lanon_data - anon_minuend_long1 + 2
209
210# Check X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with minuend and subtrahend.
211# Both forms "A: .quad A - B + C" and "A: .quad B - A + C" are tested.
212#
213# Check "A: .quad B - A + C".
214# jitlink-check: *{8}subtrahend_quad2 = (named_data - subtrahend_quad2 - 2)
215        .globl  subtrahend_quad2
216        .p2align  3
217subtrahend_quad2:
218        .quad named_data - subtrahend_quad2 - 2
219
220# Check "A: .long B - A + C".
221# jitlink-check: *{4}subtrahend_long2 = (named_data - subtrahend_long2 - 2)[31:0]
222        .globl  subtrahend_long2
223        .p2align  2
224subtrahend_long2:
225        .long named_data - subtrahend_long2 - 2
226
227# Check "A: .quad A - B + C".
228# jitlink-check: *{8}minuend_quad3 = (minuend_quad3 - named_data - 2)
229        .globl  minuend_quad3
230        .p2align  3
231minuend_quad3:
232        .quad minuend_quad3 - named_data - 2
233
234# Check "A: .long B - A + C".
235# jitlink-check: *{4}minuend_long3 = (minuend_long3 - named_data - 2)[31:0]
236        .globl  minuend_long3
237        .p2align  2
238minuend_long3:
239        .long minuend_long3 - named_data - 2
240
241# Check X86_64_RELOC_SUBTRACTOR handling for exprs of the form
242# "A: .quad/long B - C + D", where 'B' or 'C' is at a fixed offset from 'A'
243# (i.e. is part of an alt_entry chain that includes 'A').
244#
245# Check "A: .long B - C + D" where 'B' is an alt_entry for 'A'.
246# jitlink-check: *{4}subtractor_with_alt_entry_minuend_long = (subtractor_with_alt_entry_minuend_long_B - named_data - 2)[31:0]
247        .globl  subtractor_with_alt_entry_minuend_long
248        .p2align  2
249subtractor_with_alt_entry_minuend_long:
250        .long subtractor_with_alt_entry_minuend_long_B - named_data - 2
251
252        .globl  subtractor_with_alt_entry_minuend_long_B
253        .p2align  2
254        .alt_entry subtractor_with_alt_entry_minuend_long_B
255subtractor_with_alt_entry_minuend_long_B:
256        .long 0
257
258# Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
259# jitlink-check: *{8}subtractor_with_alt_entry_minuend_quad = (subtractor_with_alt_entry_minuend_quad_B - named_data - 2)
260        .globl  subtractor_with_alt_entry_minuend_quad
261        .p2align  3
262subtractor_with_alt_entry_minuend_quad:
263        .quad subtractor_with_alt_entry_minuend_quad_B - named_data - 2
264
265        .globl  subtractor_with_alt_entry_minuend_quad_B
266        .p2align  3
267        .alt_entry subtractor_with_alt_entry_minuend_quad_B
268subtractor_with_alt_entry_minuend_quad_B:
269        .quad 0
270
271# Check "A: .long B - C + D" where 'C' is an alt_entry for 'A'.
272# jitlink-check: *{4}subtractor_with_alt_entry_subtrahend_long = (named_data - subtractor_with_alt_entry_subtrahend_long_B - 2)[31:0]
273        .globl  subtractor_with_alt_entry_subtrahend_long
274        .p2align  2
275subtractor_with_alt_entry_subtrahend_long:
276        .long named_data - subtractor_with_alt_entry_subtrahend_long_B - 2
277
278        .globl  subtractor_with_alt_entry_subtrahend_long_B
279        .p2align  2
280        .alt_entry subtractor_with_alt_entry_subtrahend_long_B
281subtractor_with_alt_entry_subtrahend_long_B:
282        .long 0
283
284# Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
285# jitlink-check: *{8}subtractor_with_alt_entry_subtrahend_quad = (named_data - subtractor_with_alt_entry_subtrahend_quad_B - 2)
286        .globl  subtractor_with_alt_entry_subtrahend_quad
287        .p2align  3
288subtractor_with_alt_entry_subtrahend_quad:
289        .quad named_data - subtractor_with_alt_entry_subtrahend_quad_B - 2
290
291        .globl  subtractor_with_alt_entry_subtrahend_quad_B
292        .p2align  3
293        .alt_entry subtractor_with_alt_entry_subtrahend_quad_B
294subtractor_with_alt_entry_subtrahend_quad_B:
295        .quad 0
296
297# Check X86_64_RELOC_GOT handling.
298# X86_64_RELOC_GOT is the data-section counterpart to X86_64_RELOC_GOTLD. It is
299# handled exactly the same way, including having an implicit PC-rel offset of -4
300# (despite this not making sense in a data section, and requiring an explicit
301# +4 addend to cancel it out and get the correct result).
302#
303# jitlink-check: *{4}test_got = (got_addr(macho_reloc.o, external_data) - test_got)[31:0]
304        .globl test_got
305        .p2align  2
306test_got:
307        .long   external_data@GOTPCREL + 4
308
309# Check that unreferenced atoms in no-dead-strip sections are not dead stripped.
310# We need to use a local symbol for this as any named symbol will end up in the
311# ORC responsibility set, which is automatically marked live and would couse
312# spurious passes.
313#
314# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_sect) = 0
315        .section        __DATA,__nds_test_sect,regular,no_dead_strip
316        .quad 0
317
318# Check that unreferenced local symbols that have been marked no-dead-strip are
319# not dead-striped.
320#
321# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_nlst) = 0
322        .section       __DATA,__nds_test_nlst,regular
323        .no_dead_strip no_dead_strip_test_symbol
324no_dead_strip_test_symbol:
325        .quad 0
326
327# Check that explicit zero-fill symbols are supported
328# jitlink-check: *{8}zero_fill_test = 0
329        .globl zero_fill_test
330.zerofill __DATA,__zero_fill_test,zero_fill_test,8,3
331
332# Check that section alignments are respected.
333# We test this by introducing two segments with alignment 8, each containing one
334# byte of data. We require both symbols to have an aligned address.
335#
336# jitlink-check: section_alignment_check1[2:0] = 0
337# jitlink-check: section_alignment_check2[2:0] = 0
338        .section        __DATA,__sec_align_chk1
339        .p2align 3
340
341        .globl section_alignment_check1
342section_alignment_check1:
343        .byte 0
344
345        .section        __DATA,__sec_align_chk2
346        .p2align 3
347
348        .globl section_alignment_check2
349section_alignment_check2:
350        .byte 0
351
352.subsections_via_symbols
353