Rizin
unix-like reverse engineering framework and cli tools
bin_bflt.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-FileCopyrightText: 2016-2019 Oscar Salvador <osalvador.vilardaga@gmail.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_types.h>
6 #include <rz_util.h>
7 #include <rz_lib.h>
8 #include <rz_bin.h>
9 #include <rz_io.h>
10 #include "bflt/bflt.h"
11 
12 #define VFILE_NAME_PATCHED "patched"
13 
14 static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
16  return obj->bin_obj;
17 }
18 
19 static RzList *entries(RzBinFile *bf) {
20  RzBfltObj *obj = bf->o->bin_obj;
21  RzList *ret;
22  RzBinAddr *ptr;
23 
24  if (!(ret = rz_list_newf(free))) {
25  return NULL;
26  }
27  ptr = rz_bflt_get_entry(obj);
28  if (!ptr) {
29  rz_list_free(ret);
30  return NULL;
31  }
32  rz_list_append(ret, ptr);
33  return ret;
34 }
35 
36 static RzList *maps(RzBinFile *bf) {
37  RzBfltObj *obj = bf->o->bin_obj;
39  if (!ret) {
40  return NULL;
41  }
42 
44  if (!map) {
45  rz_list_free(ret);
46  return NULL;
47  }
48  map->paddr = 0;
49  map->vaddr = rz_bflt_get_text_base(obj);
50  map->psize = obj->hdr.data_start;
51  map->vsize = obj->hdr.data_start;
52  map->perm = RZ_PERM_RWX;
53  map->name = strdup("hdr+text");
54  map->vfile_name = obj->buf_patched ? strdup(VFILE_NAME_PATCHED) : NULL;
55  rz_list_append(ret, map);
56 
57  map = RZ_NEW0(RzBinMap);
58  if (!map) {
59  rz_list_free(ret);
60  return NULL;
61  }
62  map->paddr = obj->hdr.data_start;
63  map->vaddr = rz_bflt_get_data_base(obj);
64  map->psize = obj->hdr.data_end - obj->hdr.data_start;
65  map->vsize = rz_bflt_get_data_vsize(obj);
66  map->perm = RZ_PERM_RWX;
67  map->name = strdup("data+bss");
68  map->vfile_name = obj->buf_patched ? strdup(VFILE_NAME_PATCHED) : NULL;
69  rz_list_append(ret, map);
70 
71  return ret;
72 }
73 
74 static RzList *sections(RzBinFile *bf) {
75  RzBfltObj *obj = bf->o->bin_obj;
77  if (!ret) {
78  return NULL;
79  }
80 
81  // segments
82 
84  if (!sec) {
85  goto beach;
86  }
87  sec->paddr = 0;
88  sec->vaddr = rz_bflt_get_text_base(obj);
89  sec->size = obj->hdr.data_start;
90  sec->vsize = obj->hdr.data_start;
91  sec->perm = RZ_PERM_RWX;
92  sec->name = strdup("TEXT");
93  sec->is_segment = true;
94  rz_list_push(ret, sec);
95 
96  sec = RZ_NEW0(RzBinSection);
97  if (!sec) {
98  goto beach;
99  }
100  sec->paddr = obj->hdr.data_start;
101  sec->vaddr = rz_bflt_get_data_base(obj);
102  sec->size = obj->hdr.data_start;
103  sec->vsize = rz_bflt_get_data_vsize(obj);
104  sec->perm = RZ_PERM_RWX;
105  sec->name = strdup("DATA");
106  sec->is_segment = true;
107  rz_list_push(ret, sec);
108 
109  // sections
110 
111  sec = RZ_NEW0(RzBinSection);
112  if (!sec) {
113  goto beach;
114  }
115  sec->paddr = 0;
116  sec->vaddr = rz_bflt_get_text_base(obj);
117  sec->size = BFLT_HDR_SIZE;
118  sec->vsize = BFLT_HDR_SIZE;
119  sec->perm = RZ_PERM_RWX;
120  sec->name = strdup("header");
121  rz_list_push(ret, sec);
122 
123  sec = RZ_NEW0(RzBinSection);
124  if (!sec) {
125  goto beach;
126  }
127  sec->paddr = BFLT_HDR_SIZE;
129  sec->size = obj->hdr.data_start - BFLT_HDR_SIZE;
130  sec->vsize = obj->hdr.data_start - BFLT_HDR_SIZE;
131  sec->perm = RZ_PERM_RWX;
132  sec->name = strdup("text");
133  rz_list_push(ret, sec);
134 
135  sec = RZ_NEW0(RzBinSection);
136  if (!sec) {
137  goto beach;
138  }
139  sec->paddr = obj->hdr.data_start;
140  sec->vaddr = rz_bflt_get_data_base(obj);
141  sec->size = obj->hdr.data_end - obj->hdr.data_start;
142  sec->vsize = obj->hdr.data_end - obj->hdr.data_start;
143  sec->perm = RZ_PERM_RWX;
144  sec->name = strdup("data");
145  sec->is_data = true;
146  rz_list_push(ret, sec);
147 
148  sec = RZ_NEW0(RzBinSection);
149  if (!sec) {
150  goto beach;
151  }
152  sec->paddr = obj->hdr.data_end;
153  sec->vaddr = rz_bflt_get_data_base(obj) + obj->hdr.data_end - obj->hdr.data_start;
154  sec->size = 0;
155  sec->vsize = obj->hdr.bss_end - obj->hdr.data_end;
156  sec->perm = RZ_PERM_RWX;
157  sec->name = strdup("bss");
158  sec->is_data = true;
159  rz_list_push(ret, sec);
160 
161  return ret;
162 beach:
163  rz_list_free(ret);
164  return NULL;
165 }
166 
168  RzBfltObj *obj = bf->o->bin_obj;
170  if (!r) {
171  return NULL;
172  }
173  if (obj->buf_patched) {
175  if (!vf) {
176  return r;
177  }
178  vf->buf = obj->buf_patched;
180  rz_list_push(r, vf);
181  }
182  return r;
183 }
184 
185 static void convert_relocs(RzBfltObj *bin, RzList *out, RzVector /*<RzBfltReloc>*/ *relocs) {
186  RzBfltReloc *br;
189  if (!r) {
190  return;
191  }
192  r->type = RZ_BIN_RELOC_32;
193  r->paddr = br->reloc_paddr;
194  r->vaddr = rz_bflt_paddr_to_vaddr(bin, r->paddr);
195 
196  // 0 preserved, see also patching in bflt.c
197  r->target_vaddr = br->value_orig ? rz_bflt_paddr_to_vaddr(bin, br->value_orig) : 0;
198 
199  rz_list_push(out, r);
200  }
201 }
202 
203 static RzList *relocs(RzBinFile *bf) {
204  RzBfltObj *obj = (RzBfltObj *)bf->o->bin_obj;
206  if (!list || !obj) {
208  return NULL;
209  }
210  convert_relocs(obj, list, &obj->got_relocs);
211  convert_relocs(obj, list, &obj->relocs);
212  return list;
213 }
214 
215 static RzBinInfo *info(RzBinFile *bf) {
216  RzBfltObj *obj = NULL;
217  RzBinInfo *info = NULL;
218  if (!bf || !bf->o || !bf->o->bin_obj) {
219  return NULL;
220  }
221  obj = (RzBfltObj *)bf->o->bin_obj;
222  if (!(info = RZ_NEW0(RzBinInfo))) {
223  return NULL;
224  }
225  info->file = bf->file ? strdup(bf->file) : NULL;
226  info->rclass = strdup("bflt");
227  info->bclass = strdup("bflt");
228  info->type = strdup("bFLT (Executable file)");
229  info->os = strdup("Linux");
230  info->subsystem = strdup("uClinux");
231  info->arch = strdup("arm"); // this is a wild guess, the format does not specify any arch, but arm is probably the most popular
232  info->big_endian = obj->big_endian;
233  info->bits = 32;
234  info->has_va = true;
235  info->dbg_info = 0;
236  info->machine = strdup("unknown");
237  info->has_pi = true;
238  return info;
239 }
240 
241 static bool check_buffer(RzBuffer *buf) {
242  ut8 tmp[4];
243  int r = rz_buf_read_at(buf, 0, tmp, sizeof(tmp));
244  return r == sizeof(tmp) && !memcmp(tmp, "bFLT", 4);
245 }
246 
247 static void destroy(RzBinFile *bf) {
248  rz_bflt_free(bf->o->bin_obj);
249 }
250 
251 static RzList *strings(RzBinFile *bf) {
252  return rz_bin_file_strings(bf, 0, false);
253 }
254 
256  .name = "bflt",
257  .desc = "bFLT uClinux executable",
258  .license = "LGPL3",
259  .load_buffer = &load_buffer,
260  .destroy = &destroy,
261  .check_buffer = &check_buffer,
262  .virtual_files = &virtual_files,
263  .maps = &maps,
264  .entries = &entries,
265  .sections = &sections,
266  .strings = &strings,
267  .info = &info,
268  .relocs = &relocs
269 };
270 
271 #ifndef RZ_PLUGIN_INCORE
274  .data = &rz_bin_plugin_bflt,
276 };
277 #endif
RZ_API RZ_OWN RzList * rz_bin_file_strings(RZ_NONNULL RzBinFile *bf, size_t min_length, bool raw_strings)
Generates a RzList struct containing RzBinString from a given RzBinFile.
Definition: bfile_string.c:325
ut64 rz_bflt_get_data_base(RzBfltObj *bin)
Address to map data+bss segment to.
Definition: bflt.c:198
RzBinAddr * rz_bflt_get_entry(RzBfltObj *bin)
Definition: bflt.c:183
RzBfltObj * rz_bflt_new_buf(RzBuffer *buf, ut64 baddr, bool big_endian, bool patch_relocs)
Definition: bflt.c:164
void rz_bflt_free(RzBfltObj *obj)
Definition: bflt.c:173
ut64 rz_bflt_paddr_to_vaddr(RzBfltObj *bin, ut32 paddr)
Definition: bflt.c:208
ut64 rz_bflt_get_data_vsize(RzBfltObj *bin)
Total size of data+bss.
Definition: bflt.c:204
ut64 rz_bflt_get_text_base(RzBfltObj *bin)
Address to map text segment to.
Definition: bflt.c:193
#define BFLT_HDR_SIZE
Definition: bflt.h:53
RZ_API void rz_bin_map_free(RzBinMap *map)
Definition: bin.c:1023
RZ_API void rz_bin_section_free(RzBinSection *bs)
Definition: bin.c:1116
RZ_API void rz_bin_virtual_file_free(RzBinVirtualFile *vfile)
Definition: bin.c:1012
RzBinPlugin rz_bin_plugin_bflt
Definition: bin_bflt.c:255
static bool check_buffer(RzBuffer *buf)
Definition: bin_bflt.c:241
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_bflt.c:14
static void convert_relocs(RzBfltObj *bin, RzList *out, RzVector *relocs)
Definition: bin_bflt.c:185
static RzList * strings(RzBinFile *bf)
Definition: bin_bflt.c:251
static void destroy(RzBinFile *bf)
Definition: bin_bflt.c:247
RZ_API RzLibStruct rizin_plugin
Definition: bin_bflt.c:272
#define VFILE_NAME_PATCHED
Definition: bin_bflt.c:12
static RzList * virtual_files(RzBinFile *bf)
Definition: bin_bflt.c:167
static RzBinInfo * info(RzBinFile *bf)
Definition: bin_bflt.c:215
static RzList * entries(RzBinFile *bf)
Definition: bin_bflt.c:19
static RzList * maps(RzBinFile *bf)
Definition: bin_bflt.c:36
static RzList * sections(RzBinFile *bf)
Definition: bin_bflt.c:74
static RzList * relocs(RzBinFile *bf)
Definition: bin_bflt.c:203
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
static void list(RzEgg *egg)
Definition: rz-gg.c:52
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
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
@ RZ_BIN_RELOC_32
Definition: rz_bin.h:176
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
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_RWX
Definition: rz_types.h:98
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
#define RZ_VERSION
Definition: rz_version.h:8
#define br(opcode, mask, lose, flags)
Definition: malloc.c:26
ut32 data_start
Definition: bflt.h:25
ut32 bss_end
Definition: bflt.h:27
ut32 data_end
Definition: bflt.h:26
bool big_endian
Definition: bflt.h:48
RzBfltHdr hdr
Definition: bflt.h:42
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
bool patch_relocs
ask the bin plugin to fill relocs with valid contents for analysis
Definition: rz_bin.h:250
ut64 baseaddr
where the linker maps the binary in memory
Definition: rz_bin.h:248
bool big_endian
only used for binary formats that do not specify the endian in the file, but need it to load,...
Definition: rz_bin.h:251
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
char * file
Definition: rz_bin.h:299
int has_va
Definition: rz_bin.h:228
char * type
Definition: rz_bin.h:211
char * os
Definition: rz_bin.h:219
char * subsystem
Definition: rz_bin.h:220
int has_pi
Definition: rz_bin.h:229
char * machine
Definition: rz_bin.h:216
char * bclass
Definition: rz_bin.h:212
char * file
Definition: rz_bin.h:210
ut64 dbg_info
Definition: rz_bin.h:240
char * rclass
Definition: rz_bin.h:213
char * arch
Definition: rz_bin.h:214
int big_endian
Definition: rz_bin.h:235
Description of a single memory mapping into virtual memory from a binary.
Definition: rz_bin.h:602
RzBinObjectLoadOptions opts
Definition: rz_bin.h:260
void * bin_obj
Definition: rz_bin.h:293
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
bool is_segment
Definition: rz_bin.h:634
char * name
Definition: rz_bin.h:619
RZ_NONNULL RzBuffer * buf
Definition: rz_bin.h:597
RZ_OWN RZ_NONNULL char * name
Definition: rz_bin.h:596
Definition: sdb.h:63
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4