Rizin
unix-like reverse engineering framework and cli tools
elf_hash.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 08A <08A@riseup.net>
2 // SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include "elf.h"
6 
8  ut64 offset = result->offset;
9 
10  return Elf_(rz_bin_elf_read_word)(bin, &offset, &result->data.nbuckets) &&
11  Elf_(rz_bin_elf_read_word)(bin, &offset, &result->data.symoffset) &&
12  Elf_(rz_bin_elf_read_word)(bin, &offset, &result->data.bloom_size) &&
13  Elf_(rz_bin_elf_read_word)(bin, &offset, &result->data.bloom_shift);
14 }
15 
16 static bool read_hash_table(ELFOBJ *bin, RzBinElfHashTable *result) {
17  ut64 offset = result->offset;
18 
19  return Elf_(rz_bin_elf_read_word)(bin, &offset, &result->data.nbuckets) &&
20  Elf_(rz_bin_elf_read_word)(bin, &offset, &result->data.nchains);
21 }
22 
24  size_t result = 0;
25 
26  for (Elf_(Word) i = 0; i < table->data.nbuckets; i++) {
27  Elf_(Word) tmp;
28  if (!Elf_(rz_bin_elf_read_word)(bin, &bucket_offset, &tmp)) {
29  RZ_LOG_WARN("Failed to read the GNU hash table (DT_GNU_HASH) bucket at 0x%" PFMT64x ".\n", bucket_offset);
30  return 0;
31  }
32 
33  result = RZ_MAX(result, tmp);
34  }
35 
36  return result;
37 }
38 
39 static size_t get_highest_symbol_index_in_gnu_hash_table_chains(ELFOBJ *bin, RzBinElfGnuHashTable *table, ut64 chain_offset, size_t index) {
40  if (index < table->data.symoffset) {
41  return 0;
42  }
43 
44  Elf_(Word) chain_index = index - table->data.symoffset;
45  chain_offset += chain_index * sizeof(Elf_(Word));
46 
47  while (1) {
48  index++;
49 
50  Elf_(Word) tmp;
51  if (!Elf_(rz_bin_elf_read_word)(bin, &chain_offset, &tmp)) {
52  RZ_LOG_WARN("Failed to read the GNU hash table (DT_GNU_HASH) chain at 0x%" PFMT64x ".\n", chain_offset);
53  return 0;
54  }
55 
56  if (tmp & 1) {
57  break;
58  }
59  }
60 
61  return index;
62 }
63 
65  rz_return_val_if_fail(bin && result, false);
66 
67  ut64 addr;
69  return false;
70  }
71 
72  result->offset = Elf_(rz_bin_elf_v2p)(bin, addr);
73  if (result->offset == UT64_MAX) {
74  return false;
75  }
76 
77  if (!read_gnu_hash_table(bin, result)) {
78  RZ_LOG_WARN("Failed to read the GNU hash table (DT_GNU_HASH) at 0x%" PFMT64x ".\n", result->offset);
79  return false;
80  }
81 
82  return true;
83 }
84 
86  rz_return_val_if_fail(bin && result, false);
87 
88  ut64 addr;
90  return false;
91  }
92 
93  result->offset = Elf_(rz_bin_elf_v2p)(bin, addr);
94  if (result->offset == UT64_MAX) {
95  return false;
96  }
97 
98  if (!read_hash_table(bin, result)) {
99  RZ_LOG_WARN("Failed to read the hash table (DT_HASH) at 0x%" PFMT64x ".\n", result->offset);
100  return false;
101  }
102 
103  return true;
104 }
105 
107  rz_return_val_if_fail(bin, false);
108 
109  RzBinElfGnuHashTable table;
110  if (!Elf_(rz_bin_elf_get_gnu_hash_table)(bin, &table)) {
111  return 0;
112  }
113 
114  ut64 bloom_offset = table.offset + sizeof(struct gnu_hash_table);
115  ut64 bucket_offset = bloom_offset + table.data.bloom_size * sizeof(Elf_(Addr));
116  ut64 chain_offset = bucket_offset + table.data.nbuckets * sizeof(Elf_(Word));
117 
118  size_t index = get_highest_chain_index_in_gnu_hash_table_buckets(bin, &table, bucket_offset);
119  return get_highest_symbol_index_in_gnu_hash_table_chains(bin, &table, chain_offset, index);
120 }
121 
123  rz_return_val_if_fail(bin, false);
124 
125  RzBinElfHashTable table;
126  if (!Elf_(rz_bin_elf_get_hash_table)(bin, &table)) {
127  return 0;
128  }
129 
130  return table.data.nchains;
131 }
lzma_index ** i
Definition: index.h:629
ut64 Elf_() rz_bin_elf_v2p(RZ_NONNULL ELFOBJ *bin, ut64 vaddr)
Convert a virtual address to the physical address.
Definition: elf.c:429
#define ELFOBJ
Definition: elf.h:24
bool Elf_() rz_bin_elf_read_word(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Word) *result)
Definition: elf_misc.c:62
bool Elf_() rz_bin_elf_get_dt_info(RZ_NONNULL ELFOBJ *bin, ut64 key, RZ_OUT ut64 *info)
Definition: elf_dynamic.c:120
size_t Elf_() rz_bin_elf_get_number_of_symbols_from_hash_table(RZ_NONNULL ELFOBJ *bin)
Definition: elf_hash.c:122
bool Elf_() rz_bin_elf_get_gnu_hash_table(RZ_NONNULL ELFOBJ *bin, RzBinElfGnuHashTable *result)
Definition: elf_hash.c:64
static size_t get_highest_chain_index_in_gnu_hash_table_buckets(ELFOBJ *bin, RzBinElfGnuHashTable *table, ut64 bucket_offset)
Definition: elf_hash.c:23
static size_t get_highest_symbol_index_in_gnu_hash_table_chains(ELFOBJ *bin, RzBinElfGnuHashTable *table, ut64 chain_offset, size_t index)
Definition: elf_hash.c:39
static bool read_gnu_hash_table(ELFOBJ *bin, RzBinElfGnuHashTable *result)
Definition: elf_hash.c:7
bool Elf_() rz_bin_elf_get_hash_table(RZ_NONNULL ELFOBJ *bin, RzBinElfHashTable *result)
Definition: elf_hash.c:85
size_t Elf_() rz_bin_elf_get_number_of_symbols_from_gnu_hash_table(RZ_NONNULL ELFOBJ *bin)
Definition: elf_hash.c:106
static bool read_hash_table(ELFOBJ *bin, RzBinElfHashTable *result)
Definition: elf_hash.c:16
#define Elf_(name)
Definition: elf_specs.h:32
voidpf uLong offset
Definition: ioapi.h:144
#define DT_GNU_HASH
Definition: common.h:602
#define DT_HASH
Definition: common.h:541
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MAX(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
Definition: malloc.c:26
struct gnu_hash_table data
Definition: elf.h:66
struct elf_hash_table data
Definition: elf.h:78
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58