20
20
#ifdef ABSL_HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h
21
21
22
22
#include < string.h>
23
+
23
24
#include < cassert>
24
25
#include < cstddef>
26
+ #include < cstdint>
27
+
25
28
#include " absl/base/config.h"
26
29
#include " absl/base/internal/raw_logging.h"
27
30
@@ -86,20 +89,14 @@ ElfMemImage::ElfMemImage(const void *base) {
86
89
Init (base);
87
90
}
88
91
89
- int ElfMemImage::GetNumSymbols () const {
90
- if (!hash_) {
91
- return 0 ;
92
- }
93
- // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash
94
- return static_cast <int >(hash_[1 ]);
95
- }
92
+ uint32_t ElfMemImage::GetNumSymbols () const { return num_syms_; }
96
93
97
- const ElfW (Sym) *ElfMemImage::GetDynsym(int index) const {
94
+ const ElfW (Sym) * ElfMemImage::GetDynsym(uint32_t index) const {
98
95
ABSL_RAW_CHECK (index < GetNumSymbols (), " index out of range" );
99
96
return dynsym_ + index;
100
97
}
101
98
102
- const ElfW (Versym) *ElfMemImage::GetVersym(int index) const {
99
+ const ElfW (Versym) *ElfMemImage::GetVersym(uint32_t index) const {
103
100
ABSL_RAW_CHECK (index < GetNumSymbols (), " index out of range" );
104
101
return versym_ + index;
105
102
}
@@ -154,7 +151,7 @@ void ElfMemImage::Init(const void *base) {
154
151
dynstr_ = nullptr ;
155
152
versym_ = nullptr ;
156
153
verdef_ = nullptr ;
157
- hash_ = nullptr ;
154
+ num_syms_ = 0 ;
158
155
strsize_ = 0 ;
159
156
verdefnum_ = 0 ;
160
157
// Sentinel: PT_LOAD .p_vaddr can't possibly be this.
@@ -219,12 +216,17 @@ void ElfMemImage::Init(const void *base) {
219
216
base_as_char - reinterpret_cast <const char *>(link_base_);
220
217
ElfW (Dyn)* dynamic_entry = reinterpret_cast <ElfW (Dyn)*>(
221
218
static_cast <intptr_t >(dynamic_program_header->p_vaddr ) + relocation);
219
+ uint32_t *sysv_hash = nullptr ;
220
+ uint32_t *gnu_hash = nullptr ;
222
221
for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {
223
222
const auto value =
224
223
static_cast <intptr_t >(dynamic_entry->d_un .d_val ) + relocation;
225
224
switch (dynamic_entry->d_tag ) {
226
225
case DT_HASH:
227
- hash_ = reinterpret_cast <ElfW (Word) *>(value);
226
+ sysv_hash = reinterpret_cast <uint32_t *>(value);
227
+ break ;
228
+ case DT_GNU_HASH:
229
+ gnu_hash = reinterpret_cast <uint32_t *>(value);
228
230
break ;
229
231
case DT_SYMTAB:
230
232
dynsym_ = reinterpret_cast <ElfW (Sym) *>(value);
@@ -249,13 +251,38 @@ void ElfMemImage::Init(const void *base) {
249
251
break ;
250
252
}
251
253
}
252
- if (!hash_ || !dynsym_ || !dynstr_ || !versym_ ||
254
+ if ((!sysv_hash && !gnu_hash) || !dynsym_ || !dynstr_ || !versym_ ||
253
255
!verdef_ || !verdefnum_ || !strsize_) {
254
256
assert (false ); // invalid VDSO
255
257
// Mark this image as not present. Can not recur infinitely.
256
258
Init (nullptr );
257
259
return ;
258
260
}
261
+ if (sysv_hash) {
262
+ num_syms_ = sysv_hash[1 ];
263
+ } else {
264
+ assert (gnu_hash);
265
+ // Compute the number of symbols for DT_GNU_HASH, which is specified by
266
+ // https://sourceware.org/gnu-gabi/program-loading-and-dynamic-linking.txt
267
+ uint32_t nbuckets = gnu_hash[0 ];
268
+ // The buckets array is located after the header (4 uint32) and the bloom
269
+ // filter (size_t array of gnu_hash[2] elements).
270
+ uint32_t *buckets = gnu_hash + 4 + sizeof (size_t ) / 4 * gnu_hash[2 ];
271
+ // Find the chain of the last non-empty bucket.
272
+ uint32_t idx = 0 ;
273
+ for (uint32_t i = nbuckets; i > 0 ;) {
274
+ idx = buckets[--i];
275
+ if (idx != 0 ) break ;
276
+ }
277
+ if (idx != 0 ) {
278
+ // Find the last element of the chain, which has an odd value.
279
+ // Add one to get the number of symbols.
280
+ uint32_t *chain = buckets + nbuckets - gnu_hash[1 ];
281
+ while (chain[idx++] % 2 == 0 ) {
282
+ }
283
+ }
284
+ num_syms_ = idx;
285
+ }
259
286
}
260
287
261
288
bool ElfMemImage::LookupSymbol (const char *name,
@@ -300,9 +327,9 @@ bool ElfMemImage::LookupSymbolByAddress(const void *address,
300
327
return false ;
301
328
}
302
329
303
- ElfMemImage::SymbolIterator::SymbolIterator (const void *const image, int index)
304
- : index_(index), image_(image) {
305
- }
330
+ ElfMemImage::SymbolIterator::SymbolIterator (const void *const image,
331
+ uint32_t index)
332
+ : index_(index), image_(image) { }
306
333
307
334
const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator ->() const {
308
335
return &info_;
@@ -335,7 +362,7 @@ ElfMemImage::SymbolIterator ElfMemImage::end() const {
335
362
return SymbolIterator (this , GetNumSymbols ());
336
363
}
337
364
338
- void ElfMemImage::SymbolIterator::Update (int increment) {
365
+ void ElfMemImage::SymbolIterator::Update (uint32_t increment) {
339
366
const ElfMemImage *image = reinterpret_cast <const ElfMemImage *>(image_);
340
367
ABSL_RAW_CHECK (image->IsPresent () || increment == 0 , " " );
341
368
if (!image->IsPresent ()) {
0 commit comments