| ## Promote unmarked code after a CFI-bounded predecessor into __BOLT_UNMARKED_TAIL. |
| ## Covers: |
| ## 1) FDE-only region (no symtab entry; BOLT names it __BOLT_FDE_FUNC* or .text/N) |
| ## 2) Named function (FDE range == symbol size) -> named_sub + tail |
| ## Caller is in a separate section; -Wl,-q keeps PC-relative relocs on the bl. |
| |
| # RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o |
| # RUN: %clang %cflags %t.o -pie -Wl,-q -o %t.exe |
| # RUN: llvm-bolt %t.exe -o %t.bolt --print-disasm -v=1 2>&1 | FileCheck %s |
| |
| # CHECK-COUNT-3: BOLT-WARNING: detected executable code after CFI-bounded function |
| # CHECK-SAME: creating synthetic function __BOLT_UNMARKED_TAILat |
| # CHECK-SAME: Consider adding a symbol or FDE for this code. |
| |
| ## Scenario 1a: FDE-only predecessor at the section start (named after .text). |
| ## The tail has trailing filler nops after its ret: they are trimmed from the |
| ## callable Size but remain part of MaxSize slack. |
| # CHECK: Binary Function ".text/{{[0-9]+}}" after disassembly |
| # CHECK: Size : 0x14 |
| # CHECK: MaxSize : 0x14 |
| # CHECK: Binary Function "{{.*}}__BOLT_UNMARKED_TAIL{{.*}}" after disassembly |
| # CHECK: Size : 0x8 |
| # CHECK: MaxSize : 0x10 |
| |
| ## Scenario 1b: FDE-only predecessor discovered from the FDE alone. |
| # CHECK: Binary Function "__BOLT_FDE_FUNC{{.*}}" after disassembly |
| # CHECK: Size : 0x14 |
| # CHECK: MaxSize : 0x14 |
| # CHECK: Binary Function "{{.*}}__BOLT_UNMARKED_TAIL{{.*}}" after disassembly |
| # CHECK: Size : 0x8 |
| # CHECK: MaxSize : 0x8 |
| |
| ## Scenario 2: named predecessor (FDE address range matches .size). |
| # CHECK: Binary Function "named_sub" after disassembly |
| # CHECK: Size : 0x14 |
| # CHECK: MaxSize : 0x14 |
| # CHECK: Binary Function "{{.*}}__BOLT_UNMARKED_TAIL{{.*}}" after disassembly |
| # CHECK: Size : 0x10 |
| # CHECK: MaxSize : 0x10 |
| |
| # CHECK-COUNT-3: bl __BOLT_UNMARKED_TAILat{{.*}} |
| |
| .section .text.fdeonly,"ax",@progbits |
| |
| ## Scenario 1a: FDE-only predecessor at the section start (no symbol table entry). |
| .Lfde_sub: |
| .cfi_startproc |
| stp x29, x30, [sp, #-16]! |
| mov x29, sp |
| mov w0, #42 |
| ldp x29, x30, [sp], #16 |
| ret |
| .cfi_endproc |
| |
| .Ltail_after_fde: |
| nop |
| ret |
| nop |
| nop |
| |
| ## Scenario 1b: identical FDE-only region, not at the section start. |
| .Lfde_sub2: |
| .cfi_startproc |
| stp x29, x30, [sp, #-16]! |
| mov x29, sp |
| mov w0, #42 |
| ldp x29, x30, [sp], #16 |
| ret |
| .cfi_endproc |
| |
| .Ltail_after_fde2: |
| nop |
| ret |
| |
| .section .text.named,"ax",@progbits |
| |
| ## Scenario 2: named predecessor (FDE address range matches .size). |
| .globl named_sub |
| .type named_sub, %function |
| named_sub: |
| .cfi_startproc |
| stp x29, x30, [sp, #-16]! |
| mov x29, sp |
| mov w0, #7 |
| ldp x29, x30, [sp], #16 |
| ret |
| .cfi_endproc |
| .size named_sub, .-named_sub |
| |
| .Ltail_after_named: |
| mov x0, x0 |
| mov w1, #7 |
| add w0, w0, w1 |
| ret |
| |
| .section .text.entry,"ax",@progbits |
| |
| .globl _start |
| .type _start, %function |
| _start: |
| .cfi_startproc |
| stp x29, x30, [sp, #-16]! |
| mov x29, sp |
| bl .Ltail_after_fde |
| bl .Ltail_after_fde2 |
| bl .Ltail_after_named |
| ldp x29, x30, [sp], #16 |
| mov w0, #0 |
| ret |
| .cfi_endproc |
| .size _start, .-_start |