1## This test shows how llvm-readobj uses the hash table section to derive the 2## size of a dynamic symbol table. This allows dumping of the dynamic symbol 3## table in the event of an object without section headers. 4 5## Case 1a) Table size is derived from hash table, with DT_SYMTAB before DT_HASH. 6# RUN: yaml2obj --docnum=1 %s -o %t1a-64 -DBITS=64 \ 7# RUN: -DTAG1=DT_SYMTAB -DTAG2=DT_HASH -DVAL1=0x400 -DVAL2=0x600 8# RUN: llvm-strip --strip-sections %t1a-64 9# RUN: llvm-readobj --dyn-symbols %t1a-64 2>&1 | \ 10# RUN: FileCheck %s --check-prefixes=LLVM1,STRIP --implicit-check-not=warning: 11# RUN: llvm-readelf --dyn-symbols %t1a-64 2>&1 | \ 12# RUN: FileCheck %s --check-prefixes=GNU1,GNU1-STRIP --implicit-check-not=warning: 13# RUN: yaml2obj --docnum=1 %s -o %t1a-32 -DBITS=32 \ 14# RUN: -DTAG1=DT_SYMTAB -DTAG2=DT_HASH -DVAL1=0x400 -DVAL2=0x600 15# RUN: llvm-strip --strip-sections %t1a-32 16# RUN: llvm-readobj --dyn-symbols %t1a-32 2>&1 | \ 17# RUN: FileCheck %s --check-prefixes=LLVM1,STRIP --implicit-check-not=warning: 18# RUN: llvm-readelf --dyn-symbols %t1a-32 2>&1 | \ 19# RUN: FileCheck %s --check-prefixes=GNU1,GNU1-STRIP --implicit-check-not=warning: 20 21## 1b) Table size is derived from hash table, with DT_HASH before DT_SYMTAB. 22## We don't bother testing 32 and 64-bit here. The above cases show that reading 23## the nchain value is correct for all formats, and other tests show the basic 24## printing behaviour. 25# RUN: yaml2obj --docnum=1 %s -o %t1b-64 -DBITS=64 \ 26# RUN: -DTAG1=DT_HASH -DTAG2=DT_SYMTAB -DVAL1=0x600 -DVAL2=0x400 27# RUN: llvm-strip --strip-sections %t1b-64 28# RUN: llvm-readobj --dyn-symbols %t1b-64 2>&1 | \ 29# RUN: FileCheck %s --check-prefixes=LLVM1,STRIP --implicit-check-not=warning: 30# RUN: llvm-readelf --dyn-symbols %t1b-64 2>&1 | \ 31# RUN: FileCheck %s --check-prefixes=GNU1,GNU1-STRIP --implicit-check-not=warning: 32 33# LLVM1: DynamicSymbols [ 34# LLVM1-NEXT: Symbol { 35# LLVM1-NEXT: Name: (0) 36# LLVM1-NEXT: Value: 0x0 37# LLVM1-NEXT: Size: 0 38# LLVM1-NEXT: Binding: Local (0x0) 39# LLVM1-NEXT: Type: None (0x0) 40# LLVM1-NEXT: Other: 0 41# LLVM1-NEXT: Section: Undefined (0x0) 42# LLVM1-NEXT: } 43# LLVM1-NEXT: Symbol { 44# LLVM1-NEXT: Name: foo (5) 45# LLVM1-NEXT: Value: 0x100 46# LLVM1-NEXT: Size: 0 47# LLVM1-NEXT: Binding: Local (0x0) 48# LLVM1-NEXT: Type: Function (0x2) 49# LLVM1-NEXT: Other: 0 50# STRIP-NEXT: Section: <?> (0x1) 51# NOSTRIP-NEXT: Section: .text (0x1) 52# LLVM1-NEXT: } 53# LLVM1-NEXT: Symbol { 54# LLVM1-NEXT: Name: bar (1) 55# LLVM1-NEXT: Value: 0x200 56# LLVM1-NEXT: Size: 0 57# LLVM1-NEXT: Binding: Local (0x0) 58# LLVM1-NEXT: Type: Object (0x1) 59# LLVM1-NEXT: Other: 0 60# STRIP-NEXT: Section: <?> (0x2) 61# NOSTRIP-NEXT: Section: .data (0x2) 62# LLVM1-NEXT: } 63# LLVM1-NEXT: ] 64 65# GNU1-STRIP: Symbol table for image contains 3 entries: 66# GNU1-NOSTRIP: Symbol table '.dynsym' contains 3 entries: 67# GNU1-NEXT: Num: Value Size Type Bind Vis Ndx Name 68# GNU1-NEXT: 0: {{0*}}00000000 0 NOTYPE LOCAL DEFAULT UND 69# GNU1-NEXT: 1: {{0*}}00000100 0 FUNC LOCAL DEFAULT 1 foo 70# GNU1-NEXT: 2: {{0*}}00000200 0 OBJECT LOCAL DEFAULT 2 bar 71# GNU1-EMPTY: 72 73--- !ELF 74FileHeader: 75 Class: ELFCLASS[[BITS]] 76 Data: ELFDATA2LSB 77 Type: ET_DYN 78Sections: 79 - Name: .text 80 Type: SHT_PROGBITS 81 - Name: .data 82 Type: SHT_PROGBITS 83 - Name: .dynsym 84 Type: SHT_DYNSYM 85 Flags: [ SHF_ALLOC ] 86 Address: 0x400 87 AddressAlign: 0x400 88 - Name: .hash 89 Type: SHT_HASH 90 Flags: [ SHF_ALLOC ] 91 Address: 0x600 92 AddressAlign: 0x200 93 Bucket: [ 1 ] 94 Chain: [ 1, 2, 3 ] 95 - Name: .dynstr 96 Type: SHT_STRTAB 97 Flags: [ SHF_ALLOC ] 98 Address: 0x800 99 AddressAlign: 0x200 100 - Name: .dynamic 101 Type: SHT_DYNAMIC 102 Flags: [ SHF_ALLOC ] 103 Address: 0xA00 104 AddressAlign: 0x200 105 Entries: 106 - Tag: DT_STRTAB 107 Value: 0x800 108 - Tag: DT_STRSZ 109 Value: 9 110 - Tag: [[TAG1]] 111 Value: [[VAL1]] 112 - Tag: [[TAG2]] 113 Value: [[VAL2]] 114 - Tag: DT_NULL 115 Value: 0 116DynamicSymbols: 117 - Name: foo 118 Type: STT_FUNC 119 Section: .text 120 Value: 0x100 121 - Name: bar 122 Type: STT_OBJECT 123 Section: .data 124 Value: 0x200 125ProgramHeaders: 126 - Type: PT_LOAD 127 VAddr: 0 128 FirstSec: .text 129 LastSec: .data 130 - Type: PT_LOAD 131 VAddr: 0x400 132 FirstSec: .dynsym 133 LastSec: .dynamic 134 - Type: PT_DYNAMIC 135 VAddr: 0xA00 136 FirstSec: .dynamic 137 LastSec: .dynamic 138 139## Case 2: Table size from DT_HASH does not match size from section header. 140# RUN: yaml2obj --docnum=2 %s -o %t2-smaller -DCHAIN="[1, 2]" 141# RUN: llvm-readobj --dyn-symbols %t2-smaller 2>&1 | \ 142# RUN: FileCheck %s --check-prefixes=LLVM2,WARN \ 143# RUN: --implicit-check-not=warning: -DNCHAIN=2 144# RUN: llvm-readelf --dyn-symbols %t2-smaller 2>&1 | \ 145# RUN: FileCheck %s --check-prefixes=GNU2,WARN \ 146# RUN: --implicit-check-not=warning: -DNCHAIN=2 147 148# RUN: yaml2obj --docnum=2 %s -o %t2-larger -DCHAIN="[1, 2, 3, 4]" 149# RUN: llvm-readobj --dyn-symbols %t2-larger 2>&1 | \ 150# RUN: FileCheck %s --check-prefixes=LLVM2,LLVM2-MORE,LLVM2-ALL,WARN \ 151# RUN: --implicit-check-not=warning: -DNCHAIN=4 152# RUN: llvm-readelf --dyn-symbols %t2-larger 2>&1 | \ 153# RUN: FileCheck %s --check-prefixes=GNU2,GNU2-MORE,GNU2-ALL,WARN \ 154# RUN: --implicit-check-not=warning: -DNCHAIN=4 155 156# WARN: warning: '{{.*}}2-{{.*}}': hash table nchain ([[NCHAIN]]) differs from symbol count derived from SHT_DYNSYM section header (3) 157 158## Show we report a warning when the sh_entsize of the SHT_DYNSYM section is zero and therefore we are unable 159## to derive the number of dynamic symbols from SHT_DYNSYM section header. 160# RUN: yaml2obj --docnum=2 %s -o %t2-zero-entsize -DCHAIN="[1, 2, 3, 4]" -DENTSIZE=0 161# RUN: llvm-readobj --dyn-symbols %t2-zero-entsize 2>&1 | \ 162# RUN: FileCheck %s -DFILE=%t2-zero-entsize --check-prefixes=LLVM2,LLVM2-MORE,LLVM2-ALL,WARN-ENTSIZE \ 163# RUN: --implicit-check-not=warning: 164# RUN: llvm-readelf --dyn-symbols %t2-zero-entsize 2>&1 | \ 165# RUN: FileCheck %s -DFILE=%t2-zero-entsize --check-prefixes=GNU2,GNU2-MORE,GNU2-ALL,WARN-ENTSIZE \ 166# RUN: --implicit-check-not=warning: -DNCHAIN=4 167 168## WARN-ENTSIZE: warning: '[[FILE]]': SHT_DYNSYM section has sh_entsize == 0 169 170## Show there's no warning if the sizes match 171# RUN: yaml2obj --docnum=2 %s -o %t2-same -DCHAIN="[1, 2, 3]" 172# RUN: llvm-readobj --dyn-symbols %t2-same 2>&1 | \ 173# RUN: FileCheck %s --check-prefixes=LLVM2,LLVM2-MORE --implicit-check-not=warning: 174# RUN: llvm-readelf --dyn-symbols %t2-same 2>&1 | \ 175# RUN: FileCheck %s --check-prefixes=GNU2,GNU2-MORE \ 176# RUN: --implicit-check-not=warning: -DNCHAIN=3 177 178# LLVM2: DynamicSymbols [ 179# LLVM2-NEXT: Symbol { 180# LLVM2-NEXT: Name: (0) 181# LLVM2-NEXT: Value: 0x0 182# LLVM2-NEXT: Size: 0 183# LLVM2-NEXT: Binding: Local (0x0) 184# LLVM2-NEXT: Type: None (0x0) 185# LLVM2-NEXT: Other: 0 186# LLVM2-NEXT: Section: Undefined (0x0) 187# LLVM2-NEXT: } 188# LLVM2-NEXT: Symbol { 189# LLVM2-NEXT: Name: foo (9) 190# LLVM2-NEXT: Value: 0x100 191# LLVM2-NEXT: Size: 0 192# LLVM2-NEXT: Binding: Local (0x0) 193# LLVM2-NEXT: Type: Function (0x2) 194# LLVM2-NEXT: Other: 0 195# LLVM2-NEXT: Section: .text (0x1) 196# LLVM2-NEXT: } 197# LLVM2-MORE-NEXT: Symbol { 198# LLVM2-MORE-NEXT: Name: bar (5) 199# LLVM2-MORE-NEXT: Value: 0x200 200# LLVM2-MORE-NEXT: Size: 0 201# LLVM2-MORE-NEXT: Binding: Local (0x0) 202# LLVM2-MORE-NEXT: Type: Object (0x1) 203# LLVM2-MORE-NEXT: Other: 0 204# LLVM2-MORE-NEXT: Section: .data (0x2) 205# LLVM2-MORE-NEXT: } 206# LLVM2-ALL-NEXT: Symbol { 207# LLVM2-ALL-NEXT: Name: baz (1) 208# LLVM2-ALL-NEXT: Value: 0x300 209# LLVM2-ALL-NEXT: Size: 0 210# LLVM2-ALL-NEXT: Binding: Local (0x0) 211# LLVM2-ALL-NEXT: Type: Object (0x1) 212# LLVM2-ALL-NEXT: Other: 0 213# LLVM2-ALL-NEXT: Section: .data (0x2) 214# LLVM2-ALL-NEXT: } 215# LLVM2-NEXT: ] 216 217# GNU2: Symbol table '.dynsym' contains [[NCHAIN]] entries: 218# GNU2-NEXT: Num: Value Size Type Bind Vis Ndx Name 219# GNU2-NEXT: 0: {{0*}}00000000 0 NOTYPE LOCAL DEFAULT UND 220# GNU2-NEXT: 1: {{0*}}00000100 0 FUNC LOCAL DEFAULT 1 foo 221# GNU2-MORE-NEXT: 2: {{0*}}00000200 0 OBJECT LOCAL DEFAULT 2 bar 222# GNU2-ALL-NEXT: 3: {{0*}}00000300 0 OBJECT LOCAL DEFAULT 2 baz 223# GNU2-EMPTY: 224 225## In this YAML, we define 4 dynamic symbols (including the null symbol), but 226## constrain the .dynsym section header to say there are only 3. This means that 227## when a size of 4 is derived from the hash table, we still have a valid symbol 228## to dump. 229--- !ELF 230FileHeader: 231 Class: ELFCLASS64 232 Data: ELFDATA2LSB 233 Type: ET_DYN 234Sections: 235 - Name: .text 236 Type: SHT_PROGBITS 237 - Name: .data 238 Type: SHT_PROGBITS 239 - Name: .dynsym 240 Type: SHT_DYNSYM 241 Flags: [ SHF_ALLOC ] 242 ShSize: 0x48 243 Address: 0x400 244 AddressAlign: 0x400 245## 0x18 is the standard entsize value. 246 EntSize: [[ENTSIZE=0x18]] 247 - Name: .hash 248 Type: SHT_HASH 249 Flags: [ SHF_ALLOC ] 250 Address: 0x600 251 AddressAlign: 0x200 252 Bucket: [ 1 ] 253 Chain: [[CHAIN]] 254 - Name: .dynstr 255 Type: SHT_STRTAB 256 Flags: [ SHF_ALLOC ] 257 Address: 0x800 258 AddressAlign: 0x200 259 - Name: .dynamic 260 Type: SHT_DYNAMIC 261 Flags: [ SHF_ALLOC ] 262 Address: 0xA00 263 AddressAlign: 0x200 264 Entries: 265 - Tag: DT_SYMTAB 266 Value: 0x400 267 - Tag: DT_HASH 268 Value: 0x600 269 - Tag: DT_STRTAB 270 Value: 0x800 271 - Tag: DT_STRSZ 272 Value: 13 273 - Tag: DT_NULL 274 Value: 0 275DynamicSymbols: 276 - Name: foo 277 Type: STT_FUNC 278 Section: .text 279 Value: 0x100 280 - Name: bar 281 Type: STT_OBJECT 282 Section: .data 283 Value: 0x200 284 - Name: baz 285 Type: STT_OBJECT 286 Section: .data 287 Value: 0x300 288ProgramHeaders: 289 - Type: PT_LOAD 290 VAddr: 0 291 FirstSec: .text 292 LastSec: .data 293 - Type: PT_LOAD 294 VAddr: 0x400 295 FirstSec: .dynsym 296 LastSec: .dynamic 297 - Type: PT_DYNAMIC 298 VAddr: 0xA00 299 FirstSec: .dynamic 300 LastSec: .dynamic 301 302## Case 3: DT_HASH is missing. 303## Show that no warning occurs if there are section headers. 304# RUN: yaml2obj --docnum=1 %s -o %t3 -DTAG1=DT_SYMTAB -DVAL1=0x400 -DTAG2=DT_NULL -DVAL2=0 -DBITS=64 305# RUN: llvm-readobj --dyn-symbols %t3 2>&1 | \ 306# RUN: FileCheck %s --check-prefixes=LLVM1,NOSTRIP --implicit-check-not=warning: 307# RUN: llvm-readelf --dyn-symbols %t3 2>&1 | \ 308# RUN: FileCheck %s --check-prefixes=GNU1,GNU1-NOSTRIP --implicit-check-not=warning: 309 310## Show that size is treated as zero, if no section headers are present. 311# RUN: llvm-strip --strip-sections %t3 312# RUN: llvm-readobj --dyn-symbols %t3 2>&1 | \ 313# RUN: FileCheck %s --check-prefix=LLVM3 --implicit-check-not=warning: 314# RUN: llvm-readelf --dyn-symbols %t3 2>&1 | \ 315# RUN: FileCheck %s --implicit-check-not={{.}} --allow-empty 316 317# LLVM3: DynamicSymbols [ 318# LLVM3: ] 319 320## Case 4: The size of the dynamic symbol table, inferred from the hash table, is broken. 321## It is so large that symbol table goes past the end of the file. We have a dynamic 322## relocation which refers to a symbol with an index that is also too large to be 323## in the file. Check we report a warning when trying to dump this relocation. 324 325# RUN: yaml2obj --docnum=3 %s -o %t4.1 326 327## Remember the size of the output produced. 328# RUN: wc -c %t4.1 > %t4.out.gnu.txt 329# RUN: llvm-readelf --sections --dyn-relocations %t4.1 >> %t4.out.gnu.txt 2>&1 330# RUN: FileCheck %s -DFILE=%t4.1 --input-file=%t4.out.gnu.txt --check-prefix=BROKEN-NCHAIN-GNU 331 332# BROKEN-NCHAIN-GNU: [[#%u, FILESIZE:]] 333# BROKEN-NCHAIN-GNU: warning: '[[FILE]]': the size (0x17ffffffe8) of the dynamic symbol table at 0x[[#%x, DYNSYMOFF:]], derived from the hash table, goes past the end of the file (0x[[#%x, FILESIZE]]) and will be ignored 334 335# BROKEN-NCHAIN-GNU: [Nr] Name Type Address Off 336# BROKEN-NCHAIN-GNU: [ 1] .rela.plt RELA 0000000000001000 0000[[#%x, RELAOFF:]] 337# BROKEN-NCHAIN-GNU: [ 4] .dynsym DYNSYM 0000000000001078 0000[[#%x, DYNSYMOFF]] 338 339# BROKEN-NCHAIN-GNU: 'PLT' relocation section at offset 0x[[#%x, RELAOFF]] contains 24 bytes: 340# BROKEN-NCHAIN-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend 341# BROKEN-NCHAIN-GNU-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 4292739037: index is greater than or equal to the number of dynamic symbols (1) 342# BROKEN-NCHAIN-GNU-NEXT: 0000000000000000 ffddffdd00000000 R_X86_64_NONE <corrupt> + 0 343 344# RUN: wc -c %t4.1 > %t4.out.llvm.txt 345# RUN: llvm-readobj --sections --dyn-relocations %t4.1 2>&1 >> %t4.out.llvm.txt 2>&1 346# RUN: FileCheck %s -DFILE=%t4.1 --input-file=%t4.out.llvm.txt --check-prefix=BROKEN-NCHAIN-LLVM 347 348# BROKEN-NCHAIN-LLVM: [[#%u, FILESIZE:]] 349# BROKEN-NCHAIN-LLVM: warning: '[[FILE]]': the size (0x17ffffffe8) of the dynamic symbol table at 0x[[#%x, DYNSYMOFF:]], derived from the hash table, goes past the end of the file (0x[[#%x, FILESIZE]]) and will be ignored 350 351# BROKEN-NCHAIN-LLVM: Name: .dynsym 352# BROKEN-NCHAIN-LLVM-NEXT: Type: SHT_DYNSYM 353# BROKEN-NCHAIN-LLVM-NEXT: Flags [ 354# BROKEN-NCHAIN-LLVM-NEXT: SHF_ALLOC 355# BROKEN-NCHAIN-LLVM-NEXT: ] 356# BROKEN-NCHAIN-LLVM-NEXT: Address: 0x1078 357# BROKEN-NCHAIN-LLVM-NEXT: Offset: 0x[[#%X, DYNSYMOFF]] 358 359# BROKEN-NCHAIN-LLVM: Dynamic Relocations { 360# BROKEN-NCHAIN-LLVM-NEXT: warning: '[[FILE]]': unable to get name of the dynamic symbol with index 4292739037: index is greater than or equal to the number of dynamic symbols (1) 361# BROKEN-NCHAIN-LLVM-NEXT: 0x0 R_X86_64_NONE <corrupt> 0x0 362# BROKEN-NCHAIN-LLVM-NEXT: } 363 364--- !ELF 365FileHeader: 366 Class: ELFCLASS64 367 Data: ELFDATA2LSB 368 Type: ET_EXEC 369 Machine: EM_X86_64 370Sections: 371 - Name: .rela.plt 372 Type: SHT_RELA 373 Flags: [ SHF_ALLOC ] 374 Address: 0x1000 375 Relocations: 376 - Type: R_X86_64_NONE 377 Symbol: 0xFFDDFFDD 378 - Name: .dynamic 379 Type: SHT_DYNAMIC 380 Flags: [ SHF_ALLOC ] 381 Entries: 382 - Tag: DT_PLTRELSZ 383 Value: 0x18 384 - Tag: DT_JMPREL 385## 0x1000 - PT_LOAD's p_vaddr (0x1000) == 0x0. 386## 0x0 + PT_LOAD's p_offset (0x78) == .rela.plt section offset (0x78). 387 Value: 0x1000 388 - Tag: DT_PLTREL 389 Value: 0x7 ## 7 == DT_RELA 390 - Tag: DT_HASH 391## 0x1068 - PT_LOAD's p_vaddr (0x1000) == 0x68. 392## 0x68 + PT_LOAD's p_offset (0x78) == .hash section offset (0xE0). 393 Value: 0x1068 394 - Tag: DT_NULL 395 Value: 0x0 396 - Name: .hash 397 Type: SHT_HASH 398 Flags: [ SHF_ALLOC ] 399 Bucket: [ 0 ] 400 Chain: [ 0 ] 401 NChain: 0xFFFFFFFF 402DynamicSymbols: [] 403ProgramHeaders: 404 - Type: PT_LOAD 405 FirstSec: .rela.plt 406 LastSec: .hash 407 VAddr: 0x1000 408