1## Check how the GNU Hash section is dumped with --gnu-hash-table.
2
3# RUN: yaml2obj --docnum=1 -DBITS=64 %s -o %t.x64
4# RUN: yaml2obj --docnum=1 -DBITS=32 %s -o %t.x32
5
6# RUN: llvm-readobj --gnu-hash-table %t.x64 | FileCheck %s
7# RUN: llvm-readelf --gnu-hash-table %t.x64 | FileCheck %s
8
9# RUN: llvm-readobj --gnu-hash-table %t.x32 | FileCheck %s
10# RUN: llvm-readelf --gnu-hash-table %t.x32 | FileCheck %s
11
12# CHECK:      GnuHashTable {
13# CHECK-NEXT:   Num Buckets: 3
14# CHECK-NEXT:   First Hashed Symbol Index: 1
15# CHECK-NEXT:   Num Mask Words: 2
16# CHECK-NEXT:   Shift Count: 2
17# CHECK-NEXT:   Bloom Filter: [0x3, 0x4]
18# CHECK-NEXT:   Buckets: [5, 6, 7]
19# CHECK-NEXT:   Values: [0x8, 0x9, 0xA, 0xB]
20# CHECK-NEXT: }
21
22--- !ELF
23FileHeader:
24  Class: ELFCLASS[[BITS]]
25  Data:  ELFDATA2LSB
26  Type:  ET_DYN
27Sections:
28  - Name:  .gnu.hash
29    Type:  SHT_GNU_HASH
30    Flags: [ SHF_ALLOC ]
31    Header:
32      SymNdx: 0x1
33      Shift2: 0x2
34## The number of words in the Bloom filter. The value of 2 is no-op.
35      MaskWords: [[MASKWORDS=2]]
36## The number of hash buckets. The value of 3 is no-op.
37      NBuckets:  [[NBUCKETS=3]]
38    BloomFilter: [0x3, 0x4]
39    HashBuckets: [0x5, 0x6, 0x7]
40    HashValues:  [0x8, 0x9, 0xA, 0xB]
41  - Name:  .dynamic
42    Type:  SHT_DYNAMIC
43    Flags: [ SHF_ALLOC ]
44    Link:  .dynstr
45    Entries:
46      - Tag:   DT_GNU_HASH
47        Value: 0x0
48      - Tag:   DT_NULL
49        Value: 0x0
50DynamicSymbols:
51  - Name:    aaa
52    Binding: STB_GLOBAL
53  - Name:    bbb
54    Binding: STB_GLOBAL
55  - Name:    ccc
56    Binding: STB_GLOBAL
57  - Name:    ddd
58    Binding: STB_GLOBAL
59ProgramHeaders:
60  - Type:     PT_LOAD
61    Flags:    [ PF_R, PF_X ]
62    FirstSec: .gnu.hash
63    LastSec:  .dynamic
64
65## Check we report a warning if there is no dynamic symbol section in the object.
66
67# RUN: yaml2obj --docnum=2 %s -o %t.nodynsym
68# RUN: llvm-readobj --gnu-hash-table %t.nodynsym 2>&1 | FileCheck %s -DFILE=%t.nodynsym --check-prefix=NODYNSYM
69# RUN: llvm-readelf --gnu-hash-table %t.nodynsym 2>&1 | FileCheck %s -DFILE=%t.nodynsym --check-prefix=NODYNSYM
70
71# NODYNSYM:      GnuHashTable {
72# NODYNSYM-NEXT:   Num Buckets: 1
73# NODYNSYM-NEXT:   First Hashed Symbol Index: 0
74# NODYNSYM-NEXT:   Num Mask Words: 1
75# NODYNSYM-NEXT:   Shift Count: 0
76# NODYNSYM-NEXT:   Bloom Filter: [0x0]
77# NODYNSYM-NEXT:   Buckets: [0]
78# NODYNSYM-NEXT: warning: '[[FILE]]': unable to dump 'Values' for the SHT_GNU_HASH section: no dynamic symbol table found
79# NODYNSYM-NEXT: }
80
81--- !ELF
82FileHeader:
83  Class: ELFCLASS64
84  Data:  ELFDATA2LSB
85  Type:  ET_DYN
86Sections:
87  - Name:  .gnu.hash
88    Type:  SHT_GNU_HASH
89    Flags: [ SHF_ALLOC ]
90    Header:
91      SymNdx: 0x0
92      Shift2: 0x0
93    BloomFilter: [ 0x0 ]
94    HashBuckets: [ 0x0 ]
95    HashValues:  [ 0x0 ]
96  - Name:  .dynamic
97    Type:  SHT_DYNAMIC
98    Flags: [ SHF_ALLOC ]
99    Entries:
100      - Tag:   DT_GNU_HASH
101        Value: 0x0
102      - Tag:   DT_NULL
103        Value: 0x0
104ProgramHeaders:
105  - Type:     PT_LOAD
106    Flags:    [ PF_R, PF_X ]
107    FirstSec: .gnu.hash
108    LastSec:  .dynamic
109
110## Check what we do when the index of the first symbol in the dynamic symbol table
111## included in the hash table is larger than the number of dynamic symbols.
112
113# RUN: yaml2obj --docnum=3 %s -o %t.brokensymndx
114# RUN: llvm-readobj --gnu-hash-table %t.brokensymndx 2>&1 \
115# RUN:   | FileCheck %s -DFILE=%t.brokensymndx --check-prefix=SYMNDX
116# RUN: llvm-readelf --gnu-hash-table %t.brokensymndx 2>&1 \
117# RUN:   | FileCheck %s -DFILE=%t.brokensymndx --check-prefix=SYMNDX
118
119# SYMNDX:      GnuHashTable {
120# SYMNDX-NEXT:   Num Buckets: 1
121# SYMNDX-NEXT:   First Hashed Symbol Index: 2
122# SYMNDX-NEXT:   Num Mask Words: 1
123# SYMNDX-NEXT:   Shift Count: 0
124# SYMNDX-NEXT:   Bloom Filter: [0x1]
125# SYMNDX-NEXT:   Buckets: [2]
126# SYMNDX-NEXT: warning: '[[FILE]]': unable to dump 'Values' for the SHT_GNU_HASH section: the first hashed symbol index (2) is greater than or equal to the number of dynamic symbols (2)
127# SYMNDX-NEXT: }
128
129--- !ELF
130FileHeader:
131  Class: ELFCLASS64
132  Data:  ELFDATA2LSB
133  Type:  ET_DYN
134Sections:
135  - Name:  .gnu.hash
136    Type:  SHT_GNU_HASH
137    Flags: [ SHF_ALLOC ]
138    Header:
139      SymNdx: 0x2
140      Shift2: 0x0
141    BloomFilter: [ 0x1 ]
142    HashBuckets: [ 0x2 ]
143    HashValues:  [ 0x3 ]
144  - Name:  .dynamic
145    Type:  SHT_DYNAMIC
146    Flags: [ SHF_ALLOC ]
147    Link:  0
148    Entries:
149      - Tag:   DT_GNU_HASH
150        Value: 0x0
151      - Tag:   DT_NULL
152        Value: 0x0
153DynamicSymbols:
154  - Name:    aaa
155    Binding: STB_GLOBAL
156ProgramHeaders:
157  - Type:     PT_LOAD
158    Flags:    [ PF_R, PF_X ]
159    FirstSec: .gnu.hash
160    LastSec:  .dynamic
161
162## Check we emit a warning when the dynamic symbol table is empty.
163## A valid dynamic symbol table should have at least one symbol: the symbol with index 0.
164
165# RUN: yaml2obj --docnum=4 %s -o %t.emptydynsym
166# RUN: llvm-readobj --gnu-hash-table %t.emptydynsym 2>&1 \
167# RUN:   | FileCheck %s -DFILE=%t.emptydynsym --check-prefix=EMPTY-DYNSYM
168# RUN: llvm-readelf --gnu-hash-table %t.emptydynsym 2>&1 \
169# RUN:   | FileCheck %s -DFILE=%t.emptydynsym --check-prefix=EMPTY-DYNSYM
170
171# EMPTY-DYNSYM:      GnuHashTable {
172# EMPTY-DYNSYM-NEXT:   Num Buckets: 1
173# EMPTY-DYNSYM-NEXT:   First Hashed Symbol Index: 0
174# EMPTY-DYNSYM-NEXT:   Num Mask Words: 1
175# EMPTY-DYNSYM-NEXT:   Shift Count: 0
176# EMPTY-DYNSYM-NEXT:   Bloom Filter: [0x0]
177# EMPTY-DYNSYM-NEXT:   Buckets: [0]
178# EMPTY-DYNSYM-NEXT: warning: '[[FILE]]': unable to dump 'Values' for the SHT_GNU_HASH section: the dynamic symbol table is empty
179# EMPTY-DYNSYM-NEXT: }
180
181--- !ELF
182FileHeader:
183  Class: ELFCLASS64
184  Data:  ELFDATA2LSB
185  Type:  ET_DYN
186Sections:
187  - Name:  .gnu.hash
188    Type:  SHT_GNU_HASH
189    Flags: [ SHF_ALLOC ]
190    Header:
191      SymNdx: 0x0
192      Shift2: 0x0
193    BloomFilter: [ 0x0 ]
194    HashBuckets: [ 0x0 ]
195    HashValues:  [ 0x0 ]
196  - Name:  .dynamic
197    Type:  SHT_DYNAMIC
198    Flags: [ SHF_ALLOC ]
199    Link:  0
200    Entries:
201      - Tag:   DT_GNU_HASH
202        Value: 0x0
203      - Tag:   DT_NULL
204        Value: 0x0
205  - Name: .dynsym
206    Type: SHT_DYNSYM
207    Size: 0
208ProgramHeaders:
209  - Type:     PT_LOAD
210    Flags:    [ PF_R, PF_X ]
211    FirstSec: .gnu.hash
212    LastSec:  .dynamic
213
214## Linkers might produce an empty no-op SHT_GNU_HASH section when
215## there are no dynamic symbols or when all dynamic symbols are undefined.
216## Such sections normally have a single zero entry in the bloom
217## filter, a single zero entry in the hash bucket and no values.
218##
219## The index of the first symbol in the dynamic symbol table
220## included in the hash table can be set to the number of dynamic symbols,
221## which is one larger than the index of the last dynamic symbol.
222## For empty tables however, this value is unimportant and can be ignored.
223
224## Case A: set the index of the first symbol in the dynamic symbol table to
225##         the number of dynamic symbols.
226# RUN: yaml2obj --docnum=5 -DSYMNDX=0x1 %s -o %t.empty.1
227# RUN: llvm-readobj --gnu-hash-table %t.empty.1 2>&1 \
228# RUN:   | FileCheck %s -DFILE=%t.empty.1 -DSYMNDX=1 --check-prefix=EMPTY --implicit-check-not="warning:"
229# RUN: llvm-readelf --gnu-hash-table %t.empty.1 2>&1 \
230# RUN:   | FileCheck %s -DFILE=%t.empty.1 -DSYMNDX=1 --check-prefix=EMPTY --implicit-check-not="warning:"
231
232## Case B: set the index of the first symbol in the dynamic symbol table to
233##         an arbitrary value that is larger than the number of dynamic symbols.
234# RUN: yaml2obj --docnum=5 -DSYMNDX=0x2 %s -o %t.empty.2
235# RUN: llvm-readobj --gnu-hash-table %t.empty.2 2>&1 \
236# RUN:   | FileCheck %s -DFILE=%t.empty.2 -DSYMNDX=2 --check-prefix=EMPTY --implicit-check-not="warning:"
237# RUN: llvm-readelf --gnu-hash-table %t.empty.2 2>&1 \
238# RUN:   | FileCheck %s -DFILE=%t.empty.2 -DSYMNDX=2 --check-prefix=EMPTY --implicit-check-not="warning:"
239
240# EMPTY:      GnuHashTable {
241# EMPTY-NEXT:   Num Buckets: 1
242# EMPTY-NEXT:   First Hashed Symbol Index: [[SYMNDX]]
243# EMPTY-NEXT:   Num Mask Words: 1
244# EMPTY-NEXT:   Shift Count: 0
245# EMPTY-NEXT:   Bloom Filter: [0x0]
246# EMPTY-NEXT:   Buckets: [0]
247# EMPTY-NEXT:   Values: []
248# EMPTY-NEXT: }
249
250--- !ELF
251FileHeader:
252  Class: ELFCLASS64
253  Data:  ELFDATA2LSB
254  Type:  ET_DYN
255Sections:
256  - Name:  .gnu.hash
257    Type:  SHT_GNU_HASH
258    Flags: [ SHF_ALLOC ]
259    Header:
260      SymNdx: [[SYMNDX]]
261      Shift2: 0x0
262    BloomFilter: [ 0x0 ]
263    HashBuckets: [ 0x0 ]
264    HashValues:  [ ]
265  - Name:  .dynamic
266    Type:  SHT_DYNAMIC
267    Flags: [ SHF_ALLOC ]
268    Link:  0
269    Entries:
270      - Tag:   DT_GNU_HASH
271        Value: 0x0
272      - Tag:   DT_NULL
273        Value: 0x0
274DynamicSymbols: []
275ProgramHeaders:
276  - Type:     PT_LOAD
277    Flags:    [ PF_R, PF_X ]
278    FirstSec: .gnu.hash
279    LastSec:  .dynamic
280
281## Check we report a proper warning when a hash table goes past the end of the file.
282
283## Case A: the 'maskwords' field is set so that the table goes past the end of the file.
284# RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_X86_64 -D MASKWORDS=4294967295 %s -o %t.err.maskwords
285# RUN: llvm-readobj --gnu-hash-table %t.err.maskwords 2>&1 | \
286# RUN:   FileCheck %s -DFILE=%t.err.maskwords -DMASKWORDS=4294967295 -DNBUCKETS=3 --check-prefix=ERR
287# RUN: llvm-readelf --gnu-hash-table %t.err.maskwords 2>&1 | \
288# RUN:   FileCheck %s -DFILE=%t.err.maskwords -DMASKWORDS=4294967295 -DNBUCKETS=3 --check-prefix=ERR
289
290## Case B: the 'nbuckets' field is set so that the table goes past the end of the file.
291# RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_X86_64 -D NBUCKETS=4294967295 %s -o %t.err.nbuckets
292# RUN: llvm-readobj --gnu-hash-table %t.err.nbuckets 2>&1 | \
293# RUN:   FileCheck %s -DFILE=%t.err.nbuckets -DMASKWORDS=2 -DNBUCKETS=4294967295 --check-prefix=ERR
294# RUN: llvm-readelf --gnu-hash-table %t.err.nbuckets 2>&1 | \
295# RUN:   FileCheck %s -DFILE=%t.err.nbuckets -DMASKWORDS=2 -DNBUCKETS=4294967295 --check-prefix=ERR
296
297# ERR:      GnuHashTable {
298# ERR-NEXT:   Num Buckets: [[NBUCKETS]]
299# ERR-NEXT:   First Hashed Symbol Index: 1
300# ERR-NEXT:   Num Mask Words: [[MASKWORDS]]
301# ERR-NEXT:   Shift Count: 2
302# ERR-NEXT: warning: '[[FILE]]': unable to dump the SHT_GNU_HASH section at 0x78: it goes past the end of the file
303# ERR-NEXT: }
304
305## Check we report a single warning about the broken GNU hash table when both
306## --gnu-hash-table and --elf-hash-histogram options are requested.
307# RUN: llvm-readelf --gnu-hash-table --elf-hash-histogram %t.err.nbuckets 2>&1 | \
308# RUN:   FileCheck %s -DFILE=%t.err.nbuckets -DMASKWORDS=2 -DNBUCKETS=4294967295 --check-prefix=ERR --implicit-check-not=warning
309