420 lines · plain
1# REQUIRES: aarch642 3## Check for the following:4## (1) address match between thunk definitions and call destinations5## (2) address match between thunk page+offset computations and function6## definitions7## (3) a second thunk is created when the first one goes out of range8## (4) early calls to a dylib stub use a thunk, and later calls the stub9## directly10## (5) Thunks are created for all sections in the text segment with branches.11## (6) Thunks are in the linker map file.12## Notes:13## 0x4000000 = 64 Mi = half the magnitude of the forward-branch range14 15# RUN: rm -rf %t; mkdir %t16# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t/input.o17## Use --icf=safe_thunks to test that branch extension algo is compatible18## with safe_thunks ICF.19# RUN: %lld -arch arm64 -dead_strip -lSystem -U _extern_sym -map %t/thunk.map -o %t/thunk %t/input.o --icf=safe_thunks20# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t/thunk | FileCheck %s21# RUN: llvm-objdump --macho --section-headers %t/thunk > %t/headers.txt22# RUN: llvm-otool -vs __DATA __objc_selrefs %t/thunk >> %t/headers.txt23# RUN: llvm-otool -vs __TEXT __objc_stubs %t/thunk >> %t/headers.txt24# RUN: FileCheck %s --check-prefix=OBJC < %t/headers.txt25 26# RUN: FileCheck %s --input-file %t/thunk.map --check-prefix=MAP27 28# OBJC: Sections:29# OBJC: __text30# OBJC-NEXT: __lcxx_override31# OBJC-NEXT: __stubs32# OBJC-NEXT: __stub_helper33# OBJC-NEXT: __objc_stubs34 35# OBJC: Contents of (__DATA,__objc_selrefs) section36# OBJC-NEXT: {{[0-9a-f]*}} __TEXT:__objc_methname:foo37# OBJC-NEXT: {{[0-9a-f]*}} __TEXT:__objc_methname:bar38 39# OBJC: Contents of (__TEXT,__objc_stubs) section40# OBJC: _objc_msgSend$bar:41# OBJC: _objc_msgSend$foo:42 43# MAP: 0x{{[[:xdigit:]]+}} {{.*}} _fold_func_low_addr44# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _a45# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _b46# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _c47# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _d.thunk.048# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _e.thunk.049# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _f.thunk.050# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _g.thunk.051# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _h.thunk.052# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} ___nan.thunk.053# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _d54# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _e55# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _f56# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _g57# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _a.thunk.058# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _b.thunk.059# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _h60# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _main61# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _fold_func_high_addr62# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _c.thunk.063# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _d.thunk.164# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _e.thunk.165# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _f.thunk.166# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _fold_func_low_addr.thunk.067# MAP-NEXT: 0x{{[[:xdigit:]]+}} {{.*}} _z68 69 70# CHECK: Disassembly of section __TEXT,__text:71 72# CHECK: [[#%.13x, A_PAGE:]][[#%.3x, A_OFFSET:]] <_a>:73# CHECK: bl 0x[[#%x, A:]] <_a>74# CHECK: bl 0x[[#%x, B:]] <_b>75# CHECK: bl 0x[[#%x, C:]] <_c>76# CHECK: bl 0x[[#%x, D_THUNK_0:]] <_d.thunk.0>77# CHECK: bl 0x[[#%x, E_THUNK_0:]] <_e.thunk.0>78# CHECK: bl 0x[[#%x, F_THUNK_0:]] <_f.thunk.0>79# CHECK: bl 0x[[#%x, G_THUNK_0:]] <_g.thunk.0>80# CHECK: bl 0x[[#%x, H_THUNK_0:]] <_h.thunk.0>81# CHECK: bl 0x[[#%x, NAN_THUNK_0:]] <___nan.thunk.0>82 83# CHECK: [[#%.13x, B_PAGE:]][[#%.3x, B_OFFSET:]] <_b>:84# CHECK: bl 0x[[#%x, A]] <_a>85# CHECK: bl 0x[[#%x, B]] <_b>86# CHECK: bl 0x[[#%x, C]] <_c>87# CHECK: bl 0x[[#%x, D_THUNK_0]] <_d.thunk.0>88# CHECK: bl 0x[[#%x, E_THUNK_0]] <_e.thunk.0>89# CHECK: bl 0x[[#%x, F_THUNK_0]] <_f.thunk.0>90# CHECK: bl 0x[[#%x, G_THUNK_0]] <_g.thunk.0>91# CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0>92# CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0>93 94# CHECK: [[#%.13x, C_PAGE:]][[#%.3x, C_OFFSET:]] <_c>:95# CHECK: bl 0x[[#%x, A]] <_a>96# CHECK: bl 0x[[#%x, B]] <_b>97# CHECK: bl 0x[[#%x, C]] <_c>98# CHECK: bl 0x[[#%x, D:]] <_d>99# CHECK: bl 0x[[#%x, E:]] <_e>100# CHECK: bl 0x[[#%x, F_THUNK_0]] <_f.thunk.0>101# CHECK: bl 0x[[#%x, G_THUNK_0]] <_g.thunk.0>102# CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0>103# CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0>104 105# CHECK: [[#%x, D_THUNK_0]] <_d.thunk.0>:106# CHECK: adrp x16, 0x[[#%x, D_PAGE:]]107# CHECK: add x16, x16, #[[#D_OFFSET:]]108 109# CHECK: [[#%x, E_THUNK_0]] <_e.thunk.0>:110# CHECK: adrp x16, 0x[[#%x, E_PAGE:]]111# CHECK: add x16, x16, #[[#E_OFFSET:]]112 113# CHECK: [[#%x, F_THUNK_0]] <_f.thunk.0>:114# CHECK: adrp x16, 0x[[#%x, F_PAGE:]]115# CHECK: add x16, x16, #[[#F_OFFSET:]]116 117# CHECK: [[#%x, G_THUNK_0]] <_g.thunk.0>:118# CHECK: adrp x16, 0x[[#%x, G_PAGE:]]119# CHECK: add x16, x16, #[[#G_OFFSET:]]120 121# CHECK: [[#%x, H_THUNK_0]] <_h.thunk.0>:122# CHECK: adrp x16, 0x[[#%x, H_PAGE:]]123# CHECK: add x16, x16, #[[#H_OFFSET:]]124 125# CHECK: [[#%x, NAN_THUNK_0]] <___nan.thunk.0>:126# CHECK: adrp x16, 0x[[#%x, NAN_PAGE:]]127# CHECK: add x16, x16, #[[#NAN_OFFSET:]]128 129# CHECK: [[#%x, D_PAGE + D_OFFSET]] <_d>:130# CHECK: bl 0x[[#%x, A]] <_a>131# CHECK: bl 0x[[#%x, B]] <_b>132# CHECK: bl 0x[[#%x, C]] <_c>133# CHECK: bl 0x[[#%x, D]] <_d>134# CHECK: bl 0x[[#%x, E]] <_e>135# CHECK: bl 0x[[#%x, F_THUNK_0]] <_f.thunk.0>136# CHECK: bl 0x[[#%x, G_THUNK_0]] <_g.thunk.0>137# CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0>138# CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0>139 140# CHECK: [[#%x, E_PAGE + E_OFFSET]] <_e>:141# CHECK: bl 0x[[#%x, A_THUNK_0:]] <_a.thunk.0>142# CHECK: bl 0x[[#%x, B_THUNK_0:]] <_b.thunk.0>143# CHECK: bl 0x[[#%x, C]] <_c>144# CHECK: bl 0x[[#%x, D]] <_d>145# CHECK: bl 0x[[#%x, E]] <_e>146# CHECK: bl 0x[[#%x, F:]] <_f>147# CHECK: bl 0x[[#%x, G:]] <_g>148# CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0>149# CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0>150 151# CHECK: [[#%x, F_PAGE + F_OFFSET]] <_f>:152# CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0>153# CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0>154# CHECK: bl 0x[[#%x, C]] <_c>155# CHECK: bl 0x[[#%x, D]] <_d>156# CHECK: bl 0x[[#%x, E]] <_e>157# CHECK: bl 0x[[#%x, F]] <_f>158# CHECK: bl 0x[[#%x, G]] <_g>159# CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0>160# CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0>161 162# CHECK: [[#%x, G_PAGE + G_OFFSET]] <_g>:163# CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0>164# CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0>165# CHECK: bl 0x[[#%x, C_THUNK_0:]] <_c.thunk.0>166# CHECK: bl 0x[[#%x, D_THUNK_1:]] <_d.thunk.1>167# CHECK: bl 0x[[#%x, E]] <_e>168# CHECK: bl 0x[[#%x, F]] <_f>169# CHECK: bl 0x[[#%x, G]] <_g>170# CHECK: bl 0x[[#%x, H:]] <_h>171# CHECK: bl 0x[[#%x, STUBS:]]172 173# CHECK: [[#%x, A_THUNK_0]] <_a.thunk.0>:174# CHECK: adrp x16, 0x[[#%x, A_PAGE]]000175# CHECK: add x16, x16, #[[#%d, A_OFFSET]]176 177# CHECK: [[#%x, B_THUNK_0]] <_b.thunk.0>:178# CHECK: adrp x16, 0x[[#%x, B_PAGE]]000179# CHECK: add x16, x16, #[[#%d, B_OFFSET]]180 181# CHECK: [[#%x, H_PAGE + H_OFFSET]] <_h>:182# CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0>183# CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0>184# CHECK: bl 0x[[#%x, C_THUNK_0]] <_c.thunk.0>185# CHECK: bl 0x[[#%x, D_THUNK_1]] <_d.thunk.1>186# CHECK: bl 0x[[#%x, E]] <_e>187# CHECK: bl 0x[[#%x, F]] <_f>188# CHECK: bl 0x[[#%x, G]] <_g>189# CHECK: bl 0x[[#%x, H]] <_h>190# CHECK: bl 0x[[#%x, STUBS]]191 192# CHECK: <_main>:193# CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0>194# CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0>195# CHECK: bl 0x[[#%x, C_THUNK_0]] <_c.thunk.0>196# CHECK: bl 0x[[#%x, D_THUNK_1]] <_d.thunk.1>197# CHECK: bl 0x[[#%x, E_THUNK_1:]] <_e.thunk.1>198# CHECK: bl 0x[[#%x, F_THUNK_1:]] <_f.thunk.1>199# CHECK: bl 0x[[#%x, G]] <_g>200# CHECK: bl 0x[[#%x, H]] <_h>201# CHECK: bl 0x[[#%x, STUBS]]202 203# CHECK: [[#%x, C_THUNK_0]] <_c.thunk.0>:204# CHECK: adrp x16, 0x[[#%x, C_PAGE]]000205# CHECK: add x16, x16, #[[#%d, C_OFFSET]]206 207# CHECK: [[#%x, D_THUNK_1]] <_d.thunk.1>:208# CHECK: adrp x16, 0x[[#%x, D_PAGE]]209# CHECK: add x16, x16, #[[#D_OFFSET]]210 211# CHECK: [[#%x, E_THUNK_1]] <_e.thunk.1>:212# CHECK: adrp x16, 0x[[#%x, E_PAGE]]213# CHECK: add x16, x16, #[[#E_OFFSET]]214 215# CHECK: [[#%x, F_THUNK_1]] <_f.thunk.1>:216# CHECK: adrp x16, 0x[[#%x, F_PAGE]]217# CHECK: add x16, x16, #[[#F_OFFSET]]218 219# CHECK: Disassembly of section __TEXT,__lcxx_override:220# CHECK: <_z>:221# CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0>222 223# CHECK: Disassembly of section __TEXT,__stubs:224 225# CHECK: [[#%x, NAN_PAGE + NAN_OFFSET]] <__stubs>:226 227.section __TEXT,__objc_methname,cstring_literals228lselref1:229 .asciz "foo"230lselref2:231 .asciz "bar"232 233.section __DATA,__objc_selrefs,literal_pointers,no_dead_strip234.p2align 3235.quad lselref1236.quad lselref2237 238.text239.globl _objc_msgSend240_objc_msgSend:241 ret242 243.subsections_via_symbols244 245.addrsig246.addrsig_sym _fold_func_low_addr247.addrsig_sym _fold_func_high_addr248 249.text250 251.globl _fold_func_low_addr252.p2align 2253_fold_func_low_addr:254 add x0, x0, x0255 add x1, x0, x1256 add x2, x0, x2257 ret258 259.globl _a260.p2align 2261_a:262 bl _a263 bl _b264 bl _c265 bl _d266 bl _e267 bl _f268 bl _g269 bl _h270 bl ___nan271 ret272 273.globl _b274.p2align 2275_b:276 bl _a277 bl _b278 bl _c279 bl _d280 bl _e281 bl _f282 bl _g283 bl _h284 bl ___nan285 .space 0x4000000-0x3c286 ret287 288.globl _c289.p2align 2290_c:291 bl _a292 bl _b293 bl _c294 bl _d295 bl _e296 bl _f297 bl _g298 bl _h299 bl ___nan300 ret301 302.globl _d303.p2align 2304_d:305 bl _a306 bl _b307 bl _c308 bl _d309 bl _e310 bl _f311 bl _g312 bl _h313 bl ___nan314 .space 0x4000000-0x38315 ret316 317.globl _e318.p2align 2319_e:320 bl _a321 bl _b322 bl _c323 bl _d324 bl _e325 bl _f326 bl _g327 bl _h328 bl ___nan329 ret330 331.globl _f332.p2align 2333_f:334 bl _a335 bl _b336 bl _c337 bl _d338 bl _e339 bl _f340 bl _g341 bl _h342 bl ___nan343 .space 0x4000000-0x34344 ret345 346.globl _g347.p2align 2348_g:349 bl _a350 bl _b351 bl _c352 bl _d353 bl _e354 bl _f355 bl _g356 bl _h357 bl ___nan358 ret359 360.globl _h361.p2align 2362_h:363 bl _a364 bl _b365 bl _c366 bl _d367 bl _e368 bl _f369 bl _g370 bl _h371 bl ___nan372 .space 0x4000000-0x30373 ret374 375.globl _main376.p2align 2377_main:378 bl _a379 bl _b380 bl _c381 bl _d382 bl _e383 bl _f384 bl _g385 bl _h386 bl _fold_func_low_addr387 bl _fold_func_high_addr388 bl ___nan389 bl _objc_msgSend$foo390 bl _objc_msgSend$bar391 ret392 393.globl _fold_func_high_addr394.p2align 2395_fold_func_high_addr:396 add x0, x0, x0397 add x1, x0, x1398 add x2, x0, x2399 ret400 401 402.section __TEXT,__cstring403 # The .space below has to be composed of non-zero characters. Otherwise, the404 # linker will create a symbol for every '0' in the section, leading to405 # dramatic memory usage and a huge linker map file406 .space 0x4000000, 'A'407 .byte 0408 409 410.section __TEXT,__lcxx_override,regular,pure_instructions411 412.globl _z413.no_dead_strip _z414.p2align 2415_z:416 bl _a417 ## Ensure calling into stubs works418 bl _extern_sym419 ret420