Rizin
unix-like reverse engineering framework and cli tools
elf_relocs.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 08A <08A@riseup.net>
2 // SPDX-FileCopyrightText: 2008-2020 nibble <nibble.ds@gmail.com>
3 // SPDX-FileCopyrightText: 2008-2020 pancake <pancake@nopcode.org>
4 // SPDX-FileCopyrightText: 2008-2020 alvaro_fe <alvaro.felipe91@gmail.com>
5 // SPDX-License-Identifier: LGPL-3.0-only
6 
7 #include "elf.h"
8 #include <ht_uu.h>
9 
15 };
16 
18  return (struct relocs_segment){
19  .offset = offset,
20  .size = size,
21  .entry_size = entry_size,
22  .mode = mode,
23  };
24 }
25 
27  RzBinElfSection *sub_section = Elf_(rz_bin_elf_get_section)(bin, section->info);
28 
29  if (!sub_section) {
30  reloc->paddr = UT64_MAX;
31  reloc->vaddr = reloc->offset;
32  } else {
33  reloc->paddr = sub_section->offset + reloc->offset;
34  reloc->vaddr = Elf_(rz_bin_elf_p2v)(bin, reloc->paddr);
35  }
36 }
37 
39  reloc->paddr = Elf_(rz_bin_elf_v2p)(bin, reloc->offset);
40 
41  if (reloc->paddr == UT64_MAX) {
42  reloc->paddr = reloc->offset;
43  }
44 
45  reloc->vaddr = reloc->offset;
46 }
47 
51  } else {
53  }
54 }
55 
57  return mode == DT_REL ? sizeof(Elf_(Rel)) : sizeof(Elf_(Rela));
58 }
59 
60 static bool read_reloc_entry_aux(ELFOBJ *bin, Elf_(Rela) * reloc, ut64 offset, ut64 mode) {
61  if (!Elf_(rz_bin_elf_read_addr)(bin, &offset, &reloc->rz_offset) ||
62  !Elf_(rz_bin_elf_read_word_xword)(bin, &offset, &reloc->rz_info)) {
63  return false;
64  }
65 
66  if (mode == DT_REL) {
67  reloc->rz_addend = 0;
68  return true;
69  }
70 
71  return Elf_(rz_bin_elf_read_sword_sxword)(bin, &offset, &reloc->rz_addend);
72 }
73 
74 static bool read_reloc_entry(ELFOBJ *bin, Elf_(Rela) * reloc, ut64 offset, ut64 mode) {
75  if (!read_reloc_entry_aux(bin, reloc, offset, mode)) {
76  RZ_LOG_WARN("Failed to read reloc at 0x%" PFMT64x ".\n", offset);
77  return false;
78  }
79 
80  return true;
81 }
82 
84  Elf_(Rela) tmp;
85  if (!read_reloc_entry(bin, &tmp, offset, mode)) {
86  return false;
87  }
88 
89  reloc->mode = mode;
90  reloc->offset = tmp.rz_offset;
91  reloc->sym = ELF_R_SYM(tmp.rz_info);
92  reloc->type = ELF_R_TYPE(tmp.rz_info);
93  reloc->addend = tmp.rz_addend;
94 
95  return true;
96 }
97 
98 static bool has_already_been_processed(ELFOBJ *bin, ut64 offset, HtUU *set) {
99  bool found;
100  ht_uu_find(set, offset, &found);
101 
102  return found;
103 }
104 
105 static bool get_relocs_entry(ELFOBJ *bin, RzBinElfSection *section, RzVector *relocs, struct relocs_segment *segment, HtUU *set) {
106  for (ut64 entry_offset = 0; entry_offset < segment->size; entry_offset += segment->entry_size) {
107  if (has_already_been_processed(bin, segment->offset + entry_offset, set)) {
108  continue;
109  }
110 
111  if (!ht_uu_insert(set, segment->offset + entry_offset, segment->offset + entry_offset)) {
112  return false;
113  }
114 
115  RzBinElfReloc tmp = { 0 };
116  if (!get_reloc_entry(bin, &tmp, segment->offset + entry_offset, segment->mode)) {
117  return false;
118  }
119 
121 
122  if (!rz_vector_push(relocs, &tmp)) {
123  return false;
124  }
125  }
126 
127  return true;
128 }
129 
130 static bool get_relocs_entry_from_dt_dynamic_aux(ELFOBJ *bin, RzVector *relocs, ut64 dt_addr, ut64 dt_size, ut64 entry_size, ut64 mode, HtUU *set) {
131  ut64 addr;
132  ut64 size;
133 
134  if (!Elf_(rz_bin_elf_get_dt_info)(bin, dt_addr, &addr) || !Elf_(rz_bin_elf_get_dt_info)(bin, dt_size, &size)) {
135  return true;
136  }
137 
139  if (offset == UT64_MAX) {
140  return false;
141  }
142 
144 
145  return get_relocs_entry(bin, NULL, relocs, &segment, set);
146 }
147 
150 
152  return true;
153  }
154 
155  ut64 dt_pltrel;
156  if (Elf_(rz_bin_elf_get_dt_info)(bin, DT_PLTREL, &dt_pltrel)) {
157  entry_size = get_size_rel_mode(dt_pltrel);
159  return false;
160  }
161  }
162 
165  return false;
166  }
167  }
168 
171  return false;
172  }
173  }
174 
175  return true;
176 }
177 
179  return section->type == SHT_REL ? DT_REL : DT_RELA;
180 }
181 
185  if (!section->is_valid || (section->type != SHT_REL && section->type != SHT_RELA)) {
186  continue;
187  }
188 
191 
193 
194  if (!get_relocs_entry(bin, section, relocs, &segment, set)) {
195  return false;
196  }
197  }
198 
199  return true;
200 }
201 
204 
205  HtUU *set = ht_uu_new0();
206  if (!set) {
207  return NULL;
208  }
209 
210  RzVector *result = rz_vector_new(sizeof(RzBinElfReloc), NULL, NULL);
211  if (!result) {
212  ht_uu_free(set);
213  return NULL;
214  }
215 
216  if (!get_relocs_entry_from_dt_dynamic(bin, result, set)) {
217  rz_vector_free(result);
218  ht_uu_free(set);
219  return NULL;
220  }
221 
222  if (!get_relocs_entry_from_sections(bin, result, set)) {
223  rz_vector_free(result);
224  ht_uu_free(set);
225  return NULL;
226  }
227 
228  if (!rz_vector_len(result)) {
229  rz_vector_free(result);
230  ht_uu_free(set);
231  return NULL;
232  }
233 
234  ht_uu_free(set);
235 
236  return result;
237 }
238 
240  rz_return_val_if_fail(bin, false);
241 
242  return bin->relocs;
243 }
244 
247 
248  if (!bin->relocs) {
249  return 0;
250  }
251 
252  return rz_vector_len(bin->relocs);
253 }
254 
257 
258  ut64 dt_pltrel;
259  ut64 size;
260 
262  return 0;
263  }
264 
265  ut64 entry_size = get_size_rel_mode(dt_pltrel);
266  return size / entry_size;
267 }
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
#define NULL
Definition: cris-opc.c:27
ut64 Elf_() rz_bin_elf_p2v(RZ_NONNULL ELFOBJ *bin, ut64 paddr)
Convert a physical address to the virtual address.
Definition: elf.c:400
ut64 Elf_() rz_bin_elf_v2p(RZ_NONNULL ELFOBJ *bin, ut64 vaddr)
Convert a virtual address to the physical address.
Definition: elf.c:429
bool Elf_() rz_bin_elf_read_word_xword(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Word) *result)
Definition: elf_misc.c:117
#define rz_bin_elf_foreach_sections(bin, section)
Definition: elf.h:30
bool Elf_() rz_bin_elf_has_dt_dynamic(RZ_NONNULL ELFOBJ *bin)
Definition: elf_dynamic.c:130
bool Elf_() rz_bin_elf_read_addr(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Addr) *result)
Definition: elf_misc.c:82
#define ELFOBJ
Definition: elf.h:24
RZ_BORROW RzBinElfSection *Elf_() rz_bin_elf_get_section(RZ_NONNULL ELFOBJ *bin, Elf_(Half) index)
Definition: elf_sections.c:264
bool Elf_() rz_bin_elf_read_sword_sxword(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Sword) *result)
Definition: elf_misc.c:131
bool Elf_() rz_bin_elf_get_dt_info(RZ_NONNULL ELFOBJ *bin, ut64 key, RZ_OUT ut64 *info)
Definition: elf_dynamic.c:120
bool Elf_() rz_bin_elf_is_relocatable(RZ_NONNULL ELFOBJ *bin)
Check if the elf binary is relocatable.
Definition: elf_info.c:1662
static bool get_relocs_entry_from_sections(ELFOBJ *bin, RzVector *relocs, HtUU *set)
Definition: elf_relocs.c:182
RZ_OWN RzVector *Elf_() rz_bin_elf_relocs_new(RZ_NONNULL ELFOBJ *bin)
Definition: elf_relocs.c:202
static bool get_reloc_entry(ELFOBJ *bin, RzBinElfReloc *reloc, ut64 offset, ut64 mode)
Definition: elf_relocs.c:83
static ut64 get_section_relocation_mode(RzBinElfSection *section)
Definition: elf_relocs.c:178
size_t Elf_() rz_bin_elf_get_relocs_count(RZ_NONNULL ELFOBJ *bin)
Definition: elf_relocs.c:245
static bool get_relocs_entry_from_dt_dynamic(ELFOBJ *bin, RzVector *relocs, HtUU *set)
Definition: elf_relocs.c:148
static bool has_already_been_processed(ELFOBJ *bin, ut64 offset, HtUU *set)
Definition: elf_relocs.c:98
static bool read_reloc_entry(ELFOBJ *bin, Elf_(Rela) *reloc, ut64 offset, ut64 mode)
Definition: elf_relocs.c:74
bool Elf_() rz_bin_elf_has_relocs(RZ_NONNULL ELFOBJ *bin)
Definition: elf_relocs.c:239
static bool read_reloc_entry_aux(ELFOBJ *bin, Elf_(Rela) *reloc, ut64 offset, ut64 mode)
Definition: elf_relocs.c:60
static bool get_relocs_entry(ELFOBJ *bin, RzBinElfSection *section, RzVector *relocs, struct relocs_segment *segment, HtUU *set)
Definition: elf_relocs.c:105
static ut64 get_size_rel_mode(ut64 mode)
Definition: elf_relocs.c:56
static void fix_rva_and_offset_exec_file(ELFOBJ *bin, RzBinElfReloc *reloc)
Definition: elf_relocs.c:38
ut64 Elf_() rz_bin_elf_get_num_relocs_dynamic_plt(RZ_NONNULL ELFOBJ *bin)
Definition: elf_relocs.c:255
static void fix_rva_and_offset(ELFOBJ *bin, RzBinElfReloc *reloc, RzBinElfSection *section)
Definition: elf_relocs.c:48
static bool get_relocs_entry_from_dt_dynamic_aux(ELFOBJ *bin, RzVector *relocs, ut64 dt_addr, ut64 dt_size, ut64 entry_size, ut64 mode, HtUU *set)
Definition: elf_relocs.c:130
static struct relocs_segment relocs_segment_init(ut64 offset, ut64 size, ut64 entry_size, ut64 mode)
Definition: elf_relocs.c:17
static void fix_rva_and_offset_relocable_file(ELFOBJ *bin, RzBinElfReloc *reloc, RzBinElfSection *section)
Definition: elf_relocs.c:26
#define ELF_R_SYM
Definition: elf_specs.h:37
#define Elf_(name)
Definition: elf_specs.h:32
#define ELF_R_TYPE
Definition: elf_specs.h:38
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
#define SHT_REL
Definition: common.h:340
#define DT_RELSZ
Definition: common.h:555
#define DT_RELASZ
Definition: common.h:545
#define DT_RELAENT
Definition: common.h:546
#define DT_PLTREL
Definition: common.h:557
#define DT_REL
Definition: common.h:554
#define DT_PLTRELSZ
Definition: common.h:539
#define SHT_RELA
Definition: common.h:335
#define DT_JMPREL
Definition: common.h:560
#define DT_RELENT
Definition: common.h:556
#define DT_RELA
Definition: common.h:544
#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_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64x
Definition: rz_types.h:393
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75
RZ_API RzVector * rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:42
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
Definition: malloc.c:26
st64 addend
exact addend value taken from the ELF, meaning depends on type
Definition: elf.h:147
ut64 offset
exact offset value taken from the ELF, meaning depends on the binary type
Definition: elf.h:148
ut64 vaddr
source vaddr of the reloc, calculated from offset
Definition: elf.h:150
ut64 paddr
absolute paddr in the file, calculated from offset, or UT64_MAX if no such addr exists
Definition: elf.h:149
uint32_t offset
uint32_t size
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58