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*)&num;
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