1## This reproduces a bug when rewriting dynamic relocations in X86 as 2## BOLT incorrectly attributes R_X86_64_64 dynamic relocations 3## to the wrong section when the -jump-tables=move flag is used. We 4## expect the relocations to belong to the .bolt.org.rodata section but 5## it is attributed to a new .rodata section that only contains jump 6## table entries, created by BOLT. BOLT will only create this new .rodata 7## section if both -jump-tables=move is used and a hot function with 8## jt is present in the input binary, triggering a scenario where the 9## dynamic relocs rewriting gets confused on where to put .rodata relocs. 10 11## It is uncommon to end up with dynamic relocations against .rodata, 12## but it can happen. In these cases we cannot corrupt the 13## output binary by writing out dynamic relocs incorrectly. The linker 14## avoids emitting relocs against read-only sections but we override 15## this behavior with the -z notext flag. During runtime, these pages 16## are mapped with write permission and then changed to read-only after 17## the dynamic linker finishes processing the dynamic relocs. 18 19## In this test, we create a reference to a dynamic object that will 20## imply in R_X86_64_64 being used for .rodata. Now BOLT, when creating 21## a new .rodata to hold jump table entries, needs to remember to emit 22## these dynamic relocs against the original .rodata, and not the new 23## one it just created. 24 25# REQUIRES: system-linux 26 27# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux \ 28# RUN: %s -o %t.o 29# RUN: link_fdata %s %t.o %t.fdata 30# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux \ 31# RUN: %p/Inputs/define_bar.s -o %t.2.o 32# RUN: llvm-strip --strip-unneeded %t.o 33# RUN: ld.lld %t.2.o -o %t.so -shared 34# RUN: ld.lld -z notext %t.o -o %t.exe -q %t.so 35# RUN: llvm-bolt -data %t.fdata %t.exe -relocs -o %t.out -lite=0 \ 36# RUN: -jump-tables=move 37# RUN: llvm-readobj -rs %t.out | FileCheck --check-prefix=READOBJ %s 38 39## Verify that BOLT outputs the dynamic reloc at the correct address, 40## which is the start of the .bolt.org.rodata section. 41# READOBJ: Relocations [ 42# READOBJ: Section ([[#]]) .rela.dyn { 43# READOBJ-NEXT: 0x[[#%X,ADDR:]] R_X86_64_64 bar 0x10 44# READOBJ: Symbols [ 45# READOBJ: Name: .bolt.org.rodata 46# READOBJ-NEXT: Value: 0x[[#ADDR]] 47 48 # Create a hot function with jump table 49 .text 50 .globl _start 51 .type _start, %function 52_start: 53 .cfi_startproc 54# FDATA: 0 [unknown] 0 1 _start 0 0 6 55 movq .LJUMPTABLE(,%rdi,8), %rax 56b: jmpq *%rax 57# FDATA: 1 _start #b# 1 _start #c# 0 3 58c: 59 mov $1, %rax 60d: 61 xorq %rax, %rax 62 ret 63 .cfi_endproc 64 .size _start, .-_start 65 66 # This is the section that needs to be tested. 67 .section .rodata 68 .align 4 69 # We will have a R_X86_64_64 here or R_X86_64_COPY if this section 70 # is non-writable. We use -z notext to force the linker to accept dynamic 71 # relocations in read-only sections and make it a R_X86_64_64. 72 .quad bar + 16 # Reference a dynamic object (such as a vtable ref) 73 # Add other contents to this section: a hot jump table that will be 74 # copied by BOLT into a new section. 75.LJUMPTABLE: 76 .quad c 77 .quad c 78 .quad d 79 .quad d 80