Rizin
unix-like reverse engineering framework and cli tools
coff_reloc.c File Reference
#include "coff.h"
#include <rz_util.h>
#include <ht_uu.h>

Go to the source code of this file.

Typedefs

typedef void(* RelocsForeachCb) (RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
 

Functions

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 More...
 
RZ_API ut64 rz_coff_import_index_addr (struct rz_bin_coff_obj *obj, ut64 imp_index)
 
static void relocs_foreach (struct rz_bin_coff_obj *bin, RelocsForeachCb cb, void *user)
 
void get_relocs_list_cb (RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
 
RZ_API RzListrz_coff_get_relocs (struct rz_bin_coff_obj *bin)
 
RZ_API ut64 rz_coff_get_reloc_targets_vfile_size (struct rz_bin_coff_obj *obj)
 size of the artificial reloc target vfile More...
 
static void patch_reloc_cb (RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
 
RZ_API RZ_BORROW RzBufferrz_coff_get_patched_buf (struct rz_bin_coff_obj *bin)
 

Typedef Documentation

◆ RelocsForeachCb

typedef void(* RelocsForeachCb) (RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)

Definition at line 36 of file coff_reloc.c.

Function Documentation

◆ get_relocs_list_cb()

void get_relocs_list_cb ( RZ_BORROW RzBinReloc reloc,
ut8 patch_buf,
size_t  patch_buf_sz,
void *  user 
)

Definition at line 185 of file coff_reloc.c.

185  {
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 }
#define r
Definition: crypto_rc6.c:12
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
#define RZ_NEW(x)
Definition: rz_types.h:285

References memcpy(), r, rz_list_push(), and RZ_NEW.

Referenced by rz_coff_get_relocs().

◆ patch_reloc_cb()

static void patch_reloc_cb ( RZ_BORROW RzBinReloc reloc,
ut8 patch_buf,
size_t  patch_buf_sz,
void *  user 
)
static

Definition at line 212 of file coff_reloc.c.

212  {
213  RzBuffer *buf = user;
214  if (patch_buf) {
215  rz_buf_write_at(buf, reloc->paddr, patch_buf, patch_buf_sz);
216  }
217 }
voidpf void * buf
Definition: ioapi.h:138
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

References rz_buf_write_at().

Referenced by rz_coff_get_patched_buf().

◆ relocs_foreach()

static void relocs_foreach ( struct rz_bin_coff_obj bin,
RelocsForeachCb  cb,
void *  user 
)
static

Definition at line 38 of file coff_reloc.c.

38  {
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 }
lzma_index ** i
Definition: index.h:629
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 NULL
Definition: cris-opc.c:27
uint16_t ut16
uint32_t ut32
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
uint8_t ut8
Definition: lh5801.h:11
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
char * dst
Definition: lz4.h:724
@ RZ_BIN_RELOC_32
Definition: rz_bin.h:176
#define rz_buf_read_le16_at(b, addr, result)
Definition: rz_buf.h:270
#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
#define rz_buf_read_le32_offset(b, offset, result)
Definition: rz_buf.h:277
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
#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 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

References rz_bin_reloc_t::addend, rz_bin_reloc_t::additive, calloc(), cb, COFF_FILE_MACHINE_AMD64, COFF_FILE_MACHINE_ARM64, COFF_FILE_MACHINE_ARMNT, COFF_FILE_MACHINE_I386, COFF_REL_AMD64_REL32, COFF_REL_ARM64_BRANCH26, COFF_REL_ARM_BLX23T, COFF_REL_ARM_BRANCH24T, COFF_REL_I386_DIR32, COFF_REL_I386_REL32, dst, free(), i, rz_bin_reloc_t::import, rz_bin_symbol_t::is_imported, NULL, rz_bin_reloc_t::paddr, RZ_BIN_RELOC_32, rz_buf_read_le16_at, rz_buf_read_le16_offset, rz_buf_read_le32_at, rz_buf_read_le32_offset, rz_coff_import_index_addr(), coff_reloc::rz_symndx, coff_reloc::rz_type, coff_reloc::rz_vaddr, rz_write_le16(), rz_write_le32(), st32, rz_bin_reloc_t::symbol, rz_bin_reloc_t::target_vaddr, rz_bin_reloc_t::type, ut64(), rz_bin_symbol_t::vaddr, and rz_bin_reloc_t::vaddr.

Referenced by rz_coff_get_patched_buf(), and rz_coff_get_relocs().

◆ rz_coff_get_patched_buf()

RZ_API RZ_BORROW RzBuffer* rz_coff_get_patched_buf ( struct rz_bin_coff_obj bin)

Definition at line 219 of file coff_reloc.c.

219  {
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 }
static void patch_reloc_cb(RZ_BORROW RzBinReloc *reloc, ut8 *patch_buf, size_t patch_buf_sz, void *user)
Definition: coff_reloc.c:212
static void relocs_foreach(struct rz_bin_coff_obj *bin, RelocsForeachCb cb, void *user)
Definition: coff_reloc.c:38
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API void rz_buf_sparse_set_write_mode(RzBuffer *b, RzBufferSparseWriteMode mode)
Only for sparse RzBuffers.
Definition: buf_sparse.c:325
@ 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
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

References NULL, patch_reloc_cb(), relocs_foreach(), rz_buf_new_sparse_overlay(), rz_buf_sparse_set_write_mode(), RZ_BUF_SPARSE_WRITE_MODE_SPARSE, RZ_BUF_SPARSE_WRITE_MODE_THROUGH, and rz_return_val_if_fail.

Referenced by virtual_files().

◆ rz_coff_get_reloc_targets_map_base()

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 at line 9 of file coff_reloc.c.

9  {
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 }
ut16 val
Definition: armass64_const.h:6
#define RZ_COFF_RELOC_TARGET_SIZE
Definition: coff.h:55
int max
Definition: enough.c:225
static ut64 rz_num_align_delta(ut64 v, ut64 alignment)
Padding to align v to the next alignment-boundary.
Definition: rz_num.h:116
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
bool reloc_targets_map_base_calculated
Definition: coff.h:37

References rz_bin_coff_obj::hdr, i, max, rz_bin_coff_obj::reloc_targets_map_base, rz_bin_coff_obj::reloc_targets_map_base_calculated, RZ_COFF_RELOC_TARGET_SIZE, rz_num_align_delta(), rz_return_val_if_fail, rz_bin_coff_obj::scn_hdrs, rz_bin_coff_obj::scn_va, ut64(), and val.

Referenced by maps(), and rz_coff_import_index_addr().

◆ rz_coff_get_reloc_targets_vfile_size()

RZ_API ut64 rz_coff_get_reloc_targets_vfile_size ( struct rz_bin_coff_obj obj)

size of the artificial reloc target vfile

Definition at line 206 of file coff_reloc.c.

206  {
207  rz_return_val_if_fail(obj, 0);
208  ut64 count = obj->imp_index ? obj->imp_index->count : 0;
210 }
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
HtUU * imp_index
locally-generated indices for imports, in particular for deterministically assigning reloc targets
Definition: coff.h:34

References count, rz_bin_coff_obj::imp_index, RZ_COFF_RELOC_TARGET_SIZE, rz_return_val_if_fail, and ut64().

Referenced by maps(), and virtual_files().

◆ rz_coff_get_relocs()

RZ_API RzList* rz_coff_get_relocs ( struct rz_bin_coff_obj bin)

Definition at line 195 of file coff_reloc.c.

195  {
198  if (!r) {
199  return NULL;
200  }
202  return r;
203 }
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 RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248

References free(), get_relocs_list_cb(), NULL, r, relocs_foreach(), rz_list_newf(), and rz_return_val_if_fail.

Referenced by relocs().

◆ rz_coff_import_index_addr()

RZ_API ut64 rz_coff_import_index_addr ( struct rz_bin_coff_obj obj,
ut64  imp_index 
)

Definition at line 32 of file coff_reloc.c.

32  {
34 }
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

References rz_coff_get_reloc_targets_map_base(), and RZ_COFF_RELOC_TARGET_SIZE.

Referenced by _fill_bin_symbol(), and relocs_foreach().