Rizin
unix-like reverse engineering framework and cli tools
coff_reloc.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "coff.h"
5 #include <rz_util.h>
6 #include <ht_uu.h>
7 
10  rz_return_val_if_fail(obj, 0);
12  return obj->reloc_targets_map_base;
13  }
14  if (!obj->scn_va) {
15  return 0;
16  }
17  ut64 max = 0;
18  for (size_t i = 0; i < obj->hdr.f_nscns; i++) {
19  struct coff_scn_hdr *hdr = &obj->scn_hdrs[i];
20  ut64 val = obj->scn_va[i] + hdr->s_size;
21  if (val > max) {
22  max = val;
23  }
24  }
25  max += 8;
29  return obj->reloc_targets_map_base;
30 }
31 
34 }
35 
36 typedef void (*RelocsForeachCb)(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user);
37 
38 static void relocs_foreach(struct rz_bin_coff_obj *bin, RelocsForeachCb cb, void *user) {
39  if (!bin->scn_hdrs) {
40  return;
41  }
42  for (size_t i = 0; i < bin->hdr.f_nscns; i++) {
43  if (!bin->scn_hdrs[i].s_nreloc) {
44  continue;
45  }
46  int size = bin->scn_hdrs[i].s_nreloc * sizeof(struct coff_reloc);
47  if (size < 0) {
48  break;
49  }
50  struct coff_reloc *rel = calloc(1, size + sizeof(struct coff_reloc));
51  if (!rel) {
52  break;
53  }
54  if (bin->scn_hdrs[i].s_relptr > bin->size ||
55  bin->scn_hdrs[i].s_relptr + size > bin->size) {
56  free(rel);
57  break;
58  }
59  ut64 offset = bin->scn_hdrs[i].s_relptr;
60  bool read_success = false;
61  for (size_t j = 0; j < bin->scn_hdrs[i].s_nreloc; j++) {
62  struct coff_reloc *coff_rel = rel + j;
63  read_success = rz_buf_read_le32_offset(bin->b, &offset, &coff_rel->rz_vaddr) &&
64  rz_buf_read_le32_offset(bin->b, &offset, &coff_rel->rz_symndx) &&
65  rz_buf_read_le16_offset(bin->b, &offset, &coff_rel->rz_type);
66  if (!read_success) {
67  break;
68  }
69  }
70  if (!read_success) {
71  free(rel);
72  break;
73  }
74  for (size_t j = 0; j < bin->scn_hdrs[i].s_nreloc; j++) {
75  RzBinSymbol *symbol = (RzBinSymbol *)ht_up_find(bin->sym_ht, (ut64)rel[j].rz_symndx, NULL);
76  if (!symbol) {
77  continue;
78  }
79  RzBinReloc reloc = { 0 };
80 
81  reloc.symbol = symbol;
82  reloc.paddr = bin->scn_hdrs[i].s_scnptr + rel[j].rz_vaddr;
83  if (bin->scn_va) {
84  reloc.vaddr = bin->scn_va[i] + rel[j].rz_vaddr;
85  }
86  reloc.type = rel[j].rz_type;
87 
88  ut64 sym_vaddr = symbol->vaddr;
89  if (symbol->is_imported) {
90  reloc.import = (RzBinImport *)ht_up_find(bin->imp_ht, (ut64)rel[j].rz_symndx, NULL);
91  ut64 imp_idx = ht_uu_find(bin->imp_index, (ut64)rel[j].rz_symndx, NULL);
92  sym_vaddr = rz_coff_import_index_addr(bin, imp_idx);
93  }
94  reloc.target_vaddr = sym_vaddr;
95 
96  size_t plen = 0;
97  ut8 patch_buf[8];
98  if (sym_vaddr) {
99  switch (bin->hdr.f_magic) {
101  switch (rel[j].rz_type) {
102  case COFF_REL_I386_DIR32:
103  reloc.type = RZ_BIN_RELOC_32;
104  rz_write_le32(patch_buf, (ut32)sym_vaddr);
105  plen = 4;
106  break;
107  case COFF_REL_I386_REL32:
108  reloc.type = RZ_BIN_RELOC_32;
109  reloc.additive = 1;
110  ut32 data;
111  if (!rz_buf_read_le32_at(bin->b, reloc.paddr, &data)) {
112  break;
113  }
114  reloc.addend = data;
115  data += sym_vaddr - reloc.vaddr - 4;
116  rz_write_le32(patch_buf, (st32)data);
117  plen = 4;
118  break;
119  }
120  break;
122  switch (rel[j].rz_type) {
124  reloc.type = RZ_BIN_RELOC_32;
125  reloc.additive = 1;
126  ut32 data;
127  if (!rz_buf_read_le32_at(bin->b, reloc.paddr, &data)) {
128  break;
129  }
130  reloc.addend = data;
131  data += sym_vaddr - reloc.vaddr - 4;
132  rz_write_le32(patch_buf, (st32)data);
133  plen = 4;
134  break;
135  }
136  break;
138  switch (rel[j].rz_type) {
140  case COFF_REL_ARM_BLX23T:
141  reloc.type = RZ_BIN_RELOC_32;
142  ut16 hiword;
143  if (!rz_buf_read_le16_at(bin->b, reloc.paddr, &hiword)) {
144  break;
145  }
146  ut16 loword;
147  if (!rz_buf_read_le16_at(bin->b, reloc.paddr + 2, &loword)) {
148  break;
149  }
150  ut64 dst = sym_vaddr - reloc.vaddr - 4;
151  if (dst & 1) {
152  break;
153  }
154  loword |= (ut16)(dst >> 1) & 0x7ff;
155  hiword |= (ut16)(dst >> 12) & 0x7ff;
156  rz_write_le16(patch_buf, hiword);
157  rz_write_le16(patch_buf + 2, loword);
158  plen = 4;
159  break;
160  }
161  break;
163  switch (rel[j].rz_type) {
165  reloc.type = RZ_BIN_RELOC_32;
166  ut32 data;
167  if (!rz_buf_read_le32_at(bin->b, reloc.paddr, &data)) {
168  break;
169  }
170  ut64 dst = sym_vaddr - reloc.vaddr;
171  data |= (ut32)((dst >> 2) & 0x3ffffffULL);
172  rz_write_le32(patch_buf, data);
173  plen = 4;
174  break;
175  }
176  break;
177  }
178  }
179  cb(&reloc, plen ? patch_buf : NULL, plen, user);
180  }
181  free(rel);
182  }
183 }
184 
185 void get_relocs_list_cb(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user) {
186  RzList *r = user;
187  RzBinReloc *reloc_copy = RZ_NEW(RzBinReloc);
188  if (!reloc_copy) {
189  return;
190  }
191  memcpy(reloc_copy, reloc, sizeof(*reloc_copy));
192  rz_list_push(r, reloc_copy);
193 }
194 
198  if (!r) {
199  return NULL;
200  }
202  return r;
203 }
204 
207  rz_return_val_if_fail(obj, 0);
208  ut64 count = obj->imp_index ? obj->imp_index->count : 0;
210 }
211 
212 static void patch_reloc_cb(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user) {
213  RzBuffer *buf = user;
214  if (patch_buf) {
215  rz_buf_write_at(buf, reloc->paddr, patch_buf, patch_buf_sz);
216  }
217 }
218 
221  if (bin->buf_patched) {
222  return bin->buf_patched;
223  }
225  if (!bin->buf_patched) {
226  return NULL;
227  }
228  relocs_foreach(bin, patch_reloc_cb, bin->buf_patched);
230  return bin->buf_patched;
231 }
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
#define RZ_COFF_RELOC_TARGET_SIZE
Definition: coff.h:55
static void patch_reloc_cb(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
Definition: coff_reloc.c:212
RZ_API ut64 rz_coff_get_reloc_targets_vfile_size(struct rz_bin_coff_obj *obj)
size of the artificial reloc target vfile
Definition: coff_reloc.c:206
RZ_API ut64 rz_coff_get_reloc_targets_map_base(struct rz_bin_coff_obj *obj)
base vaddr where to map the artificial reloc target vfile
Definition: coff_reloc.c:9
static void relocs_foreach(struct rz_bin_coff_obj *bin, RelocsForeachCb cb, void *user)
Definition: coff_reloc.c:38
RZ_API RZ_BORROW RzBuffer * rz_coff_get_patched_buf(struct rz_bin_coff_obj *bin)
Definition: coff_reloc.c:219
void(* RelocsForeachCb)(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
Definition: coff_reloc.c:36
RZ_API RzList * rz_coff_get_relocs(struct rz_bin_coff_obj *bin)
Definition: coff_reloc.c:195
void get_relocs_list_cb(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
Definition: coff_reloc.c:185
RZ_API ut64 rz_coff_import_index_addr(struct rz_bin_coff_obj *obj, ut64 imp_index)
Definition: coff_reloc.c:32
#define COFF_REL_I386_REL32
Definition: coff_specs.h:144
#define COFF_REL_ARM64_BRANCH26
Definition: coff_specs.h:163
#define COFF_FILE_MACHINE_ARM64
Definition: coff_specs.h:13
#define COFF_REL_I386_DIR32
Definition: coff_specs.h:142
#define COFF_FILE_MACHINE_AMD64
Definition: coff_specs.h:10
#define COFF_REL_ARM_BRANCH24T
Definition: coff_specs.h:157
#define COFF_REL_ARM_BLX23T
Definition: coff_specs.h:158
#define COFF_FILE_MACHINE_I386
Definition: coff_specs.h:15
#define COFF_FILE_MACHINE_ARMNT
Definition: coff_specs.h:12
#define COFF_REL_AMD64_REL32
Definition: coff_specs.h:150
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint16_t ut16
uint32_t ut32
int max
Definition: enough.c:225
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
char * dst
Definition: lz4.h:724
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_BIN_RELOC_32
Definition: rz_bin.h:176
#define rz_buf_read_le16_at(b, addr, result)
Definition: rz_buf.h:270
RZ_API void rz_buf_sparse_set_write_mode(RzBuffer *b, RzBufferSparseWriteMode mode)
Only for sparse RzBuffers.
Definition: buf_sparse.c:325
RZ_API st64 rz_buf_write_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL const ut8 *buf, ut64 len)
Write len bytes of the buffer at the specified address.
Definition: buf.c:1197
#define rz_buf_read_le16_offset(b, offset, result)
Definition: rz_buf.h:276
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
@ RZ_BUF_SPARSE_WRITE_MODE_SPARSE
all writes are performed in the sparse overlay
Definition: rz_buf.h:60
@ RZ_BUF_SPARSE_WRITE_MODE_THROUGH
all writes are performed in the underlying base buffer
Definition: rz_buf.h:61
#define rz_buf_read_le32_offset(b, offset, result)
Definition: rz_buf.h:277
RZ_API RZ_OWN RzBuffer * rz_buf_new_sparse_overlay(RzBuffer *b, RzBufferSparseWriteMode write_mode)
Creates a sparse buffer from a already populated buffer.
Definition: buf.c:426
static void rz_write_le32(void *dest, ut32 val)
Definition: rz_endian.h:256
static void rz_write_le16(void *dest, ut16 val)
Definition: rz_endian.h:222
static ut64 rz_num_align_delta(ut64 v, ut64 alignment)
Padding to align v to the next alignment-boundary.
Definition: rz_num.h:116
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_BORROW
Definition: rz_types.h:63
#define st32
Definition: rz_types_base.h:12
Definition: malloc.c:26
ut32 rz_vaddr
Definition: coff_specs.h:213
ut32 rz_symndx
Definition: coff_specs.h:214
ut16 rz_type
Definition: coff_specs.h:215
ut64 reloc_targets_map_base
Definition: coff.h:36
ut64 * scn_va
Definition: coff.h:35
struct coff_hdr hdr
Definition: coff.h:20
struct coff_scn_hdr * scn_hdrs
Definition: coff.h:22
HtUU * imp_index
locally-generated indices for imports, in particular for deterministically assigning reloc targets
Definition: coff.h:34
bool reloc_targets_map_base_calculated
Definition: coff.h:37
ut64 paddr
the paddr where the value should be patched into
Definition: rz_bin.h:717
RzBinRelocType type
Definition: rz_bin.h:712
ut64 vaddr
the vaddr where the value should be patched into
Definition: rz_bin.h:716
ut64 target_vaddr
the target address that the patched reloc points to
Definition: rz_bin.h:718
RzBinImport * import
Definition: rz_bin.h:714
bool additive
Definition: rz_bin.h:720
st64 addend
Definition: rz_bin.h:715
RzBinSymbol * symbol
Definition: rz_bin.h:713
bool is_imported
Definition: rz_bin.h:684
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176