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

Go to the source code of this file.

Macros

#define MAX_SHARED_LIBS   1
 
#define FLAT_DATA_ALIGN   0x20
 
#define READ(x, i)
 

Functions

static bool bflt_init_hdr (RzBfltObj *bin)
 
static bool bflt_reloc_big_endian (RzBfltObj *bin)
 
static void bflt_load_relocs (RzBfltObj *bin)
 
static void patch_relocs_in (RzBfltObj *bin, RzVector *relocs)
 
static void bflt_patch_relocs (RzBfltObj *bin)
 
static bool rz_bflt_init (RzBfltObj *obj, RzBuffer *buf, ut64 baddr, bool big_endian, bool patch_relocs)
 
RzBfltObjrz_bflt_new_buf (RzBuffer *buf, ut64 baddr, bool big_endian, bool patch_relocs)
 
void rz_bflt_free (RzBfltObj *obj)
 
RzBinAddrrz_bflt_get_entry (RzBfltObj *bin)
 
ut64 rz_bflt_get_text_base (RzBfltObj *bin)
 Address to map text segment to. More...
 
ut64 rz_bflt_get_data_base (RzBfltObj *bin)
 Address to map data+bss segment to. More...
 
ut64 rz_bflt_get_data_vsize (RzBfltObj *bin)
 Total size of data+bss. More...
 
ut64 rz_bflt_paddr_to_vaddr (RzBfltObj *bin, ut32 paddr)
 

Detailed Description

uClinux bFLT file format For reference, see linux/include/uapi/linux/flat.h linux/fs/binfmt_flat.c in the uClinux kernel, e.g. from uClinux-dist-20160919

Definition in file bflt.c.

Macro Definition Documentation

◆ FLAT_DATA_ALIGN

#define FLAT_DATA_ALIGN   0x20

Definition at line 20 of file bflt.c.

◆ MAX_SHARED_LIBS

#define MAX_SHARED_LIBS   1

Definition at line 19 of file bflt.c.

◆ READ

#define READ (   x,
  i 
)
Value:
rz_read_be32((x) + (i)); \
(i) += 4;
lzma_index ** i
Definition: index.h:629
int x
Definition: mipsasm.c:20
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87

Definition at line 22 of file bflt.c.

Function Documentation

◆ bflt_init_hdr()

static bool bflt_init_hdr ( RzBfltObj bin)
static

Definition at line 26 of file bflt.c.

26  {
27  ut8 bhdr[BFLT_HDR_SIZE] = { 0 };
28  st64 len = rz_buf_read_at(bin->b, 0, bhdr, BFLT_HDR_SIZE);
29  if (len != BFLT_HDR_SIZE) {
30  RZ_LOG_WARN("read bFLT hdr failed\n");
31  return false;
32  }
33 
34  if (strncmp((const char *)bhdr, "bFLT", 4)) {
35  RZ_LOG_WARN("wrong magic number in bFLT file\n");
36  return false;
37  }
38 
39  size_t i = 4;
40  bin->hdr.rev = READ(bhdr, i);
41  bin->hdr.entry = READ(bhdr, i);
42  bin->hdr.data_start = READ(bhdr, i);
43  bin->hdr.data_end = READ(bhdr, i);
44  bin->hdr.bss_end = READ(bhdr, i);
45  bin->hdr.stack_size = READ(bhdr, i);
46  bin->hdr.reloc_start = READ(bhdr, i);
47  bin->hdr.reloc_count = READ(bhdr, i);
48  bin->hdr.flags = READ(bhdr, i);
49  bin->hdr.build_date = READ(bhdr, i);
50 
51  if (bin->hdr.rev != FLAT_VERSION) {
52  RZ_LOG_WARN("only bFLT v4 is supported! This file has version %" PFMT32u "\n", bin->hdr.rev);
53  return false;
54  }
55  if (bin->hdr.flags & FLAT_FLAG_GZIP || bin->hdr.flags & FLAT_FLAG_GZDATA) {
56  RZ_LOG_WARN("this bFLT file is compressed. This is not (yet) supported.\n");
57  }
58  return true;
59 }
size_t len
Definition: 6502dis.c:15
#define READ(x, i)
Definition: bflt.c:22
#define FLAT_FLAG_GZDATA
Definition: bflt.h:18
#define BFLT_HDR_SIZE
Definition: bflt.h:53
#define FLAT_VERSION
Definition: bflt.h:14
#define FLAT_FLAG_GZIP
Definition: bflt.h:17
uint8_t ut8
Definition: lh5801.h:11
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define PFMT32u
Definition: rz_types.h:409
#define st64
Definition: rz_types_base.h:10
Definition: malloc.c:26

