|
| 1 | +## Test the different ways of hooking the init function for instrumentation (via |
| 2 | +## entry point, DT_INIT and via DT_INIT_ARRAY). We test the latter for both PIE |
| 3 | +## and non-PIE binaries because of the different ways of handling relocations |
| 4 | +## (static or dynamic), executable and shared library. |
| 5 | +## All tests perform the following steps: |
| 6 | +## - Compile and link for the case to be tested |
| 7 | +## - Some sanity-checks on the dynamic section and relocations in the binary to |
| 8 | +## verify it has the shape we want for testing: |
| 9 | +## - INTERP in Program Headers |
| 10 | +## - DT_INIT or DT_INIT_ARRAY in dynamic section |
| 11 | +## - No relative relocations for non-PIE |
| 12 | +## - Instrument (with extra --runtime-lib-init-hook=init/init_array options |
| 13 | +## in some cases) |
| 14 | +## - Verify generated binary |
| 15 | +# REQUIRES: system-linux,bolt-runtime,target=aarch64{{.*}} |
| 16 | + |
| 17 | +# RUN: %clang %cflags -pie %s -Wl,-q -o %t.exe |
| 18 | +# RUN: llvm-readelf -d %t.exe | FileCheck --check-prefix=DYN-INIT %s |
| 19 | +# RUN: llvm-readelf -l %t.exe | FileCheck --check-prefix=PH-INTERP %s |
| 20 | +# RUN: llvm-readelf -r %t.exe | FileCheck --check-prefix=RELOC-PIE %s |
| 21 | +# RUN: llvm-bolt %t.exe -o %t --instrument |
| 22 | +# RUN: llvm-readelf -hdrs %t | FileCheck --check-prefix=CHECK-INIT-EP %s |
| 23 | +# RUN: llvm-bolt %t.exe -o %t-no-ep --instrument --runtime-lib-init-hook=init |
| 24 | +# RUN: llvm-readelf -hdrs %t-no-ep | FileCheck --check-prefix=CHECK-INIT-NO-EP %s |
| 25 | +# RUN: llvm-bolt %t.exe -o %t-no-ep --instrument --runtime-lib-init-hook=init_array |
| 26 | +# RUN: llvm-readelf -hdrs %t-no-ep | FileCheck --check-prefix=CHECK-INIT-ARRAY-NO-EP %s |
| 27 | + |
| 28 | +# RUN: %clang -shared %cflags -pie %s -Wl,-q -o %t-shared.exe |
| 29 | +# RUN: llvm-readelf -d %t-shared.exe | FileCheck --check-prefix=DYN-INIT %s |
| 30 | +# RUN: llvm-readelf -l %t-shared.exe | FileCheck --check-prefix=PH-INTERP-SHARED %s |
| 31 | +# RUN: llvm-readelf -r %t-shared.exe | FileCheck --check-prefix=RELOC-SHARED-PIE %s |
| 32 | +# RUN: llvm-bolt %t-shared.exe -o %t-shared --instrument |
| 33 | +# RUN: llvm-readelf -hdrs %t-shared | FileCheck --check-prefix=CHECK-SHARED-INIT %s |
| 34 | + |
| 35 | +# RUN: %clang %cflags -pie %s -Wl,-q,-init=0 -o %t-no-init.exe |
| 36 | +# RUN: llvm-readelf -d %t-no-init.exe | FileCheck --check-prefix=DYN-NO-INIT %s |
| 37 | +# RUN: llvm-readelf -l %t-no-init.exe | FileCheck --check-prefix=PH-INTERP %s |
| 38 | +# RUN: llvm-readelf -r %t-no-init.exe | FileCheck --check-prefix=RELOC-PIE %s |
| 39 | +# RUN: llvm-bolt %t-no-init.exe -o %t-no-init --instrument |
| 40 | +# RUN: llvm-readelf -hdrs %t-no-init | FileCheck --check-prefix=CHECK-NO-INIT-EP %s |
| 41 | +# RUN: llvm-bolt %t-no-init.exe -o %t-no-init-no-ep --instrument --runtime-lib-init-hook=init |
| 42 | +# RUN: llvm-readelf -hdrs %t-no-init-no-ep | FileCheck --check-prefix=CHECK-NO-INIT-NO-EP %s |
| 43 | + |
| 44 | +# RUN: %clang -shared %cflags -pie %s -Wl,-q,-init=0 -o %t-shared-no-init.exe |
| 45 | +# RUN: llvm-readelf -d %t-shared-no-init.exe | FileCheck --check-prefix=DYN-NO-INIT %s |
| 46 | +# RUN: llvm-readelf -l %t-shared-no-init.exe | FileCheck --check-prefix=PH-INTERP-SHARED %s |
| 47 | +# RUN: llvm-readelf -r %t-shared-no-init.exe | FileCheck --check-prefix=RELOC-SHARED-PIE %s |
| 48 | +# RUN: llvm-bolt %t-shared-no-init.exe -o %t-shared-no-init --instrument |
| 49 | +# RUN: llvm-readelf -drs %t-shared-no-init | FileCheck --check-prefix=CHECK-SHARED-NO-INIT %s |
| 50 | + |
| 51 | +## Create a dummy shared library to link against to force creation of the dynamic section. |
| 52 | +# RUN: %clang %cflags %p/../Inputs/stub.c -fPIC -shared -o %t-stub.so |
| 53 | +# RUN: %clang %cflags %s -no-pie -Wl,-q,-init=0 %t-stub.so -o %t-no-pie-no-init.exe |
| 54 | +# RUN: llvm-readelf -r %t-no-pie-no-init.exe | FileCheck --check-prefix=RELOC-NO-PIE %s |
| 55 | +# RUN: llvm-bolt %t-no-pie-no-init.exe -o %t-no-pie-no-init --instrument |
| 56 | +# RUN: llvm-readelf -hds %t-no-pie-no-init | FileCheck --check-prefix=CHECK-NO-PIE-NO-INIT-EP %s |
| 57 | + |
| 58 | +## With init: dynamic section should contain DT_INIT |
| 59 | +# DYN-INIT: (INIT) |
| 60 | + |
| 61 | +## Without init: dynamic section should only contain DT_INIT_ARRAY |
| 62 | +# DYN-NO-INIT-NOT: (INIT) |
| 63 | +# DYN-NO-INIT: (INIT_ARRAY) |
| 64 | +# DYN-NO-INIT: (INIT_ARRAYSZ) |
| 65 | + |
| 66 | +## With interp program header (executable) |
| 67 | +# PH-INTERP: Program Headers: |
| 68 | +# PH-INTERP: INTERP |
| 69 | + |
| 70 | +## Without interp program header (shared library) |
| 71 | +# PH-INTERP-SHARED: Program Headers: |
| 72 | +# PH-INTERP-SHARED-NOT: INTERP |
| 73 | + |
| 74 | +## With PIE: binary should have relative relocations |
| 75 | +# RELOC-PIE: R_AARCH64_RELATIVE |
| 76 | + |
| 77 | +## With PIE: binary should have relative relocations |
| 78 | +# RELOC-SHARED-PIE: R_AARCH64_ABS64 |
| 79 | + |
| 80 | +## Without PIE: binary should not have relative relocations |
| 81 | +# RELOC-NO-PIE-NOT: R_AARCH64_RELATIVE |
| 82 | + |
| 83 | +## Check that entry point address is set to __bolt_runtime_start for PIE executable with DT_INIT |
| 84 | +# CHECK-INIT-EP: ELF Header: |
| 85 | +# CHECK-INIT-EP: Entry point address: 0x[[#%x,EP_ADDR:]] |
| 86 | +## Check that the dynamic relocation at .init and .init_array were not patched |
| 87 | +# CHECK-INIT-EP: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 88 | +# CHECK-INIT-EP-NOT: (INIT) 0x[[#%x, EP_ADDR]] |
| 89 | +# CHECK-INIT-EP-NOT: (INIT_ARRAY) 0x[[#%x, EP_ADDR]] |
| 90 | +## Check that the new entry point address points to __bolt_runtime_start |
| 91 | +# CHECK-INIT-EP: Symbol table '.symtab' contains {{.*}} entries: |
| 92 | +# CHECK-INIT-EP: {{0+}}[[#%x, EP_ADDR]] {{.*}} __bolt_runtime_start |
| 93 | + |
| 94 | +## Check that DT_INIT address is set to __bolt_runtime_start for PIE executable with DT_INIT |
| 95 | +# CHECK-INIT-NO-EP: ELF Header: |
| 96 | +# CHECK-INIT-NO-EP: Entry point address: 0x[[#%x,EP_ADDR:]] |
| 97 | +## Read Dynamic section DT_INIT and DT_INIT_ARRAY entries |
| 98 | +# CHECK-INIT-NO-EP: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 99 | +# CHECK-INIT-NO-EP-DAG: (INIT) 0x[[#%x,INIT:]] |
| 100 | +# CHECK-INIT-NO-EP-DAG: (INIT_ARRAY) 0x[[#%x,INIT_ARRAY:]] |
| 101 | +## Check if ELF entry point address points to _start symbol and new DT_INIT entry points to __bolt_runtime_start |
| 102 | +# CHECK-INIT-NO-EP: Symbol table '.symtab' contains {{.*}} entries: |
| 103 | +# CHECK-INIT-NO-EP-DAG: {{0+}}[[#%x, EP_ADDR]] {{.*}} _start |
| 104 | +# CHECK-INIT-NO-EP-DAG: {{0+}}[[#%x, INIT]] {{.*}} __bolt_runtime_start |
| 105 | + |
| 106 | +## Check that 1st entry of DT_INIT_ARRAY is set to __bolt_runtime_start and DT_INIT was not changed |
| 107 | +# CHECK-INIT-ARRAY-NO-EP: ELF Header: |
| 108 | +# CHECK-INIT-ARRAY-NO-EP: Entry point address: 0x[[#%x,EP_ADDR:]] |
| 109 | +## Read Dynamic section DT_INIT and DT_INIT_ARRAY entries |
| 110 | +# CHECK-INIT-ARRAY-NO-EP: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 111 | +# CHECK-INIT-ARRAY-NO-EP-DAG: (INIT) 0x[[#%x,INIT:]] |
| 112 | +# CHECK-INIT-ARRAY-NO-EP-DAG: (INIT_ARRAY) 0x[[#%x,INIT_ARRAY:]] |
| 113 | +## Read the dynamic relocation from 1st entry of .init_array |
| 114 | +# CHECK-INIT-ARRAY-NO-EP: Relocation section '.rela.dyn' at offset {{.*}} contains {{.*}} entries |
| 115 | +# CHECK-INIT-ARRAY-NO-EP: {{0+}}[[#%x,INIT_ARRAY]] {{.*}} R_AARCH64_RELATIVE [[#%x,INIT_ADDR:]] |
| 116 | +# CHECK-INIT-ARRAY-NO-EP-NOT: {{0+}}[[#%x,INIT_ARRAY]] {{.*}} R_AARCH64_RELATIVE [[#%x,INIT]] |
| 117 | +## Check that 1st entry of .init_array points to __bolt_runtime_start |
| 118 | +# CHECK-INIT-ARRAY-NO-EP: Symbol table '.symtab' contains {{.*}} entries: |
| 119 | +# CHECK-INIT-ARRAY-NO-EP-DAG: {{0+}}[[#%x, EP_ADDR]] {{.*}} _start |
| 120 | +# CHECK-INIT-ARRAY-NO-EP-DAG: {{[0-9]]*}}: {{0+}}[[#%x, INIT_ADDR]] {{.*}} __bolt_runtime_start |
| 121 | + |
| 122 | +## Check that entry point address is set to __bolt_runtime_start for PIE executable without DT_INIT |
| 123 | +# CHECK-NO-INIT-EP: ELF Header: |
| 124 | +# CHECK-NO-INIT-EP: Entry point address: 0x[[#%x,EP_ADDR:]] |
| 125 | +## Check that the dynamic relocation at .init and .init_array were not patched |
| 126 | +# CHECK-NO-INIT-EP: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 127 | +# CHECK-NO-INIT-EP-NOT: (INIT) 0x[[#%x, EP_ADDR]] |
| 128 | +# CHECK-NO-INIT-EP-NOT: (INIT_ARRAY) 0x[[#%x, EP_ADDR]] |
| 129 | +## Check that the new entry point address points to __bolt_runtime_start |
| 130 | +# CHECK-NO-INIT-EP: Symbol table '.symtab' contains {{.*}} entries: |
| 131 | +# CHECK-NO-INIT-EP: {{0+}}[[#%x, EP_ADDR]] {{.*}} __bolt_runtime_start |
| 132 | + |
| 133 | +## Check that DT_INIT is set to __bolt_runtime_start for shared library with DT_INIT |
| 134 | +# CHECK-SHARED-INIT: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 135 | +# CHECK-SHARED-INIT-DAG: (INIT) 0x[[#%x, INIT:]] |
| 136 | +# CHECK-SHARED-INIT-DAG: (INIT_ARRAY) 0x[[#%x, INIT_ARRAY:]] |
| 137 | +## Check that the dynamic relocation at .init_array was not patched |
| 138 | +# CHECK-SHARED-INIT: Relocation section '.rela.dyn' at offset {{.*}} contains {{.*}} entries |
| 139 | +# CHECK-SHARED-INIT-NOT: {{0+}}[[#%x, INIT_ARRAY]] {{.*}} R_AARCH64_ABS64 {{0+}}[[#%x, INIT]] |
| 140 | +## Check that dynamic section DT_INIT points to __bolt_runtime_start |
| 141 | +# CHECK-SHARED-INIT: Symbol table '.symtab' contains {{.*}} entries: |
| 142 | +# CHECK-SHARED-INIT: {{0+}}[[#%x, INIT]] {{.*}} __bolt_runtime_start |
| 143 | + |
| 144 | +## Check that entry point address is set to __bolt_runtime_start for PIE executable without DT_INIT |
| 145 | +# CHECK-NO-INIT-NO-EP: ELF Header: |
| 146 | +# CHECK-NO-INIT-NO-EP: Entry point address: 0x[[#%x,EP_ADDR:]] |
| 147 | +# CHECK-NO-INIT-NO-EP: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 148 | +# CHECK-NO-INIT-NO-EP-NOT: (INIT) |
| 149 | +# CHECK-NO-INIT-NO-EP: (INIT_ARRAY) 0x[[#%x,INIT_ARRAY:]] |
| 150 | +## Read the dynamic relocation from 1st entry of .init_array |
| 151 | +# CHECK-NO-INIT-NO-EP: Relocation section '.rela.dyn' at offset {{.*}} contains {{.*}} entries |
| 152 | +# CHECK-NO-INIT-NO-EP: {{0+}}[[#%x,INIT_ARRAY]] {{.*}} R_AARCH64_RELATIVE [[#%x,INIT_ADDR:]] |
| 153 | +## Check that 1st entry of .init_array points to __bolt_runtime_start |
| 154 | +# CHECK-NO-INIT-NO-EP: Symbol table '.symtab' contains {{.*}} entries: |
| 155 | +# CHECK-NO-INIT-NO-EP-DAG: {{0+}}[[#%x, EP_ADDR]] {{.*}} _start |
| 156 | +# CHECK-NO-INIT-NO-EP-DAG: {{[0-9]]*}}: {{0+}}[[#%x, INIT_ADDR]] {{.*}} __bolt_runtime_start |
| 157 | + |
| 158 | +## Check that entry point address is set to __bolt_runtime_start for shared library without DT_INIT |
| 159 | +# CHECK-SHARED-NO-INIT: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 160 | +# CHECK-SHARED-NO-INIT-NOT: (INIT) |
| 161 | +# CHECK-SHARED-NO-INIT: (INIT_ARRAY) 0x[[#%x,INIT_ARRAY:]] |
| 162 | +## Read the dynamic relocation from 1st entry of .init_array |
| 163 | +# CHECK-SHARED-NO-INIT: Relocation section '.rela.dyn' at offset {{.*}} contains {{.*}} entries |
| 164 | +# CHECK-SHARED-NO-INIT: {{0+}}[[#%x, INIT_ARRAY]] {{.*}} R_AARCH64_ABS64 [[#%x,INIT_ADDR:]] |
| 165 | +## Check that 1st entry of .init_array points to __bolt_runtime_start |
| 166 | +# CHECK-SHARED-NO-INIT: Symbol table '.symtab' contains {{.*}} entries: |
| 167 | +# CHECK-SHARED-NO-INIT: {{[0-9]]*}}: {{0+}}[[#%x, INIT_ADDR]] {{.*}} __bolt_runtime_start |
| 168 | + |
| 169 | +## Check that entry point address is set to __bolt_runtime_start for non-PIE executable with DT_INIT |
| 170 | +# CHECK-NO-PIE-NO-INIT-EP: ELF Header: |
| 171 | +# CHECK-NO-PIE-NO-INIT-EP: Entry point address: 0x[[#%x,EP_ADDR:]] |
| 172 | +## Check that the dynamic relocation at .init and .init_array were not patched |
| 173 | +# CHECK-NO-PIE-NO-INIT-EP: Dynamic section at offset {{.*}} contains {{.*}} entries: |
| 174 | +# CHECK-NO-PIE-NO-INIT-EP-NOT: (INIT) 0x[[#%x, EP_ADDR]] |
| 175 | +# CHECK-NO-PIE-NO-INIT-EP-NOT: (INIT_ARRAY) 0x[[#%x, EP_ADDR]] |
| 176 | +## Check that the new entry point address points to __bolt_runtime_start |
| 177 | +# CHECK-NO-PIE-NO-INIT-EP: Symbol table '.symtab' contains {{.*}} entries: |
| 178 | +# CHECK-NO-PIE-NO-INIT-EP: {{0+}}[[#%x, EP_ADDR]] {{.*}} __bolt_runtime_start |
| 179 | + |
| 180 | + .globl _start |
| 181 | + .type _start, %function |
| 182 | +_start: |
| 183 | + # Dummy relocation to force relocation mode. |
| 184 | + .reloc 0, R_AARCH64_NONE |
| 185 | + ret |
| 186 | +.size _start, .-_start |
| 187 | + |
| 188 | + .globl _init |
| 189 | + .type _init, %function |
| 190 | +_init: |
| 191 | + ret |
| 192 | + .size _init, .-_init |
| 193 | + |
| 194 | + .globl _fini |
| 195 | + .type _fini, %function |
| 196 | +_fini: |
| 197 | + ret |
| 198 | + .size _fini, .-_fini |
| 199 | + |
| 200 | + .section .init_array,"aw" |
| 201 | + .align 3 |
| 202 | + .dword _init |
| 203 | + |
| 204 | + .section .fini_array,"aw" |
| 205 | + .align 3 |
| 206 | + .dword _fini |
0 commit comments