| // Test how BOLT handles indirect branch sequence of instructions in |
| // AArch64MCPlus builder. |
| |
| // clang-format off |
| |
| // REQUIRES: system-linux, asserts |
| |
| // RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown -mattr=+pauth %s -o %t.o |
| // RUN: %clang %cflags --target=aarch64-unknown-linux %t.o -o %t.exe -Wl,-q |
| // RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg --debug-only=mcplus -v=1 2>&1 \ |
| // RUN: | FileCheck %s |
| |
| // Pattern 1: there is no shift amount after the 'add' instruction. |
| // |
| // adr x6, 0x219fb0 <sigall_set+0x88> |
| // add x6, x6, x14, lsl #2 |
| // ldr w7, [x6] |
| // add x6, x6, w7, sxtw => no shift amount |
| // br x6 |
| // |
| |
| // Pattern 2: nop/adr pair is used in place of adrp/add |
| // |
| // nop => nop/adr instead of adrp/add |
| // adr x13, 0x215a18 <_nl_value_type_LC_COLLATE+0x50> |
| // ldrh w13, [x13, w12, uxtw #1] |
| // adr x12, 0x247b30 <__gettextparse+0x5b0> |
| // add x13, x12, w13, sxth #2 |
| // br x13 |
| |
| .section .text |
| .align 4 |
| .globl _start |
| .type _start, %function |
| _start: |
| bl test1 |
| bl test2 |
| // mov x0, #4 |
| // mov w8, #93 |
| // svc #0 |
| |
| // Pattern 1 |
| // CHECK: BOLT-DEBUG: failed to match indirect branch: ShiftVAL != 2 |
| .globl test1 |
| .type test1, %function |
| test1: |
| mov x1, #0 |
| nop |
| adr x3, datatable |
| add x3, x3, x1, lsl #2 |
| ldr w2, [x3] |
| add x3, x3, w2, sxtw |
| br x3 |
| test1_0: |
| ret |
| test1_1: |
| ret |
| test1_2: |
| ret |
| .size test1, .-test1 |
| |
| // Temporary workaround for PC-relative relocations from datatable leaking into |
| // test2 function and creating phantom entry points. |
| .skip 0x100 |
| |
| // Pattern 2 |
| // CHECK: BOLT-DEBUG: failed to match indirect branch: nop/adr instead of adrp/add |
| .globl test2 |
| .type test2, %function |
| test2: |
| nop |
| adr x3, jump_table |
| ldrh w3, [x3, x1, lsl #1] |
| nop |
| adr x1, test2_0 |
| add x3, x1, w3, sxth #2 |
| br x3 |
| test2_0: |
| ret |
| test2_1: |
| ret |
| |
| // Make sure BOLT does not crash trying to disassemble BRA* instructions. |
| .globl test_braa |
| .type test_braa, %function |
| test_braa: |
| braa x0, x1 |
| |
| .globl test_brab |
| .type test_brab, %function |
| test_brab: |
| brab x0, x1 |
| |
| .globl test_braaz |
| .type test_braaz, %function |
| test_braaz: |
| braaz x0 |
| |
| .globl test_brabz |
| .type test_brabz, %function |
| test_brabz: |
| brabz x0 |
| |
| .section .rodata,"a",@progbits |
| datatable: |
| .word test1_0-datatable |
| .word test1_1-datatable |
| .word test1_2-datatable |
| |
| jump_table: |
| .hword (test2_0-test2_0)>>2 |
| .hword (test2_1-test2_0)>>2 |