References BFLT_HDR_SIZE, FLAT_FLAG_GZDATA, FLAT_FLAG_GZIP, FLAT_VERSION, i, len, PFMT32u, READ, rz_buf_read_at(), RZ_LOG_WARN, and st64.

Referenced by rz_bflt_init().

◆ bflt_load_relocs()

static void bflt_load_relocs ( RzBfltObj bin)
static

Definition at line 69 of file bflt.c.

69  {
70  bool big_endian = bflt_reloc_big_endian(bin);
71 
72  // got is a single table of 32bit values at the beginning of data
73  // to be rebased in-place, and terminated by -1
74  if (bin->hdr.flags & FLAT_FLAG_GOTPIC) {
75  for (ut64 offset = 0;; offset += 4) {
76  ut32 paddr = bin->hdr.data_start + offset;
77  if (paddr + 4 > bin->size || paddr + 4 < paddr) {
78  break;
79  }
80  ut32 value;
81  if (!rz_buf_read_ble32_at(bin->b, paddr, &value, big_endian)) {
82  break;
83  }
84  if (value == 0xffffffff) {
85  break;
86  }
87  RzBfltReloc *reloc = rz_vector_push(&bin->got_relocs, NULL);
88  if (!reloc) {
89  break;
90  }
91  reloc->reloc_paddr = paddr;
92  reloc->value_orig = value ? value + BFLT_HDR_SIZE : 0; // uClinux kernel leaves 0 relocs alone
93  }
94  }
95 
96  // addresses of other places to rebase are indirectly given in the reloc table
97  for (ut32 i = 0; i < bin->hdr.reloc_count; i++) {
98  ut32 table_paddr = bin->hdr.reloc_start + i * 4;
99  if (table_paddr + 4 > bin->size || table_paddr + 4 < bin->hdr.reloc_start) {
100  break;
101  }
102  ut32 reloc_paddr;
103  if (!rz_buf_read_be32_at(bin->b, table_paddr, &reloc_paddr)) {
104  break;
105  }
106  reloc_paddr += BFLT_HDR_SIZE;
107  if (reloc_paddr + 4 < reloc_paddr || reloc_paddr > bin->size) {
108  continue;
109  }
110  ut32 value;
111  if (!rz_buf_read_ble32_at(bin->b, reloc_paddr, &value, big_endian)) {
112  continue;
113  }
114  RzBfltReloc *reloc = rz_vector_push(&bin->got_relocs, NULL);
115  if (!reloc) {
116  break;
117  }
118  reloc->reloc_paddr = reloc_paddr;
119  reloc->value_orig = value + BFLT_HDR_SIZE;
120  }
121 }
static bool bflt_reloc_big_endian(RzBfltObj *bin)
Definition: bflt.c:61
#define FLAT_FLAG_GOTPIC
Definition: bflt.h:16
static int value
Definition: cmd_api.c:93
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
voidpf uLong offset
Definition: ioapi.h:144
#define rz_buf_read_be32_at(b, addr, result)
Definition: rz_buf.h:285
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
ut32 reloc_paddr
where to patch, offset from the beginning of the file
Definition: bflt.h:37
ut32 value_orig
original value at that address
Definition: bflt.h:38
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References BFLT_HDR_SIZE, bflt_reloc_big_endian(), FLAT_FLAG_GOTPIC, i, NULL, rz_bflt_reloc_t::reloc_paddr, rz_buf_read_be32_at, rz_vector_push(), ut64(), value, and rz_bflt_reloc_t::value_orig.

Referenced by rz_bflt_init().

◆ bflt_patch_relocs()

static void bflt_patch_relocs ( RzBfltObj bin)
static

Definition at line 137 of file bflt.c.

137  {
139  if (!bin->buf_patched) {
140  return;
141  }
142  patch_relocs_in(bin, &bin->got_relocs);
143  patch_relocs_in(bin, &bin->relocs);
145 }
static void patch_relocs_in(RzBfltObj *bin, RzVector *relocs)
Definition: bflt.c:123
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 patch_relocs_in(), rz_buf_new_sparse_overlay(), rz_buf_sparse_set_write_mode(), RZ_BUF_SPARSE_WRITE_MODE_SPARSE, and RZ_BUF_SPARSE_WRITE_MODE_THROUGH.

