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