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