Referenced by rz_bflt_init().

◆ bflt_reloc_big_endian()

static bool bflt_reloc_big_endian ( RzBfltObj bin)
static

Definition at line 61 of file bflt.c.

61  {
62  // if bin->hdr.flags & FLAT_FLAG_GOTPIC, then all relocs
63  // are already in target order, otherwise they are always be
64  return (bin->hdr.flags & FLAT_FLAG_GOTPIC)
65  ? bin->big_endian
66  : true;
67 }

References FLAT_FLAG_GOTPIC.

Referenced by bflt_load_relocs().

◆ patch_relocs_in()

static void patch_relocs_in ( RzBfltObj bin,
RzVector relocs 
)
static

Definition at line 123 of file bflt.c.

123  {
124  RzBfltReloc *reloc;
125  rz_vector_foreach(relocs, reloc) {
126  if (!reloc->value_orig) {
127  // 0 relocs are not patched (this is some workaround for null pointers in the uClinux kernel)
128  continue;
129  }
130  rz_buf_write_ble32_at(bin->buf_patched,
131  reloc->reloc_paddr,
133  bin->big_endian);
134  }
135 }
ut64 rz_bflt_paddr_to_vaddr(RzBfltObj *bin, ut32 paddr)
Definition: bflt.c:208
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169

References rz_bflt_reloc_t::reloc_paddr, relocs(), rz_bflt_paddr_to_vaddr(), rz_vector_foreach, and rz_bflt_reloc_t::value_orig.

Referenced by bflt_patch_relocs().

◆ rz_bflt_free()

void rz_bflt_free ( RzBfltObj obj)

Definition at line 173 of file bflt.c.

173  {
174  if (obj) {
175  rz_buf_free(obj->b);
176  rz_buf_free(obj->buf_patched);
177  rz_vector_fini(&obj->relocs);
178  rz_vector_fini(&obj->got_relocs);
179  RZ_FREE(obj);
180  }
181 }
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
#define RZ_FREE(x)
Definition: rz_types.h:369
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RzBuffer * b
Definition: bflt.h:45
RzVector got_relocs
Definition: bflt.h:44
RzVector relocs
Definition: bflt.h:43
RzBuffer * buf_patched
overlay over the original file with relocs patched
Definition: bflt.h:46

References rz_bflt_obj_t::b, rz_bflt_obj_t::buf_patched, rz_bflt_obj_t::got_relocs, rz_bflt_obj_t::relocs, rz_buf_free(), RZ_FREE, and rz_vector_fini().

Referenced by destroy(), and rz_bflt_new_buf().

◆ rz_bflt_get_data_base()

ut64 rz_bflt_get_data_base ( RzBfltObj bin)

Address to map data+bss segment to.

Definition at line 198 of file bflt.c.

198  {
199  ut64 r = bin->baddr + bin->hdr.data_start + MAX_SHARED_LIBS * sizeof(ut32);
201 }
#define FLAT_DATA_ALIGN
Definition: bflt.c:20
#define MAX_SHARED_LIBS
Definition: bflt.c:19
#define r
Definition: crypto_rc6.c:12
static ut64 rz_num_align_delta(ut64 v, ut64 alignment)
Padding to align v to the next alignment-boundary.
Definition: rz_num.h:116

References FLAT_DATA_ALIGN, MAX_SHARED_LIBS, r, rz_num_align_delta(), and ut64().

Referenced by maps(), rz_bflt_paddr_to_vaddr(), and sections().

◆ rz_bflt_get_data_vsize()

ut64 rz_bflt_get_data_vsize ( RzBfltObj bin)

Total size of data+bss.

Definition at line 204 of file bflt.c.

204  {
205  return RZ_MAX(bin->hdr.data_end, bin->hdr.bss_end) - bin->hdr.data_start;
206 }
#define RZ_MAX(x, y)

References RZ_MAX.

Referenced by maps(), and sections().

◆ rz_bflt_get_entry()

RzBinAddr* rz_bflt_get_entry ( RzBfltObj bin)

Definition at line 183 of file bflt.c.

