1 /* radare2 - LGPL - Copyright 2009-2020 - pancake, nibble, dso */
2
3 #include <r_bin.h>
4 #include <r_types.h>
5 #include <r_util.h>
6 #include <r_lib.h>
7 #include <r_io.h>
8 #include <config.h>
9 #include "i/private.h"
10
11 R_LIB_VERSION (r_bin);
12
13 #define DB a->sdb;
14 #define RBINLISTFREE(x)\
15 if (x) { \
16 r_list_free (x);\
17 (x) = NULL;\
18 }
19
20 #define ARCHS_KEY "archs"
21
22 #if !defined(R_BIN_STATIC_PLUGINS)
23 #define R_BIN_STATIC_PLUGINS 0
24 #endif
25 #if !defined(R_BIN_XTR_STATIC_PLUGINS)
26 #define R_BIN_XTR_STATIC_PLUGINS 0
27 #endif
28 #if !defined(R_BIN_LDR_STATIC_PLUGINS)
29 #define R_BIN_LDR_STATIC_PLUGINS 0
30 #endif
31
32 static RBinPlugin *bin_static_plugins[] = { R_BIN_STATIC_PLUGINS, NULL };
33 static RBinXtrPlugin *bin_xtr_static_plugins[] = { R_BIN_XTR_STATIC_PLUGINS, NULL };
34 static RBinLdrPlugin *bin_ldr_static_plugins[] = { R_BIN_LDR_STATIC_PLUGINS, NULL };
35
__getoffset(RBin * bin,int type,int idx)36 static int __getoffset(RBin *bin, int type, int idx) {
37 RBinFile *a = r_bin_cur (bin);
38 RBinPlugin *plugin = r_bin_file_cur_plugin (a);
39 if (plugin && plugin->get_offset) {
40 return plugin->get_offset (a, type, idx);
41 }
42 return -1;
43 }
44
__getname(RBin * bin,int type,int idx,bool sd)45 static const char *__getname(RBin *bin, int type, int idx, bool sd) {
46 RBinFile *a = r_bin_cur (bin);
47 RBinPlugin *plugin = r_bin_file_cur_plugin (a);
48 if (plugin && plugin->get_name) {
49 return plugin->get_name (a, type, idx, sd);
50 }
51 return NULL;
52 }
53
binobj_a2b(RBinObject * o,ut64 addr)54 static ut64 binobj_a2b(RBinObject *o, ut64 addr) {
55 return o ? addr + o->baddr_shift : addr;
56 }
57
58 // TODO: move these two function do a different file
r_bin_xtrdata_new(RBuffer * buf,ut64 offset,ut64 size,ut32 file_count,RBinXtrMetadata * metadata)59 R_API RBinXtrData *r_bin_xtrdata_new(RBuffer *buf, ut64 offset, ut64 size, ut32 file_count, RBinXtrMetadata *metadata) {
60 RBinXtrData *data = R_NEW0 (RBinXtrData);
61 if (data) {
62 data->offset = offset;
63 data->size = size;
64 data->file_count = file_count;
65 data->metadata = metadata;
66 data->loaded = 0;
67 // don't slice twice TODO. review this
68 data->buf = r_buf_ref (buf); // r_buf_new_slice (buf, offset, size);
69 }
70 return data;
71 }
72
r_bin_string_type(int type)73 R_API const char *r_bin_string_type(int type) {
74 switch (type) {
75 case 'a': return "ascii";
76 case 'u': return "utf8";
77 case 'w': return "utf16le";
78 case 'W': return "utf32le";
79 case 'b': return "base64";
80 }
81 return "ascii"; // XXX
82 }
83
r_bin_xtrdata_free(void * data_)84 R_API void r_bin_xtrdata_free(void /*RBinXtrData*/ *data_) {
85 RBinXtrData *data = data_;
86 r_return_if_fail (data);
87 if (data->metadata) {
88 free (data->metadata->libname);
89 free (data->metadata->arch);
90 free (data->metadata->machine);
91 free (data->metadata);
92 }
93 free (data->file);
94 r_buf_free (data->buf);
95 free (data);
96 }
97
r_bin_raw_strings(RBinFile * bf,int min)98 R_API RList *r_bin_raw_strings(RBinFile *bf, int min) {
99 r_return_val_if_fail (bf, NULL);
100 return r_bin_file_get_strings (bf, min, 0, 2);
101 }
102
r_bin_dump_strings(RBinFile * bf,int min,int raw)103 R_API RList *r_bin_dump_strings(RBinFile *bf, int min, int raw) {
104 r_return_val_if_fail (bf, NULL);
105 return r_bin_file_get_strings (bf, min, 1, raw);
106 }
107
r_bin_options_init(RBinOptions * opt,int fd,ut64 baseaddr,ut64 loadaddr,int rawstr)108 R_API void r_bin_options_init(RBinOptions *opt, int fd, ut64 baseaddr, ut64 loadaddr, int rawstr) {
109 memset (opt, 0, sizeof (*opt));
110 opt->baseaddr = baseaddr;
111 opt->loadaddr = loadaddr;
112 opt->fd = fd;
113 opt->rawstr = rawstr;
114 }
115
r_bin_arch_options_init(RBinArchOptions * opt,const char * arch,int bits)116 R_API void r_bin_arch_options_init(RBinArchOptions *opt, const char *arch, int bits) {
117 opt->arch = arch? arch: R_SYS_ARCH;
118 opt->bits = bits? bits: R_SYS_BITS;
119 }
120
r_bin_file_hash_free(RBinFileHash * fhash)121 R_API void r_bin_file_hash_free(RBinFileHash *fhash) {
122 if (fhash) {
123 R_FREE (fhash->type);
124 R_FREE (fhash->hex);
125 free (fhash);
126 }
127 }
128
r_bin_info_free(RBinInfo * rb)129 R_API void r_bin_info_free(RBinInfo *rb) {
130 if (!rb) {
131 return;
132 }
133
134 r_list_free (rb->file_hashes);
135 free (rb->intrp);
136 free (rb->file);
137 free (rb->type);
138 free (rb->bclass);
139 free (rb->rclass);
140 free (rb->arch);
141 free (rb->cpu);
142 free (rb->machine);
143 free (rb->os);
144 free (rb->subsystem);
145 free (rb->default_cc);
146 free (rb->rpath);
147 free (rb->guid);
148 free (rb->debug_file_name);
149 free (rb->actual_checksum);
150 free (rb->claimed_checksum);
151 free (rb->compiler);
152 free (rb->head_flag);
153 free (rb);
154 }
155
r_bin_import_clone(RBinImport * o)156 R_API RBinImport *r_bin_import_clone(RBinImport *o) {
157 r_return_val_if_fail (o, NULL);
158
159 RBinImport *res = r_mem_dup (o, sizeof (*o));
160 if (res) {
161 res->name = R_STR_DUP (o->name);
162 res->classname = R_STR_DUP (o->classname);
163 res->descriptor = R_STR_DUP (o->descriptor);
164 }
165 return res;
166 }
167
r_bin_import_free(void * _imp)168 R_API void r_bin_import_free(void *_imp) {
169 RBinImport *imp = (RBinImport *)_imp;
170 if (imp) {
171 R_FREE (imp->name);
172 R_FREE (imp->libname);
173 R_FREE (imp->classname);
174 R_FREE (imp->descriptor);
175 free (imp);
176 }
177 }
178
r_bin_symbol_name(RBinSymbol * s)179 R_API const char *r_bin_symbol_name(RBinSymbol *s) {
180 if (s->dup_count) {
181 return sdb_fmt ("%s_%d", s->name, s->dup_count);
182 }
183 return s->name;
184 }
185
r_bin_symbol_new(const char * name,ut64 paddr,ut64 vaddr)186 R_API RBinSymbol *r_bin_symbol_new(const char *name, ut64 paddr, ut64 vaddr) {
187 RBinSymbol *sym = R_NEW0 (RBinSymbol);
188 if (sym) {
189 sym->name = name? strdup (name): NULL;
190 sym->paddr = paddr;
191 sym->vaddr = vaddr;
192 }
193 return sym;
194 }
195
r_bin_symbol_free(void * _sym)196 R_API void r_bin_symbol_free(void *_sym) {
197 RBinSymbol *sym = (RBinSymbol *)_sym;
198 if (sym) {
199 free (sym->name);
200 free (sym->libname);
201 free (sym->classname);
202 free (sym);
203 }
204 }
205
r_bin_string_free(void * _str)206 R_API void r_bin_string_free(void *_str) {
207 RBinString *str = (RBinString *)_str;
208 if (str) {
209 free (str->string);
210 free (str);
211 }
212 }
213
214 // XXX - change this to RBinObject instead of RBinFile
215 // makes no sense to pass in a binfile and set the RBinObject
216 // kinda a clunky functions
217 // XXX - this is a rather hacky way to do things, there may need to be a better
218 // way.
r_bin_open(RBin * bin,const char * file,RBinOptions * opt)219 R_API bool r_bin_open(RBin *bin, const char *file, RBinOptions *opt) {
220 r_return_val_if_fail (bin && bin->iob.io && opt, false);
221
222 RIOBind *iob = &(bin->iob);
223 if (!iob->desc_get (iob->io, opt->fd)) {
224 opt->fd = iob->fd_open (iob->io, file, R_PERM_R, 0644);
225 }
226 if (opt->fd < 0) {
227 eprintf ("Couldn't open bin for file '%s'\n", file);
228 return false;
229 }
230 opt->sz = 0;
231 opt->pluginname = NULL;
232 return r_bin_open_io (bin, opt);
233 }
234
r_bin_reload(RBin * bin,ut32 bf_id,ut64 baseaddr)235 R_API bool r_bin_reload(RBin *bin, ut32 bf_id, ut64 baseaddr) {
236 r_return_val_if_fail (bin, false);
237
238 RBinFile *bf = r_bin_file_find_by_id (bin, bf_id);
239 if (!bf) {
240 eprintf ("r_bin_reload: No file to reopen\n");
241 return false;
242 }
243 RBinOptions opt;
244 r_bin_options_init (&opt, bf->fd, baseaddr, bf->loadaddr, bin->rawstr);
245 opt.filename = bf->file;
246
247 bool res = r_bin_open_buf (bin, bf->buf, &opt);
248 r_bin_file_delete (bin, bf->id);
249 return res;
250 }
251
r_bin_open_buf(RBin * bin,RBuffer * buf,RBinOptions * opt)252 R_API bool r_bin_open_buf(RBin *bin, RBuffer *buf, RBinOptions *opt) {
253 r_return_val_if_fail (bin && opt, false);
254
255 RListIter *it;
256 RBinXtrPlugin *xtr;
257
258 bin->rawstr = opt->rawstr;
259 bin->file = opt->filename;
260 if (opt->loadaddr == UT64_MAX) {
261 opt->loadaddr = 0;
262 }
263
264 RBinFile *bf = NULL;
265 if (bin->use_xtr && !opt->pluginname) {
266 // XXX - for the time being this is fine, but we may want to
267 // change the name to something like
268 // <xtr_name>:<bin_type_name>
269 r_list_foreach (bin->binxtrs, it, xtr) {
270 if (!xtr->check_buffer) {
271 eprintf ("Missing check_buffer callback for '%s'\n", xtr->name);
272 continue;
273 }
274 if (xtr->check_buffer (buf)) {
275 if (xtr->extract_from_buffer || xtr->extractall_from_buffer ||
276 xtr->extract_from_bytes || xtr->extractall_from_bytes) {
277 bf = r_bin_file_xtr_load_buffer (bin, xtr,
278 bin->file, buf, opt->baseaddr, opt->loadaddr,
279 opt->xtr_idx, opt->fd, bin->rawstr);
280 }
281 }
282 }
283 }
284 if (!bf) {
285 // Uncomment for this speedup: 20s vs 22s
286 // RBuffer *buf = r_buf_new_slurp (bin->file);
287 bf = r_bin_file_new_from_buffer (bin, bin->file, buf, bin->rawstr,
288 opt->baseaddr, opt->loadaddr, opt->fd, opt->pluginname);
289 if (!bf) {
290 return false;
291 }
292 }
293 if (!r_bin_file_set_cur_binfile (bin, bf)) {
294 return false;
295 }
296 r_id_storage_set (bin->ids, bin->cur, bf->id);
297 return true;
298 }
299
r_bin_open_io(RBin * bin,RBinOptions * opt)300 R_API bool r_bin_open_io(RBin *bin, RBinOptions *opt) {
301 r_return_val_if_fail (bin && opt && bin->iob.io, false);
302 r_return_val_if_fail (opt->fd >= 0 && (st64)opt->sz >= 0, false);
303
304 RIOBind *iob = &(bin->iob);
305 RIO *io = iob? iob->io: NULL;
306
307 bool is_debugger = iob->fd_is_dbg (io, opt->fd);
308 const char *fname = iob->fd_get_name (io, opt->fd);
309 if (opt->loadaddr == UT64_MAX) {
310 opt->loadaddr = 0;
311 }
312
313 // Create RBuffer from the opened file
314 // When debugging something, we want to open the backed file because
315 // not all binary info are mapped in the virtual space. If that is not
316 // possible (e.g. remote file) just try to load bin info from the
317 // debugee process.
318 RBuffer *buf = NULL;
319 if (is_debugger) {
320 buf = r_buf_new_file (fname, O_RDONLY, 0);
321 is_debugger = false;
322 }
323 if (!buf) {
324 buf = r_buf_new_with_io (&bin->iob, opt->fd);
325 }
326 if (!buf) {
327 return false;
328 }
329
330 if (!opt->sz) {
331 opt->sz = r_buf_size (buf);
332 }
333
334 // Slice buffer if necessary
335 RBuffer *slice = buf;
336 if (!is_debugger && (opt->loadaddr != 0 || opt->sz != r_buf_size (buf))) {
337 slice = r_buf_new_slice (buf, opt->loadaddr, opt->sz);
338 } else if (is_debugger && opt->baseaddr != UT64_MAX && opt->baseaddr != 0) {
339 slice = r_buf_new_slice (buf, opt->baseaddr, opt->sz);
340 }
341 if (slice != buf) {
342 r_buf_free (buf);
343 buf = slice;
344 }
345
346 opt->filename = fname;
347 bool res = r_bin_open_buf (bin, buf, opt);
348 r_buf_free (buf);
349 return res;
350 }
351
r_bin_get_binplugin_by_name(RBin * bin,const char * name)352 R_IPI RBinPlugin *r_bin_get_binplugin_by_name(RBin *bin, const char *name) {
353 RBinPlugin *plugin;
354 RListIter *it;
355
356 r_return_val_if_fail (bin && name, NULL);
357
358 r_list_foreach (bin->plugins, it, plugin) {
359 if (!strcmp (plugin->name, name)) {
360 return plugin;
361 }
362 }
363 return NULL;
364 }
365
r_bin_get_binplugin_by_buffer(RBin * bin,RBuffer * buf)366 R_API RBinPlugin *r_bin_get_binplugin_by_buffer(RBin *bin, RBuffer *buf) {
367 RBinPlugin *plugin;
368 RListIter *it;
369
370 r_return_val_if_fail (bin && buf, NULL);
371
372 r_list_foreach (bin->plugins, it, plugin) {
373 if (plugin->check_buffer) {
374 if (plugin->check_buffer (buf)) {
375 return plugin;
376 }
377 }
378 }
379 return NULL;
380 }
381
r_bin_get_xtrplugin_by_name(RBin * bin,const char * name)382 R_IPI RBinXtrPlugin *r_bin_get_xtrplugin_by_name(RBin *bin, const char *name) {
383 RBinXtrPlugin *xtr;
384 RListIter *it;
385
386 r_return_val_if_fail (bin && name, NULL);
387
388 // TODO: use a hashtable here
389 r_list_foreach (bin->binxtrs, it, xtr) {
390 if (!strcmp (xtr->name, name)) {
391 return xtr;
392 }
393 // must be set to null
394 xtr = NULL;
395 }
396 return NULL;
397 }
398
r_bin_plugin_free(RBinPlugin * p)399 static void r_bin_plugin_free(RBinPlugin *p) {
400 if (p && p->fini) {
401 p->fini (NULL);
402 }
403 R_FREE (p);
404 }
405
406 // rename to r_bin_plugin_add like the rest
r_bin_add(RBin * bin,RBinPlugin * foo)407 R_API bool r_bin_add(RBin *bin, RBinPlugin *foo) {
408 RListIter *it;
409 RBinPlugin *plugin;
410
411 r_return_val_if_fail (bin && foo, false);
412
413 if (foo->init) {
414 foo->init (bin->user);
415 }
416 r_list_foreach (bin->plugins, it, plugin) {
417 if (!strcmp (plugin->name, foo->name)) {
418 return false;
419 }
420 }
421 plugin = R_NEW0 (RBinPlugin);
422 memcpy (plugin, foo, sizeof (RBinPlugin));
423 r_list_append (bin->plugins, plugin);
424 return true;
425 }
426
r_bin_ldr_add(RBin * bin,RBinLdrPlugin * foo)427 R_API bool r_bin_ldr_add(RBin *bin, RBinLdrPlugin *foo) {
428 RListIter *it;
429 RBinLdrPlugin *ldr;
430
431 r_return_val_if_fail (bin && foo, false);
432
433 if (foo->init) {
434 foo->init (bin->user);
435 }
436 // avoid duplicates
437 r_list_foreach (bin->binldrs, it, ldr) {
438 if (!strcmp (ldr->name, foo->name)) {
439 return false;
440 }
441 }
442 r_list_append (bin->binldrs, foo);
443 return true;
444 }
445
r_bin_xtr_add(RBin * bin,RBinXtrPlugin * foo)446 R_API bool r_bin_xtr_add(RBin *bin, RBinXtrPlugin *foo) {
447 RListIter *it;
448 RBinXtrPlugin *xtr;
449
450 r_return_val_if_fail (bin && foo, false);
451
452 if (foo->init) {
453 foo->init (bin->user);
454 }
455 // avoid duplicates
456 r_list_foreach (bin->binxtrs, it, xtr) {
457 if (!strcmp (xtr->name, foo->name)) {
458 return false;
459 }
460 }
461 r_list_append (bin->binxtrs, foo);
462 return true;
463 }
464
r_bin_free(RBin * bin)465 R_API void r_bin_free(RBin *bin) {
466 if (bin) {
467 bin->file = NULL;
468 free (bin->force);
469 free (bin->srcdir);
470 free (bin->strenc);
471 //r_bin_free_bin_files (bin);
472 r_list_free (bin->binfiles);
473 r_list_free (bin->binxtrs);
474 r_list_free (bin->plugins);
475 r_list_free (bin->binldrs);
476 sdb_free (bin->sdb);
477 r_id_storage_free (bin->ids);
478 r_str_constpool_fini (&bin->constpool);
479 free (bin);
480 }
481 }
482
r_bin_print_plugin_details(RBin * bin,RBinPlugin * bp,PJ * pj,int json)483 static bool r_bin_print_plugin_details(RBin *bin, RBinPlugin *bp, PJ *pj, int json) {
484 if (json == 'q') {
485 bin->cb_printf ("%s\n", bp->name);
486 } else if (json) {
487 pj_o (pj);
488 pj_ks (pj, "name", bp->name);
489 pj_ks (pj, "description", bp->desc);
490 pj_ks (pj, "license", r_str_get_fail (bp->license, "???"));
491 pj_end (pj);
492 } else {
493 bin->cb_printf ("Name: %s\n", bp->name);
494 bin->cb_printf ("Description: %s\n", bp->desc);
495 if (bp->license) {
496 bin->cb_printf ("License: %s\n", bp->license);
497 }
498 if (bp->version) {
499 bin->cb_printf ("Version: %s\n", bp->version);
500 }
501 if (bp->author) {
502 bin->cb_printf ("Author: %s\n", bp->author);
503 }
504 }
505 return true;
506 }
507
__printXtrPluginDetails(RBin * bin,RBinXtrPlugin * bx,int json)508 static void __printXtrPluginDetails(RBin *bin, RBinXtrPlugin *bx, int json) {
509 if (json == 'q') {
510 bin->cb_printf ("%s\n", bx->name);
511 } else if (json) {
512 PJ *pj = pj_new ();
513 if (!pj) {
514 return;
515 }
516 pj_o (pj);
517 pj_ks (pj, "name", bx->name);
518 pj_ks (pj, "description", bx->desc);
519 pj_ks (pj, "license", r_str_get_fail (bx->license, "???"));
520 pj_end (pj);
521 bin->cb_printf ("%s\n", pj_string (pj));
522 pj_free (pj);
523 } else {
524 bin->cb_printf ("Name: %s\n", bx->name);
525 bin->cb_printf ("Description: %s\n", bx->desc);
526 if (bx->license) {
527 bin->cb_printf ("License: %s\n", bx->license);
528 }
529 }
530 }
531
r_bin_list_plugin(RBin * bin,const char * name,PJ * pj,int json)532 R_API bool r_bin_list_plugin(RBin *bin, const char* name, PJ *pj, int json) {
533 RListIter *it;
534 RBinPlugin *bp;
535 RBinXtrPlugin *bx;
536
537 r_return_val_if_fail (bin && name, false);
538
539 r_list_foreach (bin->plugins, it, bp) {
540 if (!r_str_cmp (name, bp->name, strlen (name))) {
541 continue;
542 }
543 return r_bin_print_plugin_details (bin, bp, pj, json);
544 }
545 r_list_foreach (bin->binxtrs, it, bx) {
546 if (!r_str_cmp (name, bx->name, strlen (name))) {
547 continue;
548 }
549 __printXtrPluginDetails (bin, bx, json);
550 return true;
551 }
552
553 eprintf ("Cannot find plugin %s\n", name);
554 return false;
555 }
556
r_bin_list(RBin * bin,PJ * pj,int format)557 R_API void r_bin_list(RBin *bin, PJ *pj, int format) {
558 RListIter *it;
559 RBinPlugin *bp;
560 RBinXtrPlugin *bx;
561 RBinLdrPlugin *ld;
562
563 if (format == 'q') {
564 r_list_foreach (bin->plugins, it, bp) {
565 bin->cb_printf ("%s\n", bp->name);
566 }
567 r_list_foreach (bin->binxtrs, it, bx) {
568 bin->cb_printf ("%s\n", bx->name);
569 }
570 } else if (format) {
571 pj_o (pj);
572 pj_ka (pj, "bin");
573 r_list_foreach (bin->plugins, it, bp) {
574 pj_o (pj);
575 pj_ks (pj, "name", bp->name);
576 pj_ks (pj, "description", bp->desc);
577 pj_ks (pj, "license", r_str_get_fail (bp->license, "???"));
578 pj_end (pj);
579 }
580 pj_end (pj);
581 pj_ka (pj, "xtr");
582 r_list_foreach (bin->binxtrs, it, bx) {
583 pj_o (pj);
584 pj_ks (pj, "name", bx->name);
585 pj_ks (pj, "description", bx->desc);
586 pj_ks (pj, "license", r_str_get_fail (bx->license, "???"));
587 pj_end (pj);
588 }
589 pj_end (pj);
590 pj_ka (pj, "ldr");
591 r_list_foreach (bin->binxtrs, it, ld) {
592 pj_o (pj);
593 pj_ks (pj, "name", ld->name);
594 pj_ks (pj, "description", ld->desc);
595 pj_ks (pj, "license", r_str_get_fail (ld->license, "???"));
596 pj_end (pj);
597 }
598 pj_end (pj);
599 pj_end (pj);
600 } else {
601 r_list_foreach (bin->plugins, it, bp) {
602 bin->cb_printf ("bin %-11s %s (%s) %s %s\n",
603 bp->name, bp->desc, r_str_get_fail (bp->license, "???"),
604 r_str_get (bp->version),
605 r_str_get (bp->author));
606 }
607 r_list_foreach (bin->binxtrs, it, bx) {
608 const char *name = strncmp (bx->name, "xtr.", 4)? bx->name : bx->name + 3;
609 bin->cb_printf ("xtr %-11s %s (%s)\n", name,
610 bx->desc, r_str_get_fail (bx->license, "???"));
611 }
612 r_list_foreach (bin->binldrs, it, ld) {
613 const char *name = strncmp (ld->name, "ldr.", 4)? ld->name : ld->name + 3;
614 bin->cb_printf ("ldr %-11s %s (%s)\n", name,
615 ld->desc, r_str_get_fail (ld->license, "???"));
616 }
617 }
618 }
619
620 /* returns the base address of bin or UT64_MAX in case of errors */
r_bin_get_baddr(RBin * bin)621 R_API ut64 r_bin_get_baddr(RBin *bin) {
622 r_return_val_if_fail (bin, UT64_MAX);
623 return r_bin_file_get_baddr (bin->cur);
624 }
625
626 /* returns the load address of bin or UT64_MAX in case of errors */
r_bin_get_laddr(RBin * bin)627 R_API ut64 r_bin_get_laddr(RBin *bin) {
628 r_return_val_if_fail (bin, UT64_MAX);
629 RBinObject *o = r_bin_cur_object (bin);
630 return o ? o->loadaddr : UT64_MAX;
631 }
632
633 // TODO: should be RBinFile specific imho
r_bin_set_baddr(RBin * bin,ut64 baddr)634 R_API void r_bin_set_baddr(RBin *bin, ut64 baddr) {
635 r_return_if_fail (bin);
636 RBinFile *bf = r_bin_cur (bin);
637 RBinObject *o = r_bin_cur_object (bin);
638 if (o) {
639 if (!o->plugin || !o->plugin->baddr) {
640 return;
641 }
642 ut64 file_baddr = o->plugin->baddr (bf);
643 if (baddr == UT64_MAX) {
644 o->baddr = file_baddr;
645 o->baddr_shift = 0; // o->baddr; // - file_baddr;
646 } else {
647 if (file_baddr != UT64_MAX) {
648 o->baddr = baddr;
649 o->baddr_shift = baddr - file_baddr;
650 }
651 }
652 } else {
653 eprintf ("Warning: This should be an assert probably.\n");
654 }
655 // XXX - update all the infos?
656 // maybe in RBinFile.rebase() ?
657 }
658
r_bin_get_sym(RBin * bin,int sym)659 R_API RBinAddr *r_bin_get_sym(RBin *bin, int sym) {
660 r_return_val_if_fail (bin, NULL);
661 RBinObject *o = r_bin_cur_object (bin);
662 if (sym < 0 || sym >= R_BIN_SYM_LAST) {
663 return NULL;
664 }
665 return o? o->binsym[sym]: NULL;
666 }
667
668 // XXX: those accessors are redundant
r_bin_get_entries(RBin * bin)669 R_API RList *r_bin_get_entries(RBin *bin) {
670 r_return_val_if_fail (bin, NULL);
671 RBinObject *o = r_bin_cur_object (bin);
672 return o ? o->entries : NULL;
673 }
674
r_bin_get_fields(RBin * bin)675 R_API RList *r_bin_get_fields(RBin *bin) {
676 r_return_val_if_fail (bin, NULL);
677 RBinObject *o = r_bin_cur_object (bin);
678 return o ? o->fields : NULL;
679 }
680
r_bin_get_imports(RBin * bin)681 R_API RList *r_bin_get_imports(RBin *bin) {
682 r_return_val_if_fail (bin, NULL);
683 RBinObject *o = r_bin_cur_object (bin);
684 return o ? o->imports : NULL;
685 }
686
r_bin_get_info(RBin * bin)687 R_API RBinInfo *r_bin_get_info(RBin *bin) {
688 r_return_val_if_fail (bin, NULL);
689 RBinObject *o = r_bin_cur_object (bin);
690 return o ? o->info : NULL;
691 }
692
r_bin_get_libs(RBin * bin)693 R_API RList *r_bin_get_libs(RBin *bin) {
694 r_return_val_if_fail (bin, NULL);
695 RBinObject *o = r_bin_cur_object (bin);
696 return o ? o->libs : NULL;
697 }
698
relocs_rbtree2list(RBNode * root)699 static RList *relocs_rbtree2list(RBNode *root) {
700 RList *res = r_list_new ();
701 RBinReloc *reloc;
702 RBIter it;
703
704 r_rbtree_foreach (root, it, reloc, RBinReloc, vrb) {
705 r_list_append (res, reloc);
706 }
707 return res;
708 }
709
r_bin_patch_relocs(RBin * bin)710 R_API RBNode *r_bin_patch_relocs(RBin *bin) {
711 r_return_val_if_fail (bin, NULL);
712 RBinObject *o = r_bin_cur_object (bin);
713 return o? r_bin_object_patch_relocs (bin, o): NULL;
714 }
715
716 // return a list of <const RBinReloc> that needs to be freed by the caller
r_bin_patch_relocs_list(RBin * bin)717 R_API RList *r_bin_patch_relocs_list(RBin *bin) {
718 r_return_val_if_fail (bin, NULL);
719 RBNode *root = r_bin_patch_relocs (bin);
720 return root? relocs_rbtree2list (root): NULL;
721 }
722
r_bin_get_relocs(RBin * bin)723 R_API RBNode *r_bin_get_relocs(RBin *bin) {
724 r_return_val_if_fail (bin, NULL);
725 RBinObject *o = r_bin_cur_object (bin);
726 return o ? o->relocs : NULL;
727 }
728
729 // return a list of <const RBinReloc> that needs to be freed by the caller
r_bin_get_relocs_list(RBin * bin)730 R_API RList *r_bin_get_relocs_list(RBin *bin) {
731 r_return_val_if_fail (bin, NULL);
732 RBNode *root = r_bin_get_relocs (bin);
733 return root? relocs_rbtree2list (root): NULL;
734 }
735
r_bin_get_sections(RBin * bin)736 R_API RList *r_bin_get_sections(RBin *bin) {
737 r_return_val_if_fail (bin, NULL);
738 RBinObject *o = r_bin_cur_object (bin);
739 return o ? o->sections : NULL;
740 }
741
r_bin_get_section_at(RBinObject * o,ut64 off,int va)742 R_API RBinSection *r_bin_get_section_at(RBinObject *o, ut64 off, int va) {
743 RBinSection *section;
744 RListIter *iter;
745 ut64 from, to;
746
747 r_return_val_if_fail (o, NULL);
748 // TODO: must be O(1) .. use sdb here
749 r_list_foreach (o->sections, iter, section) {
750 if (section->is_segment) {
751 continue;
752 }
753 from = va ? binobj_a2b (o, section->vaddr) : section->paddr;
754 to = from + (va ? section->vsize: section->size);
755 if (off >= from && off < to) {
756 return section;
757 }
758 }
759 return NULL;
760 }
761
r_bin_reset_strings(RBin * bin)762 R_API RList *r_bin_reset_strings(RBin *bin) {
763 RBinFile *bf = r_bin_cur (bin);
764
765 if (!bf || !bf->o) {
766 return NULL;
767 }
768 if (bf->o->strings) {
769 r_list_free (bf->o->strings);
770 bf->o->strings = NULL;
771 }
772
773 bf->rawstr = bin->rawstr;
774 RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
775
776 if (plugin && plugin->strings) {
777 bf->o->strings = plugin->strings (bf);
778 } else {
779 bf->o->strings = r_bin_file_get_strings (bf, bin->minstrlen, 0, bf->rawstr);
780 }
781 if (bin->debase64) {
782 r_bin_object_filter_strings (bf->o);
783 }
784 return bf->o->strings;
785 }
786
r_bin_get_strings(RBin * bin)787 R_API RList *r_bin_get_strings(RBin *bin) {
788 r_return_val_if_fail (bin, NULL);
789 RBinObject *o = r_bin_cur_object (bin);
790 return o ? o->strings : NULL;
791 }
792
r_bin_is_string(RBin * bin,ut64 va)793 R_API int r_bin_is_string(RBin *bin, ut64 va) {
794 RBinString *string;
795 RListIter *iter;
796 RList *list;
797 if (!(list = r_bin_get_strings (bin))) {
798 return false;
799 }
800 r_list_foreach (list, iter, string) {
801 if (string->vaddr == va) {
802 return true;
803 }
804 if (string->vaddr > va) {
805 return false;
806 }
807 }
808 return false;
809 }
810
r_bin_get_symbols(RBin * bin)811 R_API RList *r_bin_get_symbols(RBin *bin) {
812 r_return_val_if_fail (bin, NULL);
813 RBinObject *o = r_bin_cur_object (bin);
814 return o? o->symbols: NULL;
815 }
816
r_bin_get_mem(RBin * bin)817 R_API RList *r_bin_get_mem(RBin *bin) {
818 r_return_val_if_fail (bin, NULL);
819 RBinObject *o = r_bin_cur_object (bin);
820 return o ? o->mem : NULL;
821 }
822
r_bin_is_big_endian(RBin * bin)823 R_API int r_bin_is_big_endian(RBin *bin) {
824 r_return_val_if_fail (bin, -1);
825 RBinObject *o = r_bin_cur_object (bin);
826 return (o && o->info) ? o->info->big_endian : -1;
827 }
828
r_bin_is_static(RBin * bin)829 R_API int r_bin_is_static(RBin *bin) {
830 r_return_val_if_fail (bin, false);
831 RBinObject *o = r_bin_cur_object (bin);
832 if (o && o->libs && r_list_length (o->libs) > 0) {
833 return R_BIN_DBG_STATIC & o->info->dbg_info;
834 }
835 return true;
836 }
837
r_bin_new(void)838 R_API RBin *r_bin_new(void) {
839 int i;
840 RBinXtrPlugin *static_xtr_plugin;
841 RBinLdrPlugin *static_ldr_plugin;
842 RBin *bin = R_NEW0 (RBin);
843 if (!bin) {
844 return NULL;
845 }
846 if (!r_str_constpool_init (&bin->constpool)) {
847 goto trashbin;
848 }
849 bin->force = NULL;
850 bin->filter_rules = UT64_MAX;
851 bin->sdb = sdb_new0 ();
852 bin->cb_printf = (PrintfCallback)printf;
853 bin->plugins = r_list_newf ((RListFree)r_bin_plugin_free);
854 bin->minstrlen = 0;
855 bin->strpurge = NULL;
856 bin->strenc = NULL;
857 bin->want_dbginfo = true;
858 bin->cur = NULL;
859 bin->ids = r_id_storage_new (0, ST32_MAX);
860
861 /* bin parsers */
862 bin->binfiles = r_list_newf ((RListFree)r_bin_file_free);
863 for (i = 0; bin_static_plugins[i]; i++) {
864 r_bin_add (bin, bin_static_plugins[i]);
865 }
866 /* extractors */
867 bin->binxtrs = r_list_new ();
868 bin->binxtrs->free = free;
869 for (i = 0; bin_xtr_static_plugins[i]; i++) {
870 static_xtr_plugin = R_NEW0 (RBinXtrPlugin);
871 if (!static_xtr_plugin) {
872 goto trashbin_binxtrs;
873 }
874 *static_xtr_plugin = *bin_xtr_static_plugins[i];
875 r_bin_xtr_add (bin, static_xtr_plugin);
876 }
877 /* loaders */
878 bin->binldrs = r_list_new ();
879 bin->binldrs->free = free;
880 for (i = 0; bin_ldr_static_plugins[i]; i++) {
881 static_ldr_plugin = R_NEW0 (RBinLdrPlugin);
882 if (!static_ldr_plugin) {
883 goto trashbin_binldrs;
884 }
885 *static_ldr_plugin = *bin_ldr_static_plugins[i];
886 r_bin_ldr_add (bin, static_ldr_plugin);
887 }
888 return bin;
889 trashbin_binldrs:
890 r_list_free (bin->binldrs);
891 trashbin_binxtrs:
892 r_list_free (bin->binxtrs);
893 r_list_free (bin->binfiles);
894 r_id_storage_free (bin->ids);
895 r_str_constpool_fini (&bin->constpool);
896 trashbin:
897 free (bin);
898 return NULL;
899 }
900
r_bin_use_arch(RBin * bin,const char * arch,int bits,const char * name)901 R_API bool r_bin_use_arch(RBin *bin, const char *arch, int bits, const char *name) {
902 r_return_val_if_fail (bin && arch, false);
903
904 RBinFile *binfile = r_bin_file_find_by_arch_bits (bin, arch, bits);
905 if (!binfile) {
906 R_LOG_WARN ("Cannot find binfile with arch/bits %s/%d\n", arch, bits);
907 return false;
908 }
909
910 RBinObject *obj = r_bin_object_find_by_arch_bits (binfile, arch, bits, name);
911 if (!obj && binfile->xtr_data) {
912 RBinXtrData *xtr_data = r_list_get_n (binfile->xtr_data, 0);
913 if (xtr_data && !xtr_data->loaded) {
914 if (!r_bin_file_object_new_from_xtr_data (bin, binfile,
915 UT64_MAX, r_bin_get_laddr (bin), xtr_data)) {
916 return false;
917 }
918 }
919 obj = binfile->o;
920 }
921 return r_bin_file_set_obj (bin, binfile, obj);
922 }
923
r_bin_select(RBin * bin,const char * arch,int bits,const char * name)924 R_API bool r_bin_select(RBin *bin, const char *arch, int bits, const char *name) {
925 r_return_val_if_fail (bin, false);
926
927 RBinFile *cur = r_bin_cur (bin);
928 RBinObject *obj = NULL;
929 name = !name && cur? cur->file: name;
930 RBinFile *binfile = r_bin_file_find_by_arch_bits (bin, arch, bits);
931 if (binfile && name) {
932 obj = r_bin_object_find_by_arch_bits (binfile, arch, bits, name);
933 }
934 return r_bin_file_set_obj (bin, binfile, obj);
935 }
936
r_bin_select_object(RBinFile * binfile,const char * arch,int bits,const char * name)937 R_API int r_bin_select_object(RBinFile *binfile, const char *arch, int bits, const char *name) {
938 r_return_val_if_fail (binfile, false);
939 RBinObject *obj = r_bin_object_find_by_arch_bits (binfile, arch, bits, name);
940 return r_bin_file_set_obj (binfile->rbin, binfile, obj);
941 }
942
943 // NOTE: this functiona works as expected, but we need to merge bfid and boid
r_bin_select_bfid(RBin * bin,ut32 bf_id)944 R_API bool r_bin_select_bfid (RBin *bin, ut32 bf_id) {
945 r_return_val_if_fail (bin, false);
946 RBinFile *bf = r_bin_file_find_by_id (bin, bf_id);
947 return bf? r_bin_file_set_obj (bin, bf, NULL): false;
948 }
949
list_xtr_archs(RBin * bin,PJ * pj,int mode)950 static void list_xtr_archs(RBin *bin, PJ *pj, int mode) {
951 RBinFile *binfile = r_bin_cur (bin);
952 if (binfile->xtr_data) {
953 RListIter *iter_xtr;
954 RBinXtrData *xtr_data;
955 int bits, i = 0;
956 char *arch, *machine;
957
958 if (mode == 'j') {
959 pj_ka (pj, "bins");
960 }
961
962 r_list_foreach (binfile->xtr_data, iter_xtr, xtr_data) {
963 if (!xtr_data || !xtr_data->metadata ||
964 !xtr_data->metadata->arch) {
965 continue;
966 }
967 arch = xtr_data->metadata->arch;
968 machine = xtr_data->metadata->machine;
969 bits = xtr_data->metadata->bits;
970 switch (mode) {
971 case 'q': // "iAq"
972 bin->cb_printf ("%s\n", arch);
973 break;
974 case 'j': { // "iAj"
975 pj_o (pj);
976 pj_ks (pj, "arch", arch);
977 pj_ki (pj, "bits", bits);
978 pj_kN (pj, "offset", xtr_data->offset);
979 pj_kN (pj, "size", xtr_data->size);
980 pj_ks (pj, "machine", machine);
981 pj_end (pj);
982 break;
983 }
984 default:
985 bin->cb_printf ("%03i 0x%08" PFMT64x
986 " %" PFMT64d " %s_%i %s\n",
987 i++, xtr_data->offset,
988 xtr_data->size, arch, bits,
989 machine);
990 break;
991 }
992 }
993
994 if (mode == 'j') {
995 pj_end (pj);
996 }
997 }
998 }
999
r_bin_list_archs(RBin * bin,PJ * pj,int mode)1000 R_API void r_bin_list_archs(RBin *bin, PJ *pj, int mode) {
1001 r_return_if_fail (bin);
1002
1003 char unk[128];
1004 char archline[256];
1005 RBinFile *binfile = r_bin_cur (bin);
1006 const char *name = binfile? binfile->file: NULL;
1007 int narch = binfile? binfile->narch: 0;
1008
1009 //are we with xtr format?
1010 if (binfile && binfile->curxtr) {
1011 list_xtr_archs (bin, pj, mode);
1012 return;
1013 }
1014 Sdb *binfile_sdb = binfile? binfile->sdb: NULL;
1015 if (!binfile_sdb) {
1016 // eprintf ("Cannot find SDB!\n");
1017 return;
1018 }
1019 if (!binfile) {
1020 // eprintf ("Binary format not currently loaded!\n");
1021 return;
1022 }
1023 sdb_unset (binfile_sdb, ARCHS_KEY, 0);
1024 RBinFile *nbinfile = r_bin_file_find_by_name (bin, name);
1025 if (!nbinfile) {
1026 return;
1027 }
1028 RTable *table = r_table_new ("bins");
1029 const char *fmt = "dXnss";
1030 if (mode == 'j') {
1031 pj_ka (pj, "bins");
1032 }
1033 RBinObject *obj = nbinfile->o;
1034 RBinInfo *info = obj->info;
1035 char bits = info? info->bits: 0;
1036 ut64 boffset = obj->boffset;
1037 ut64 obj_size = obj->obj_size;
1038 const char *arch = info? info->arch: NULL;
1039 const char *machine = info? info->machine: "unknown_machine";
1040 const char *h_flag = info? info->head_flag: NULL;
1041 char * str_fmt;
1042 if (!arch) {
1043 snprintf (unk, sizeof (unk), "unk_0");
1044 arch = unk;
1045 }
1046 r_table_hide_header (table);
1047 r_table_set_columnsf (table, fmt, "num", "offset", "size", "arch", "machine", NULL);
1048
1049 if (info && narch > 1) {
1050 switch (mode) {
1051 case 'q':
1052 bin->cb_printf ("%s\n", arch);
1053 break;
1054 case 'j':
1055 pj_o (pj);
1056 pj_ks (pj, "arch", arch);
1057 pj_ki (pj, "bits", bits);
1058 pj_kn (pj, "offset", boffset);
1059 pj_kn (pj, "size", obj_size);
1060 if (!strcmp (arch, "mips")) {
1061 pj_ks (pj, "isa", info->cpu);
1062 pj_ks (pj, "features", info->features);
1063 }
1064 if (machine) {
1065 pj_ks (pj, "machine", machine);
1066 }
1067 pj_end (pj);
1068 break;
1069 default:
1070 str_fmt = h_flag && strcmp (h_flag, "unknown_flag")? sdb_fmt ("%s_%i %s", arch, bits, h_flag) \
1071 : sdb_fmt ("%s_%i", arch, bits);
1072 r_table_add_rowf (table, fmt, 0, boffset, obj_size, str_fmt, machine);
1073 bin->cb_printf ("%s", r_table_tostring (table));
1074 }
1075 snprintf (archline, sizeof (archline) - 1,
1076 "0x%08" PFMT64x ":%" PFMT64u ":%s:%d:%s",
1077 boffset, obj_size, arch, bits, machine);
1078 /// xxx machine not exported?
1079 //sdb_array_push (binfile_sdb, ARCHS_KEY, archline, 0);
1080 } else {
1081 if (info) {
1082 switch (mode) {
1083 case 'q':
1084 bin->cb_printf ("%s\n", arch);
1085 break;
1086 case 'j':
1087 pj_o (pj);
1088 pj_ks (pj, "arch", arch);
1089 pj_ki (pj, "bits", bits);
1090 pj_kn (pj, "offset", boffset);
1091 pj_kn (pj, "size", obj_size);
1092 if (!strcmp (arch, "mips")) {
1093 pj_ks (pj, "isa", info->cpu);
1094 pj_ks (pj, "features", info->features);
1095 }
1096 if (machine) {
1097 pj_ks (pj, "machine", machine);
1098 }
1099 pj_end (pj);
1100 break;
1101 default:
1102 str_fmt = h_flag && strcmp (h_flag, "unknown_flag")? sdb_fmt ("%s_%i %s", arch, bits, h_flag) \
1103 : sdb_fmt ("%s_%i", arch, bits);
1104 r_table_add_rowf (table, fmt, 0, boffset, obj_size, str_fmt, "");
1105 bin->cb_printf ("%s", r_table_tostring (table));
1106 }
1107 snprintf (archline, sizeof (archline),
1108 "0x%08" PFMT64x ":%" PFMT64u ":%s:%d",
1109 boffset, obj_size, arch, bits);
1110 } else if (nbinfile && mode) {
1111 switch (mode) {
1112 case 'q':
1113 bin->cb_printf ("%s\n", arch);
1114 break;
1115 case 'j':
1116 pj_o (pj);
1117 pj_ks (pj, "arch", arch);
1118 pj_ki (pj, "bits", bits);
1119 pj_kn (pj, "offset", boffset);
1120 pj_kn (pj, "size", obj_size);
1121 if (machine) {
1122 pj_ks (pj, "machine", machine);
1123 }
1124 pj_end (pj);
1125 break;
1126 default:
1127 r_table_add_rowf (table, fmt, 0, boffset, obj_size, "", "");
1128 bin->cb_printf ("%s", r_table_tostring (table));
1129 }
1130 snprintf (archline, sizeof (archline),
1131 "0x%08" PFMT64x ":%" PFMT64u ":%s:%d",
1132 boffset, obj_size, "unk", 0);
1133 } else {
1134 eprintf ("Error: Invalid RBinFile.\n");
1135 }
1136 //sdb_array_push (binfile_sdb, ARCHS_KEY, archline, 0);
1137 }
1138 if (mode == 'j') {
1139 pj_end (pj);
1140 }
1141 r_table_free (table);
1142 }
1143
r_bin_set_user_ptr(RBin * bin,void * user)1144 R_API void r_bin_set_user_ptr(RBin *bin, void *user) {
1145 bin->user = user;
1146 }
1147
__get_vsection_at(RBin * bin,ut64 vaddr)1148 static RBinSection* __get_vsection_at(RBin *bin, ut64 vaddr) {
1149 r_return_val_if_fail (bin, NULL);
1150 if (!bin->cur) {
1151 return NULL;
1152 }
1153 return r_bin_get_section_at (bin->cur->o, vaddr, true);
1154 }
1155
r_bin_bind(RBin * bin,RBinBind * b)1156 R_API void r_bin_bind(RBin *bin, RBinBind *b) {
1157 if (b) {
1158 b->bin = bin;
1159 b->get_offset = __getoffset;
1160 b->get_name = __getname;
1161 b->get_sections = r_bin_get_sections;
1162 b->get_vsect_at = __get_vsection_at;
1163 b->demangle = r_bin_demangle;
1164 }
1165 }
1166
r_bin_create(RBin * bin,const char * p,const ut8 * code,int codelen,const ut8 * data,int datalen,RBinArchOptions * opt)1167 R_API RBuffer *r_bin_create(RBin *bin, const char *p,
1168 const ut8 *code, int codelen,
1169 const ut8 *data, int datalen,
1170 RBinArchOptions *opt) {
1171
1172 r_return_val_if_fail (bin && p && opt, NULL);
1173
1174 RBinPlugin *plugin = r_bin_get_binplugin_by_name (bin, p);
1175 if (!plugin) {
1176 R_LOG_WARN ("Cannot find RBin plugin named '%s'.\n", p);
1177 return NULL;
1178 }
1179 if (!plugin->create) {
1180 R_LOG_WARN ("RBin plugin '%s' does not implement \"create\" method.\n", p);
1181 return NULL;
1182 }
1183 codelen = R_MAX (codelen, 0);
1184 datalen = R_MAX (datalen, 0);
1185 return plugin->create (bin, code, codelen, data, datalen, opt);
1186 }
1187
r_bin_package(RBin * bin,const char * type,const char * file,RList * files)1188 R_API RBuffer *r_bin_package(RBin *bin, const char *type, const char *file, RList *files) {
1189 if (!strcmp (type, "zip")) {
1190 // XXX: implement me
1191 r_warn_if_reached ();
1192 } else if (!strcmp (type, "fat")) {
1193 // XXX: this should be implemented in the fat plugin, not here
1194 // XXX should pick the callback from the plugin list
1195 const char *f;
1196 RListIter *iter;
1197 ut32 num;
1198 ut8 *num8 = (ut8*)#
1199 RBuffer *buf = r_buf_new_file (file, O_RDWR | O_CREAT, 0644);
1200 if (!buf) {
1201 eprintf ("Cannot open file %s - Permission Denied.\n", file);
1202 return NULL;
1203 }
1204 r_buf_write_at (buf, 0, (const ut8*)"\xca\xfe\xba\xbe", 4);
1205 int count = r_list_length (files);
1206
1207 num = r_read_be32 (&count);
1208 ut64 from = 0x1000;
1209 r_buf_write_at (buf, 4, num8, 4);
1210 int off = 12;
1211 int item = 0;
1212 r_list_foreach (files, iter, f) {
1213 size_t f_len = 0;
1214 ut8 *f_buf = (ut8 *)r_file_slurp (f, &f_len);
1215 if (f_buf) {
1216 eprintf ("ADD %s %"PFMT64u"\n", f, (ut64)f_len);
1217 } else {
1218 eprintf ("Cannot open %s\n", f);
1219 free (f_buf);
1220 continue;
1221 }
1222 item++;
1223 /* CPU */
1224 num8[0] = f_buf[7];
1225 num8[1] = f_buf[6];
1226 num8[2] = f_buf[5];
1227 num8[3] = f_buf[4];
1228 r_buf_write_at (buf, off - 4, num8, 4);
1229 /* SUBTYPE */
1230 num8[0] = f_buf[11];
1231 num8[1] = f_buf[10];
1232 num8[2] = f_buf[9];
1233 num8[3] = f_buf[8];
1234 r_buf_write_at (buf, off, num8, 4);
1235 ut32 from32 = from;
1236 /* FROM */
1237 num = r_read_be32 (&from32);
1238 r_buf_write_at (buf, off + 4, num8, 4);
1239 r_buf_write_at (buf, from, f_buf, f_len);
1240 /* SIZE */
1241 num = r_read_be32 (&f_len);
1242 r_buf_write_at (buf, off + 8, num8, 4);
1243 off += 20;
1244 from += f_len + (f_len % 0x1000);
1245 free (f_buf);
1246 }
1247 r_buf_free (buf);
1248 return NULL;
1249 } else {
1250 eprintf ("Usage: rabin2 -X [fat|zip] [filename] [files ...]\n");
1251 }
1252 return NULL;
1253 }
1254
r_bin_get_classes(RBin * bin)1255 R_API RList * /*<RBinClass>*/ r_bin_get_classes(RBin *bin) {
1256 r_return_val_if_fail (bin, NULL);
1257 RBinObject *o = r_bin_cur_object (bin);
1258 return o ? o->classes : NULL;
1259 }
1260
1261 /* returns vaddr, rebased with the baseaddr of bin, if va is enabled for bin,
1262 * paddr otherwise */
r_bin_get_vaddr(RBin * bin,ut64 paddr,ut64 vaddr)1263 R_API ut64 r_bin_get_vaddr(RBin *bin, ut64 paddr, ut64 vaddr) {
1264 r_return_val_if_fail (bin && paddr != UT64_MAX, UT64_MAX);
1265
1266 if (!bin->cur) {
1267 return paddr;
1268 }
1269 /* hack to realign thumb symbols */
1270 if (bin->cur->o && bin->cur->o->info && bin->cur->o->info->arch) {
1271 if (bin->cur->o->info->bits == 16) {
1272 RBinSection *s = r_bin_get_section_at (bin->cur->o, paddr, false);
1273 // autodetect thumb
1274 if (s && (s->perm & R_PERM_X) && strstr (s->name, "text")) {
1275 if (!strcmp (bin->cur->o->info->arch, "arm") && (vaddr & 1)) {
1276 vaddr = (vaddr >> 1) << 1;
1277 }
1278 }
1279 }
1280 }
1281 return r_bin_file_get_vaddr (bin->cur, paddr, vaddr);
1282 }
1283
r_bin_a2b(RBin * bin,ut64 addr)1284 R_API ut64 r_bin_a2b(RBin *bin, ut64 addr) {
1285 r_return_val_if_fail (bin, UT64_MAX);
1286 RBinObject *o = r_bin_cur_object (bin);
1287 return binobj_a2b (o, addr);
1288 }
1289
r_bin_get_size(RBin * bin)1290 R_API ut64 r_bin_get_size(RBin *bin) {
1291 r_return_val_if_fail (bin, UT64_MAX);
1292 RBinObject *o = r_bin_cur_object (bin);
1293 return o ? o->size : 0;
1294 }
1295
r_bin_cur(RBin * bin)1296 R_API RBinFile *r_bin_cur(RBin *bin) {
1297 r_return_val_if_fail (bin, NULL);
1298 return bin->cur;
1299 }
1300
r_bin_cur_object(RBin * bin)1301 R_API RBinObject *r_bin_cur_object(RBin *bin) {
1302 r_return_val_if_fail (bin, NULL);
1303 RBinFile *binfile = r_bin_cur (bin);
1304 return binfile ? binfile->o : NULL;
1305 }
1306
r_bin_force_plugin(RBin * bin,const char * name)1307 R_API void r_bin_force_plugin(RBin *bin, const char *name) {
1308 r_return_if_fail (bin);
1309 free (bin->force);
1310 bin->force = (name && *name) ? strdup (name) : NULL;
1311 }
1312
r_bin_entry_type_string(int etype)1313 R_API const char *r_bin_entry_type_string(int etype) {
1314 switch (etype) {
1315 case R_BIN_ENTRY_TYPE_PROGRAM:
1316 return "program";
1317 case R_BIN_ENTRY_TYPE_MAIN:
1318 return "main";
1319 case R_BIN_ENTRY_TYPE_INIT:
1320 return "init";
1321 case R_BIN_ENTRY_TYPE_FINI:
1322 return "fini";
1323 case R_BIN_ENTRY_TYPE_TLS:
1324 return "tls";
1325 case R_BIN_ENTRY_TYPE_PREINIT:
1326 return "preinit";
1327 }
1328 return NULL;
1329 }
1330
r_bin_load_filter(RBin * bin,ut64 rules)1331 R_API void r_bin_load_filter(RBin *bin, ut64 rules) {
1332 bin->filter_rules = rules;
1333 }
1334
1335 /* RBinField */
r_bin_field_new(ut64 paddr,ut64 vaddr,int size,const char * name,const char * comment,const char * format,bool format_named)1336 R_API RBinField *r_bin_field_new(ut64 paddr, ut64 vaddr, int size, const char *name, const char *comment, const char *format, bool format_named) {
1337 RBinField *ptr = R_NEW0 (RBinField);
1338 if (ptr) {
1339 ptr->name = strdup (name);
1340 ptr->comment = (comment && *comment)? strdup (comment): NULL;
1341 ptr->format = (format && *format)? strdup (format): NULL;
1342 ptr->format_named = format_named;
1343 ptr->paddr = paddr;
1344 ptr->size = size;
1345 // ptr->visibility = any default visibility?
1346 ptr->vaddr = vaddr;
1347 }
1348 return ptr;
1349 }
1350
1351 // use void* to honor the RListFree signature
r_bin_field_free(void * _field)1352 R_API void r_bin_field_free(void *_field) {
1353 RBinField *field = (RBinField*) _field;
1354 if (field) {
1355 free (field->name);
1356 free (field->comment);
1357 free (field->format);
1358 free (field);
1359 }
1360 }
1361
1362 // method name too long
1363 // RBin.methFlagToString(RBin.Method.CLASS)
r_bin_get_meth_flag_string(ut64 flag,bool compact)1364 R_API const char *r_bin_get_meth_flag_string(ut64 flag, bool compact) {
1365 switch (flag) {
1366 case R_BIN_METH_CLASS:
1367 return compact ? "c" : "class";
1368 case R_BIN_METH_STATIC:
1369 return compact ? "s" : "static";
1370 case R_BIN_METH_PUBLIC:
1371 return compact ? "p" : "public";
1372 case R_BIN_METH_PRIVATE:
1373 return compact ? "P" : "private";
1374 case R_BIN_METH_PROTECTED:
1375 return compact ? "r" : "protected";
1376 case R_BIN_METH_INTERNAL:
1377 return compact ? "i" : "internal";
1378 case R_BIN_METH_OPEN:
1379 return compact ? "o" : "open";
1380 case R_BIN_METH_FILEPRIVATE:
1381 return compact ? "e" : "fileprivate";
1382 case R_BIN_METH_FINAL:
1383 return compact ? "f" : "final";
1384 case R_BIN_METH_VIRTUAL:
1385 return compact ? "v" : "virtual";
1386 case R_BIN_METH_CONST:
1387 return compact ? "k" : "const";
1388 case R_BIN_METH_MUTATING:
1389 return compact ? "m" : "mutating";
1390 case R_BIN_METH_ABSTRACT:
1391 return compact ? "a" : "abstract";
1392 case R_BIN_METH_SYNCHRONIZED:
1393 return compact ? "y" : "synchronized";
1394 case R_BIN_METH_NATIVE:
1395 return compact ? "n" : "native";
1396 case R_BIN_METH_BRIDGE:
1397 return compact ? "b" : "bridge";
1398 case R_BIN_METH_VARARGS:
1399 return compact ? "g" : "varargs";
1400 case R_BIN_METH_SYNTHETIC:
1401 return compact ? "h" : "synthetic";
1402 case R_BIN_METH_STRICT:
1403 return compact ? "t" : "strict";
1404 case R_BIN_METH_MIRANDA:
1405 return compact ? "A" : "miranda";
1406 case R_BIN_METH_CONSTRUCTOR:
1407 return compact ? "C" : "constructor";
1408 case R_BIN_METH_DECLARED_SYNCHRONIZED:
1409 return compact ? "Y" : "declared_synchronized";
1410 default:
1411 return NULL;
1412 }
1413 }
1414
r_bin_section_new(const char * name)1415 R_IPI RBinSection *r_bin_section_new(const char *name) {
1416 RBinSection *s = R_NEW0 (RBinSection);
1417 if (s) {
1418 s->name = name? strdup (name): NULL;
1419 }
1420 return s;
1421 }
1422
r_bin_section_free(RBinSection * bs)1423 R_IPI void r_bin_section_free(RBinSection *bs) {
1424 if (bs) {
1425 free (bs->name);
1426 free (bs->format);
1427 free (bs);
1428 }
1429 }
1430
r_bin_file_at(RBin * bin,ut64 at)1431 R_API RBinFile *r_bin_file_at(RBin *bin, ut64 at) {
1432 RListIter *it, *it2;
1433 RBinFile *bf;
1434 RBinSection *s;
1435 r_list_foreach (bin->binfiles, it, bf) {
1436 // chk for baddr + size of no section is covering anything
1437 // we should honor maps not sections imho
1438 r_list_foreach (bf->o->sections, it2, s) {
1439 if (at >= s->vaddr && at < (s->vaddr + s->vsize)) {
1440 return bf;
1441 }
1442 }
1443 if (at >= bf->o->baddr && at < (bf->o->baddr + bf->size)) {
1444 return bf;
1445 }
1446 }
1447 return NULL;
1448 }
1449
r_bin_trycatch_new(ut64 source,ut64 from,ut64 to,ut64 handler,ut64 filter)1450 R_API RBinTrycatch *r_bin_trycatch_new(ut64 source, ut64 from, ut64 to, ut64 handler, ut64 filter) {
1451 RBinTrycatch *tc = R_NEW0 (RBinTrycatch);
1452 if (tc) {
1453 tc->source = source;
1454 tc->from = from;
1455 tc->to = to;
1456 tc->handler = handler;
1457 tc->filter = filter;
1458 }
1459 return tc;
1460 }
1461
r_bin_trycatch_free(RBinTrycatch * tc)1462 R_API void r_bin_trycatch_free(RBinTrycatch *tc) {
1463 free (tc);
1464 }
1465