| # REQUIRES: aarch64 |
| |
| ## Check for the following: |
| ## (1) address match between thunk definitions and call destinations |
| ## (2) address match between thunk page+offset computations and function |
| ## definitions |
| ## (3) a second thunk is created when the first one goes out of range |
| ## (4) early calls to a dylib stub use a thunk, and later calls the stub |
| ## directly |
| ## Notes: |
| ## 0x4000000 = 64 Mi = half the magnitude of the forward-branch range |
| |
| # RUN: rm -rf %t; mkdir %t |
| # RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t/input.o |
| # RUN: %lld -arch arm64 -dead_strip -lSystem -o %t/thunk %t/input.o |
| # RUN: llvm-objdump -d --no-show-raw-insn %t/thunk | FileCheck %s |
| |
| # CHECK: Disassembly of section __TEXT,__text: |
| |
| # CHECK: [[#%.13x, A_PAGE:]][[#%.3x, A_OFFSET:]] <_a>: |
| # CHECK: bl 0x[[#%x, A:]] <_a> |
| # CHECK: bl 0x[[#%x, B:]] <_b> |
| # CHECK: bl 0x[[#%x, C:]] <_c> |
| # CHECK: bl 0x[[#%x, D_THUNK_0:]] <_d.thunk.0> |
| # CHECK: bl 0x[[#%x, E_THUNK_0:]] <_e.thunk.0> |
| # CHECK: bl 0x[[#%x, F_THUNK_0:]] <_f.thunk.0> |
| # CHECK: bl 0x[[#%x, G_THUNK_0:]] <_g.thunk.0> |
| # CHECK: bl 0x[[#%x, H_THUNK_0:]] <_h.thunk.0> |
| # CHECK: bl 0x[[#%x, NAN_THUNK_0:]] <___nan.thunk.0> |
| |
| # CHECK: [[#%.13x, B_PAGE:]][[#%.3x, B_OFFSET:]] <_b>: |
| # CHECK: bl 0x[[#%x, A]] <_a> |
| # CHECK: bl 0x[[#%x, B]] <_b> |
| # CHECK: bl 0x[[#%x, C]] <_c> |
| # CHECK: bl 0x[[#%x, D_THUNK_0]] <_d.thunk.0> |
| # CHECK: bl 0x[[#%x, E_THUNK_0]] <_e.thunk.0> |
| # CHECK: bl 0x[[#%x, F_THUNK_0]] <_f.thunk.0> |
| # CHECK: bl 0x[[#%x, G_THUNK_0]] <_g.thunk.0> |
| # CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0> |
| # CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0> |
| |
| # CHECK: [[#%.13x, C_PAGE:]][[#%.3x, C_OFFSET:]] <_c>: |
| # CHECK: bl 0x[[#%x, A]] <_a> |
| # CHECK: bl 0x[[#%x, B]] <_b> |
| # CHECK: bl 0x[[#%x, C]] <_c> |
| # CHECK: bl 0x[[#%x, D:]] <_d> |
| # CHECK: bl 0x[[#%x, E:]] <_e> |
| # CHECK: bl 0x[[#%x, F_THUNK_0]] <_f.thunk.0> |
| # CHECK: bl 0x[[#%x, G_THUNK_0]] <_g.thunk.0> |
| # CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0> |
| # CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0> |
| |
| # CHECK: [[#%x, D_THUNK_0]] <_d.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, D_PAGE:]] |
| # CHECK: add x16, x16, #[[#D_OFFSET:]] |
| |
| # CHECK: [[#%x, E_THUNK_0]] <_e.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, E_PAGE:]] |
| # CHECK: add x16, x16, #[[#E_OFFSET:]] |
| |
| # CHECK: [[#%x, F_THUNK_0]] <_f.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, F_PAGE:]] |
| # CHECK: add x16, x16, #[[#F_OFFSET:]] |
| |
| # CHECK: [[#%x, G_THUNK_0]] <_g.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, G_PAGE:]] |
| # CHECK: add x16, x16, #[[#G_OFFSET:]] |
| |
| # CHECK: [[#%x, H_THUNK_0]] <_h.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, H_PAGE:]] |
| # CHECK: add x16, x16, #[[#H_OFFSET:]] |
| |
| # CHECK: [[#%x, NAN_THUNK_0]] <___nan.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, NAN_PAGE:]] |
| # CHECK: add x16, x16, #[[#NAN_OFFSET:]] |
| |
| # CHECK: [[#%x, D_PAGE + D_OFFSET]] <_d>: |
| # CHECK: bl 0x[[#%x, A]] <_a> |
| # CHECK: bl 0x[[#%x, B]] <_b> |
| # CHECK: bl 0x[[#%x, C]] <_c> |
| # CHECK: bl 0x[[#%x, D]] <_d> |
| # CHECK: bl 0x[[#%x, E]] <_e> |
| # CHECK: bl 0x[[#%x, F_THUNK_0]] <_f.thunk.0> |
| # CHECK: bl 0x[[#%x, G_THUNK_0]] <_g.thunk.0> |
| # CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0> |
| # CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0> |
| |
| # CHECK: [[#%x, E_PAGE + E_OFFSET]] <_e>: |
| # CHECK: bl 0x[[#%x, A_THUNK_0:]] <_a.thunk.0> |
| # CHECK: bl 0x[[#%x, B_THUNK_0:]] <_b.thunk.0> |
| # CHECK: bl 0x[[#%x, C]] <_c> |
| # CHECK: bl 0x[[#%x, D]] <_d> |
| # CHECK: bl 0x[[#%x, E]] <_e> |
| # CHECK: bl 0x[[#%x, F:]] <_f> |
| # CHECK: bl 0x[[#%x, G:]] <_g> |
| # CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0> |
| # CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0> |
| |
| # CHECK: [[#%x, F_PAGE + F_OFFSET]] <_f>: |
| # CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0> |
| # CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0> |
| # CHECK: bl 0x[[#%x, C]] <_c> |
| # CHECK: bl 0x[[#%x, D]] <_d> |
| # CHECK: bl 0x[[#%x, E]] <_e> |
| # CHECK: bl 0x[[#%x, F]] <_f> |
| # CHECK: bl 0x[[#%x, G]] <_g> |
| # CHECK: bl 0x[[#%x, H_THUNK_0]] <_h.thunk.0> |
| # CHECK: bl 0x[[#%x, NAN_THUNK_0]] <___nan.thunk.0> |
| |
| # CHECK: [[#%x, G_PAGE + G_OFFSET]] <_g>: |
| # CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0> |
| # CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0> |
| # CHECK: bl 0x[[#%x, C_THUNK_0:]] <_c.thunk.0> |
| # CHECK: bl 0x[[#%x, D_THUNK_1:]] <_d.thunk.1> |
| # CHECK: bl 0x[[#%x, E]] <_e> |
| # CHECK: bl 0x[[#%x, F]] <_f> |
| # CHECK: bl 0x[[#%x, G]] <_g> |
| # CHECK: bl 0x[[#%x, H:]] <_h> |
| # CHECK: bl 0x[[#%x, STUBS:]] |
| |
| # CHECK: [[#%x, A_THUNK_0]] <_a.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, A_PAGE]]000 |
| # CHECK: add x16, x16, #[[#%d, A_OFFSET]] |
| |
| # CHECK: [[#%x, B_THUNK_0]] <_b.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, B_PAGE]]000 |
| # CHECK: add x16, x16, #[[#%d, B_OFFSET]] |
| |
| # CHECK: [[#%x, H_PAGE + H_OFFSET]] <_h>: |
| # CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0> |
| # CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0> |
| # CHECK: bl 0x[[#%x, C_THUNK_0]] <_c.thunk.0> |
| # CHECK: bl 0x[[#%x, D_THUNK_1]] <_d.thunk.1> |
| # CHECK: bl 0x[[#%x, E]] <_e> |
| # CHECK: bl 0x[[#%x, F]] <_f> |
| # CHECK: bl 0x[[#%x, G]] <_g> |
| # CHECK: bl 0x[[#%x, H]] <_h> |
| # CHECK: bl 0x[[#%x, STUBS]] |
| |
| # CHECK: <_main>: |
| # CHECK: bl 0x[[#%x, A_THUNK_0]] <_a.thunk.0> |
| # CHECK: bl 0x[[#%x, B_THUNK_0]] <_b.thunk.0> |
| # CHECK: bl 0x[[#%x, C_THUNK_0]] <_c.thunk.0> |
| # CHECK: bl 0x[[#%x, D_THUNK_1]] <_d.thunk.1> |
| # CHECK: bl 0x[[#%x, E_THUNK_1:]] <_e.thunk.1> |
| # CHECK: bl 0x[[#%x, F_THUNK_1:]] <_f.thunk.1> |
| # CHECK: bl 0x[[#%x, G]] <_g> |
| # CHECK: bl 0x[[#%x, H]] <_h> |
| # CHECK: bl 0x[[#%x, STUBS]] |
| |
| # CHECK: [[#%x, C_THUNK_0]] <_c.thunk.0>: |
| # CHECK: adrp x16, 0x[[#%x, C_PAGE]]000 |
| # CHECK: add x16, x16, #[[#%d, C_OFFSET]] |
| |
| # CHECK: [[#%x, D_THUNK_1]] <_d.thunk.1>: |
| # CHECK: adrp x16, 0x[[#%x, D_PAGE]] |
| # CHECK: add x16, x16, #[[#D_OFFSET]] |
| |
| # CHECK: [[#%x, E_THUNK_1]] <_e.thunk.1>: |
| # CHECK: adrp x16, 0x[[#%x, E_PAGE]] |
| # CHECK: add x16, x16, #[[#E_OFFSET]] |
| |
| # CHECK: [[#%x, F_THUNK_1]] <_f.thunk.1>: |
| # CHECK: adrp x16, 0x[[#%x, F_PAGE]] |
| # CHECK: add x16, x16, #[[#F_OFFSET]] |
| |
| # CHECK: Disassembly of section __TEXT,__stubs: |
| |
| # CHECK: [[#%x, NAN_PAGE + NAN_OFFSET]] <__stubs>: |
| |
| .subsections_via_symbols |
| .text |
| |
| .globl _a |
| .p2align 2 |
| _a: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| ret |
| |
| .globl _b |
| .p2align 2 |
| _b: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| .space 0x4000000-0x3c |
| ret |
| |
| .globl _c |
| .p2align 2 |
| _c: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| ret |
| |
| .globl _d |
| .p2align 2 |
| _d: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| .space 0x4000000-0x38 |
| ret |
| |
| .globl _e |
| .p2align 2 |
| _e: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| ret |
| |
| .globl _f |
| .p2align 2 |
| _f: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| .space 0x4000000-0x34 |
| ret |
| |
| .globl _g |
| .p2align 2 |
| _g: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| ret |
| |
| .globl _h |
| .p2align 2 |
| _h: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| .space 0x4000000-0x30 |
| ret |
| |
| .globl _main |
| .p2align 2 |
| _main: |
| bl _a |
| bl _b |
| bl _c |
| bl _d |
| bl _e |
| bl _f |
| bl _g |
| bl _h |
| bl ___nan |
| ret |