183  {
185  if (addr && bin) {
186  addr->paddr = bin->hdr.entry;
187  addr->vaddr = rz_bflt_get_text_base(bin) + bin->hdr.entry;
188  }
189  return addr;
190 }
ut64 rz_bflt_get_text_base(RzBfltObj *bin)
Address to map text segment to.
Definition: bflt.c:193
#define RZ_NEW0(x)
Definition: rz_types.h:284
static int addr
Definition: z80asm.c:58

References addr, rz_bflt_get_text_base(), and RZ_NEW0.

Referenced by entries().

◆ rz_bflt_get_text_base()

ut64 rz_bflt_get_text_base ( RzBfltObj bin)

Address to map text segment to.

Definition at line 193 of file bflt.c.

193  {
194  return bin->baddr;
195 }

Referenced by maps(), rz_bflt_get_entry(), and sections().

◆ rz_bflt_init()

static bool rz_bflt_init ( RzBfltObj obj,
RzBuffer buf,
ut64  baddr,
bool  big_endian,
bool  patch_relocs 
)
static

Definition at line 147 of file bflt.c.

147  {
148  obj->b = rz_buf_ref(buf);
149  obj->size = rz_buf_size(buf);
150  obj->big_endian = big_endian;
151  rz_vector_init(&obj->relocs, sizeof(RzBfltReloc), NULL, NULL);
152  rz_vector_init(&obj->got_relocs, sizeof(RzBfltReloc), NULL, NULL);
153  obj->baddr = baddr == UT64_MAX ? 0 : baddr;
154  if (!bflt_init_hdr(obj)) {
155  return false;
156  }
157  bflt_load_relocs(obj);
158  if (patch_relocs) {
159  bflt_patch_relocs(obj);
160  }
161  return true;
162 }
static void bflt_patch_relocs(RzBfltObj *bin)
Definition: bflt.c:137
static bool bflt_init_hdr(RzBfltObj *bin)
Definition: bflt.c:26
static void bflt_load_relocs(RzBfltObj *bin)
Definition: bflt.c:69
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
voidpf void * buf
Definition: ioapi.h:138
RZ_API void MACH0_() patch_relocs(RzBinFile *bf, struct MACH0_(obj_t) *obj)
Patching of external relocs in a sparse overlay buffer.
Definition: mach0_relocs.c:614
RZ_API RzBuffer * rz_buf_ref(RzBuffer *b)
Increment the reference count of the buffer.
Definition: buf.c:668
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
bool big_endian
Definition: bflt.h:48
size_t size
Definition: bflt.h:49
ut64 baddr
Definition: bflt.h:47

References rz_bflt_obj_t::b, rz_bflt_obj_t::baddr, baddr(), bflt_init_hdr(), bflt_load_relocs(), bflt_patch_relocs(), rz_bflt_obj_t::big_endian, rz_bflt_obj_t::got_relocs, NULL, patch_relocs(), rz_bflt_obj_t::relocs, rz_buf_ref(), rz_buf_size(), rz_vector_init(), rz_bflt_obj_t::size, and UT64_MAX.

Referenced by rz_bflt_new_buf().

◆ rz_bflt_new_buf()

RzBfltObj* rz_bflt_new_buf ( RzBuffer buf,
ut64  baddr,
bool  big_endian,
bool  patch_relocs 
)

Definition at line 164 of file bflt.c.

164  {
166  if (bin && rz_bflt_init(bin, buf, baddr, big_endian, patch_relocs)) {
167  return bin;
168  }
169  rz_bflt_free(bin);
170  return NULL;
171 }
static bool rz_bflt_init(RzBfltObj *obj, RzBuffer *buf, ut64 baddr, bool big_endian, bool patch_relocs)
Definition: bflt.c:147
void rz_bflt_free(RzBfltObj *obj)
Definition: bflt.c:173

References baddr(), NULL, patch_relocs(), rz_bflt_free(), rz_bflt_init(), and RZ_NEW0.

Referenced by load_buffer().

◆ rz_bflt_paddr_to_vaddr()

ut64 rz_bflt_paddr_to_vaddr ( RzBfltObj bin,
ut32  paddr 
)

Definition at line 208 of file bflt.c.

208  {
209  if (paddr >= bin->hdr.data_start) {
210  return rz_bflt_get_data_base(bin) + paddr - bin->hdr.data_start;
211  }
212  return bin->baddr + paddr;
213 }
ut64 rz_bflt_get_data_base(RzBfltObj *bin)
Address to map data+bss segment to.
Definition: bflt.c:198

References rz_bflt_get_data_base().

Referenced by convert_relocs(), and patch_relocs_in().