133 lines · plain
1## Check cases when the first PIC jump table entries of one function can be2## interpreted as valid last entries of the previous function.3 4## Conditions to trigger the bug: Function A and B have jump tables that5## are adjacent in memory. We run in lite relocation mode. Function B6## is not disassembled because it does not have profile. Function A7## triggers a special conditional that forced BOLT to rewrite its jump8## table in-place (instead of moving it) because it is marked as9## non-simple (in this case, containing unknown control flow). The10## first entry of B's jump table (a PIC offset) happens to be a valid11## address inside A when added to A's jump table base address. In this12## case, BOLT could overwrite B's jump table, corrupting it, thinking13## the first entry of it is actually part of A's jump table.14 15# REQUIRES: system-linux16 17# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \18# RUN: %s -o %t.o19# RUN: link_fdata %s %t.o %t.fdata20# RUN: llvm-strip --strip-unneeded %t.o21# RUN: ld.lld %t.o -o %t.exe -q -T %S/Inputs/jt-pic-linkerscript.ld22# RUN: llvm-bolt %t.exe -relocs -o %t.out -data %t.fdata \23# RUN: -lite=124# RUN: llvm-readelf -S %t.out | FileCheck --check-prefix=CHECK %s25# The output binary is runnable, but we check for test success with26# readelf. This is another way to check this bug:27# COM: %t.out28 29## BOLT needs to create a new rodata section, indicating that it30## successfully moved the jump table in _start.31# CHECK: [{{.*}}] .bolt.org.rodata32 33 .globl _start34 .type _start, %function35_start:36 .cfi_startproc37# FDATA: 0 [unknown] 0 1 _start 0 0 138 push %rbp39 mov %rsp, %rbp40 mov 0x8(%rbp), %rdi41 cmpq $3, %rdi42 ja .L543 jmp .L644## Unreachable code, here to mark this function as non-simple45## (containing unknown control flow) with a stray indirect jmp46 jmp *%rax47.L6:48 decq %rdi49 leaq .LJT1(%rip), %rcx50 movslq (%rcx, %rdi, 4), %rax51 addq %rcx, %rax52 jmp *%rax53.L1:54 leaq str1(%rip), %rsi55 jmp .L456.L2:57 leaq str2(%rip), %rsi58 jmp .L459.L3:60 leaq str3(%rip), %rsi61 jmp .L462.L5:63 leaq str4(%rip), %rsi64.L4:65 movq $1, %rdi66 movq $10, %rdx67 movq $1, %rax68 syscall69 mov 0x8(%rbp), %rdi70 decq %rdi71 callq func_b72 movq %rax, %rdi73 movq $231, %rax74 syscall75 pop %rbp76 ret77 .cfi_endproc78 .size _start, .-_start79 80 .globl func_b81 .type func_b, %function82func_b:83 .cfi_startproc84 push %rbp85 mov %rsp, %rbp86 cmpq $3, %rdi87 ja .L2_688# FT89 leaq .LJT2(%rip), %rcx90 movslq (%rcx, %rdi, 4), %rax91 addq %rcx, %rax92 jmp *%rax93.L2_1:94 movq $0, %rax95 jmp .L2_596.L2_2:97 movq $1, %rax98 jmp .L2_599.L2_3:100 movq $2, %rax101 jmp .L2_5102.L2_4:103 movq $3, %rax104 jmp .L2_5105.L2_6:106 movq $-1, %rax107.L2_5:108 popq %rbp109 ret110 .cfi_endproc111 .size func_b, .-func_b112 113 .rodata114str1: .asciz "Message 1\n"115str2: .asciz "Message 2\n"116str3: .asciz "Message 3\n"117str4: .asciz "Highrange\n"118## Special case where the first .LJT2 entry is a valid offset of119## _start when interpreted with .LJT1 as a base address.120.LJT1:121 .long .L1-.LJT1122 .long .L2-.LJT1123 .long .L3-.LJT1124 .long .L3-.LJT1125 .long .L3-.LJT1126 .long .L3-.LJT1127 .long .L3-.LJT1128.LJT2:129 .long .L2_1-.LJT2130 .long .L2_2-.LJT2131 .long .L2_3-.LJT2132 .long .L2_4-.LJT2133