1 /* radare - LGPL - Copyright 2009-2021 - pancake */
2 
3 #include <r_core.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #define UPDATE_TIME(a) (r->times->file_open_time = r_time_now_mono () - (a))
8 
9 static int r_core_file_do_load_for_debug(RCore *r, ut64 loadaddr, const char *filenameuri);
10 static int r_core_file_do_load_for_io_plugin(RCore *r, ut64 baseaddr, ut64 loadaddr);
11 
close_but_cb(void * user,void * data,ut32 id)12 static bool close_but_cb(void *user, void *data, ut32 id) {
13        RCore *core = (RCore *)user;
14        RIODesc *desc = (RIODesc *)data;
15        if (core && desc && core->io->desc) {
16                if (desc->fd != core->io->desc->fd) {
17                        // TODO: use the API
18                        r_core_cmdf (core, "o-%d", desc->fd);
19                }
20        }
21        return true;
22 }
23 
24 // TODO: move to IO as a helper?
r_core_file_close_all_but(RCore * core)25 R_API bool r_core_file_close_all_but(RCore *core) {
26        r_id_storage_foreach (core->io->files, close_but_cb, core);
27        return true;
28 }
29 
__isMips(RAsm * a)30 static bool __isMips (RAsm *a) {
31 	return a && a->cur && a->cur->arch && strstr (a->cur->arch, "mips");
32 }
33 
loadGP(RCore * core)34 static void loadGP(RCore *core) {
35 	if (__isMips (core->rasm)) {
36 		ut64 gp = r_num_math (core->num, "loc._gp");
37 		if (!gp || gp == UT64_MAX) {
38 			r_config_set (core->config, "anal.roregs", "zero");
39 			r_core_cmd0 (core, "10aes@entry0");
40 			r_config_set (core->config, "anal.roregs", "zero,gp");
41 			gp = r_reg_getv (core->anal->reg, "gp");
42 		}
43 		// eprintf ("[mips] gp: 0x%08"PFMT64x"\n", gp);
44 		r_config_set_i (core->config, "anal.gp", gp);
45 	}
46 }
47 
r_core_file_reopen(RCore * core,const char * args,int perm,int loadbin)48 R_API bool r_core_file_reopen(RCore *core, const char *args, int perm, int loadbin) {
49 	int isdebug = r_config_get_i (core->config, "cfg.debug");
50 	char *path;
51 	ut64 laddr = r_config_get_i (core->config, "bin.laddr");
52 	RIODesc *file = NULL;
53 	RIODesc *odesc = core->io ? core->io->desc : NULL;
54 	RBinFile *bf = odesc ? r_bin_file_find_by_fd (core->bin, odesc->fd) : NULL;
55 	char *ofilepath = NULL, *obinfilepath = (bf && bf->file)? strdup (bf->file): NULL;
56 	bool ret = false;
57 	ut64 origoff = core->offset;
58 	if (odesc) {
59 		if (odesc->referer) {
60 			ofilepath = odesc->referer;
61 		} else if (odesc->uri) {
62 			ofilepath = odesc->uri;
63 		}
64 	}
65 
66 	ut64 new_baddr = UT64_MAX;
67 	if (args) {
68 		new_baddr = r_num_math (core->num, args);
69 		if (new_baddr && new_baddr != UT64_MAX) {
70 			r_config_set_i (core->config, "bin.baddr", new_baddr);
71 		} else {
72 			new_baddr = UT64_MAX;
73 		}
74 	}
75 	if (new_baddr == UT64_MAX) {
76 		new_baddr = r_config_get_i (core->config, "bin.baddr");
77 	}
78 
79 	if (r_sandbox_enable (0)) {
80 		eprintf ("Cannot reopen in sandbox\n");
81 		free (obinfilepath);
82 		return false;
83 	}
84 	if (!odesc) {
85 		eprintf ("No file opened to reopen\n");
86 		free (ofilepath);
87 		free (obinfilepath);
88 		return false;
89 	}
90 	int newpid = odesc->fd;
91 
92 	if (isdebug) {
93 		r_debug_kill (core->dbg, core->dbg->pid, core->dbg->tid, 9); // SIGKILL
94 		do {
95 			r_debug_continue (core->dbg);
96 		} while (!r_debug_is_dead (core->dbg));
97 		r_debug_detach (core->dbg, core->dbg->pid);
98 		perm = 7;
99 	} else {
100 		if (!perm) {
101 			perm = 4; //R_PERM_R;
102 		}
103 	}
104 	if (!ofilepath) {
105 		eprintf ("Unknown file path");
106 		free (obinfilepath);
107 		return false;
108 	}
109 
110 	// HACK: move last mapped address to higher place
111 	// XXX - why does this hack work?
112 	// when the new memory maps are created.
113 	path = strdup (ofilepath);
114 	free (obinfilepath);
115 	obinfilepath = strdup (ofilepath);
116 
117 	// r_str_trim (path);
118 	file = r_core_file_open (core, path, perm, laddr);
119 	if (isdebug) {
120 		int newtid = newpid;
121 		// XXX - select the right backend
122 		if (core->io->desc) {
123 			newpid = r_io_fd_get_pid (core->io, core->io->desc->fd);
124 #if __linux__
125 			core->dbg->main_pid = newpid;
126 			newtid = newpid;
127 #else
128 			newtid = r_io_fd_get_tid (core->io, core->io->desc->fd);
129 #endif
130 		}
131 		// Reset previous pid and tid
132 		core->dbg->pid = -1;
133 		core->dbg->tid = -1;
134 		core->dbg->recoil_mode = R_DBG_RECOIL_NONE;
135 		memset (&core->dbg->reason, 0, sizeof (core->dbg->reason));
136 		// Reopen and attach
137 		r_core_setup_debugger (core, "native", true);
138 		r_debug_select (core->dbg, newpid, newtid);
139 	}
140 
141 	if (file) {
142 		bool had_rbin_info = false;
143 
144 		if (odesc && bf) {
145 			if (r_bin_file_delete (core->bin, bf->id)) {
146 				had_rbin_info = true;
147 			}
148 		}
149 		r_io_fd_close (core->io, odesc->fd);
150 		eprintf ("File %s reopened in %s mode\n", path,
151 			(perm & R_PERM_W)? "read-write": "read-only");
152 
153 		if (loadbin && (loadbin == 2 || had_rbin_info)) {
154 			ut64 baddr;
155 			if (isdebug) {
156 				baddr = r_debug_get_baddr (core->dbg, path);
157 			} else if (new_baddr != UT64_MAX) {
158 				baddr = new_baddr;
159 			} else {
160 				baddr = r_config_get_i (core->config, "bin.baddr");
161 			}
162 			ret = r_core_bin_load (core, obinfilepath, baddr);
163 			r_core_bin_update_arch_bits (core);
164 			if (!ret) {
165 				eprintf ("Error: Failed to reload rbin for: %s", path);
166 			}
167 			origoff = r_num_math (core->num, "entry0");
168 		}
169 
170 		if (core->bin->cur && core->io && r_io_desc_get (core->io, file->fd) && !loadbin) {
171 			//force here NULL because is causing uaf look this better in future XXX @alvarofe
172 			core->bin->cur = NULL;
173 		}
174 		// close old file
175 	} else if (odesc) {
176 		eprintf ("r_core_file_reopen: Cannot reopen file: %s with perms 0x%x,"
177 			" attempting to open read-only.\n", path, perm);
178 		// lower it down back
179 		//ofile = r_core_file_open (core, path, R_PERM_R, addr);
180 	} else {
181 		eprintf ("Cannot reopen\n");
182 	}
183 	if (core->io->desc) {
184 		core->switch_file_view = 1;
185 		r_core_block_read (core);
186 	}
187 	r_core_seek (core, origoff, true);
188 	if (isdebug) {
189 		r_core_cmd0 (core, ".dm*");
190 		r_core_cmd0 (core, ".dr*");
191 		r_core_cmd0 (core, "sr PC");
192 	} else {
193 		loadGP (core);
194 	}
195 	// update anal io bind
196 	r_io_bind (core->io, &(core->anal->iob));
197 	if (core->io->desc && core->io->desc->fd >= 0) {
198 		r_core_cmd0 (core, "o-!");
199 	}
200 	r_core_file_close_all_but (core);
201 	// This is done to ensure that the file is correctly
202 	// loaded into the view
203 	free (obinfilepath);
204 	//free (ofilepath);
205 	// causes double free . dont free file here // R_FREE (file);
206 	free (path);
207 	return ret;
208 }
209 
r_core_sysenv_end(RCore * core,const char * cmd)210 R_API void r_core_sysenv_end(RCore *core, const char *cmd) {
211 	// TODO: remove tmpfilez
212 	if (strstr (cmd, "R2_BLOCK")) {
213 		// remove temporary BLOCK file
214 		char *f = r_sys_getenv ("R2_BLOCK");
215 		if (f) {
216 			r_file_rm (f);
217 			r_sys_setenv ("R2_BLOCK", NULL);
218 			free (f);
219 		}
220 	}
221 	r_sys_setenv ("R2_FILE", NULL);
222 	r_sys_setenv ("R2_BYTES", NULL);
223 	r_sys_setenv ("R2_OFFSET", NULL);
224 
225 	// remove temporary R2_CONFIG file
226 	char *r2_config = r_sys_getenv ("R2_CONFIG");
227 	if (r2_config) {
228 		r_file_rm (r2_config);
229 		r_sys_setenv ("R2_CONFIG", NULL);
230 		free (r2_config);
231 	}
232 }
233 
r_core_sysenv_begin(RCore * core,const char * cmd)234 R_API char *r_core_sysenv_begin(RCore * core, const char *cmd) {
235 	char *f, *ret = cmd? strdup (cmd): NULL;
236 	RIODesc *desc = core->io->desc;
237 	if (cmd && strstr (cmd, "R2_BYTES")) {
238 		char *s = r_hex_bin2strdup (core->block, core->blocksize);
239 		r_sys_setenv ("R2_BYTES", s);
240 		free (s);
241 	}
242 	r_sys_setenv ("RABIN2_PDBSERVER", r_config_get (core->config, "pdb.server"));
243 	if (desc && desc->name) {
244 		r_sys_setenv ("R2_FILE", desc->name);
245 		r_sys_setenv ("R2_SIZE", sdb_fmt ("%"PFMT64d, r_io_desc_size (desc)));
246 		if (cmd && strstr (cmd, "R2_BLOCK")) {
247 			// replace BLOCK in RET string
248 			if ((f = r_file_temp ("r2block"))) {
249 				if (r_file_dump (f, core->block, core->blocksize, 0)) {
250 					r_sys_setenv ("R2_BLOCK", f);
251 				}
252 				free (f);
253 			}
254 		}
255 	}
256 	r_sys_setenv ("R2_OFFSET", sdb_fmt ("%"PFMT64d, core->offset));
257 	r_sys_setenv ("R2_XOFFSET", sdb_fmt ("0x%08"PFMT64x, core->offset));
258 	r_sys_setenv ("R2_ENDIAN", core->rasm->big_endian? "big": "little");
259 	r_sys_setenv ("R2_BSIZE", sdb_fmt ("%d", core->blocksize));
260 
261 	// dump current config file so other r2 tools can use the same options
262 	char *config_sdb_path = NULL;
263 	int config_sdb_fd = r_file_mkstemp (NULL, &config_sdb_path);
264 	if (config_sdb_fd >= 0) {
265 		close (config_sdb_fd);
266 	}
267 
268 	Sdb *config_sdb = sdb_new (NULL, config_sdb_path, 0);
269 	r_config_serialize (core->config, config_sdb);
270 	sdb_sync (config_sdb);
271 	sdb_free (config_sdb);
272 	r_sys_setenv ("R2_CONFIG", config_sdb_path);
273 
274 	r_sys_setenv ("RABIN2_LANG", r_config_get (core->config, "bin.lang"));
275 	r_sys_setenv ("RABIN2_DEMANGLE", r_config_get (core->config, "bin.demangle"));
276 	r_sys_setenv ("R2_ARCH", r_config_get (core->config, "asm.arch"));
277 	r_sys_setenv ("R2_BITS", sdb_fmt ("%"PFMT64u, r_config_get_i (core->config, "asm.bits")));
278 	r_sys_setenv ("R2_COLOR", r_config_get_i (core->config, "scr.color")? "1": "0");
279 	r_sys_setenv ("R2_DEBUG", r_config_get_i (core->config, "cfg.debug")? "1": "0");
280 	r_sys_setenv ("R2_IOVA", r_config_get_i (core->config, "io.va")? "1": "0");
281 	free (config_sdb_path);
282 	return ret;
283 }
284 
285 #if !__linux__ && !__WINDOWS__
get_base_from_maps(RCore * core,const char * file)286 static ut64 get_base_from_maps(RCore *core, const char *file) {
287 	RDebugMap *map;
288 	RListIter *iter;
289 	ut64 b = 0LL;
290 
291 	r_debug_map_sync (core->dbg); // update process memory maps
292 	r_list_foreach (core->dbg->maps, iter, map) {
293 		if ((map->perm & 5) == 5) {
294 			// TODO: make this more flexible
295 			// XXX - why "copy/" here?
296 			if (map->name && strstr (map->name, "copy/")) {
297 				return map->addr;
298 			}
299 			if (map->file && !strcmp (map->file, file)) {
300 				return map->addr;
301 			}
302 			if (map->name && !strcmp (map->name, file)) {
303 				return map->addr;
304 			}
305 			// XXX - Commented out, as this could unexpected results
306 			//b = map->addr;
307 		}
308 	}
309 	// fallback resolution copied from cmd_debug.c:r_debug_get_baddr
310 	r_list_foreach (core->dbg->maps, iter, map) {
311 		if (map->perm == 5) { // r-x
312 			return map->addr;
313 		}
314 	}
315 
316 	return b;
317 }
318 #endif
319 
320 #if __linux__ || __APPLE__
setbpint(RCore * r,const char * mode,const char * sym)321 static bool setbpint(RCore *r, const char *mode, const char *sym) {
322 	RBreakpointItem *bp;
323 	RFlagItem *fi = r_flag_get (r->flags, sym);
324 	if (!fi) {
325 		return false;
326 	}
327 	bp = r_bp_add_sw (r->dbg->bp, fi->offset, 1, R_BP_PROT_EXEC);
328 	if (bp) {
329 		bp->internal = true;
330 #if __linux__
331 		bp->data = r_str_newf ("?e %s: %s", mode, sym);
332 #else
333 		bp->data = r_str_newf ("?e %s: %s;ps@rdi", mode, sym);
334 #endif
335 		return true;
336 	}
337 	eprintf ("Cannot set breakpoint at %s\n", sym);
338 	return false;
339 }
340 #endif
341 
342 // XXX - need to handle index selection during debugging
r_core_file_do_load_for_debug(RCore * r,ut64 baseaddr,const char * filenameuri)343 static int r_core_file_do_load_for_debug(RCore *r, ut64 baseaddr, const char *filenameuri) {
344 	RIODesc *desc = r->io->desc;
345 	RBinFile *binfile = NULL;
346 	RBinPlugin *plugin;
347 	int xtr_idx = 0; // if 0, load all if xtr is used
348 
349 	// TODO : Honor file.path eval var too?
350 	if (!strncmp ("dbg://", filenameuri, 6)) {
351 		filenameuri += 6;
352 	}
353 	if (!desc) {
354 		return false;
355 	}
356 	int fd = desc->fd;
357 	r_debug_select (r->dbg, r_io_fd_get_pid (r->io, fd),
358 			r_io_fd_get_tid (r->io, fd));
359 #if !__linux__
360 #if !__WINDOWS__
361 	baseaddr = get_base_from_maps (r, filenameuri);
362 #endif
363 	if (baseaddr != UT64_MAX) {
364 		r_config_set_i (r->config, "bin.baddr", baseaddr);
365 	}
366 #endif
367 	RBinOptions opt;
368 	r_bin_options_init (&opt, fd, baseaddr, UT64_MAX, false);
369 	opt.xtr_idx = xtr_idx;
370 	if (!r_bin_open (r->bin, filenameuri, &opt)) {
371 		eprintf ("RBinLoad: Cannot open %s\n", filenameuri);
372 		if (r_config_get_i (r->config, "bin.rawstr")) {
373 			r_bin_options_init (&opt, fd, baseaddr, UT64_MAX, true);
374 			opt.xtr_idx = xtr_idx;
375 			if (!r_bin_open (r->bin, filenameuri, &opt)) {
376 				return false;
377 			}
378 		}
379 	}
380 
381 	if (*r_config_get (r->config, "dbg.libs")) {
382 		r_core_cmd0 (r, ".dmm*");
383 #if __linux__
384 		setbpint (r, "dbg.libs", "sym.imp.dlopen");
385 		setbpint (r, "dbg.libs", "sym.imp.dlmopen");
386 		setbpint (r, "dbg.unlibs", "sym.imp.dlclose");
387 #elif __APPLE__
388 		setbpint (r, "dbg.libs", "sym._dlopen");
389 		setbpint (r, "dbg.libs", "sym._dlclose");
390 #endif
391 	}
392 	binfile = r_bin_cur (r->bin);
393 	r_core_bin_set_env (r, binfile);
394 	plugin = r_bin_file_cur_plugin (binfile);
395 	if (plugin && !strcmp (plugin->name, "any")) {
396 		// set use of raw strings
397 		// r_config_set_i (r->config, "io.va", false);
398 		//\\ r_config_set (r->config, "bin.rawstr", "true");
399 		// get bin.minstr
400 		r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr");
401 		r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf");
402 	} else if (binfile) {
403 		RBinObject *obj = r_bin_cur_object (r->bin);
404 		RBinInfo *info = obj? obj->info: NULL;
405 		if (plugin && info) {
406 			r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits);
407 		}
408 	}
409 
410 	if (plugin && !strcmp (plugin->name, "dex")) {
411 		r_core_cmd0 (r, "\"(fix-dex,wx `ph sha1 $s-32 @32` @12 ; wx `ph adler32 $s-12 @12` @8)\"\n");
412 	}
413 
414 	return true;
415 }
416 
r_core_file_do_load_for_io_plugin(RCore * r,ut64 baseaddr,ut64 loadaddr)417 static int r_core_file_do_load_for_io_plugin(RCore *r, ut64 baseaddr, ut64 loadaddr) {
418 	RIODesc *cd = r->io->desc;
419 	int fd = cd ? cd->fd : -1;
420 	RBinFile *binfile = NULL;
421 	int xtr_idx = 0; // if 0, load all if xtr is used
422 	RBinPlugin *plugin;
423 
424 	if (fd < 0) {
425 		return false;
426 	}
427 	r_io_use_fd (r->io, fd);
428 	RBinOptions opt;
429 	r_bin_options_init (&opt, fd, baseaddr, loadaddr, r->bin->rawstr);
430 	opt.xtr_idx = xtr_idx;
431 	if (!r_bin_open_io (r->bin, &opt)) {
432 		//eprintf ("Failed to load the bin with an IO Plugin.\n");
433 		return false;
434 	}
435 	binfile = r_bin_cur (r->bin);
436 	if (r_core_bin_set_env (r, binfile)) {
437 		if (!r->anal->sdb_cc->path) {
438 			R_LOG_WARN ("No calling convention defined for this file, analysis may be inaccurate.\n");
439 		}
440 	}
441 	plugin = r_bin_file_cur_plugin (binfile);
442 	if (plugin && !strcmp (plugin->name, "any")) {
443 		RBinObject *obj = r_bin_cur_object (r->bin);
444 		RBinInfo *info = obj? obj->info: NULL;
445 		if (!info) {
446 			return false;
447 		}
448 		info->bits = r->rasm->bits;
449 		// set use of raw strings
450 		r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits);
451 		// r_config_set_i (r->config, "io.va", false);
452 		// r_config_set (r->config, "bin.rawstr", "true");
453 		// get bin.minstr
454 		r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr");
455 		r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf");
456 	} else if (binfile) {
457 		RBinObject *obj = r_bin_cur_object (r->bin);
458 		RBinInfo *info = obj? obj->info: NULL;
459 		if (!info) {
460 			return false;
461 		}
462 		if (plugin) {
463 			r_core_bin_set_arch_bits (r, binfile->file,
464 				info->arch, info->bits);
465 		}
466 	}
467 
468 	if (plugin && !strcmp (plugin->name, "dex")) {
469 		r_core_cmd0 (r, "\"(fix-dex,wx `ph sha1 $s-32 @32` @12 ; wx `ph adler32 $s-12 @12` @8)\"\n");
470 	}
471 	return true;
472 }
473 
try_loadlib(RCore * core,const char * lib,ut64 addr)474 static bool try_loadlib(RCore *core, const char *lib, ut64 addr) {
475 	void *p = r_core_file_open (core, lib, 0, addr);
476 	if (p) {
477 		r_core_bin_load (core, lib, addr);
478 		R_FREE (p);
479 		return true;
480 	}
481 	return false;
482 }
483 
r_core_file_loadlib(RCore * core,const char * lib,ut64 libaddr)484 R_API bool r_core_file_loadlib(RCore *core, const char *lib, ut64 libaddr) {
485 	const char *dirlibs = r_config_get (core->config, "dir.libs");
486 	bool free_libdir = true;
487 #ifdef __WINDOWS__
488 	char *libdir = r_str_r2_prefix (R2_LIBDIR);
489 #else
490 	char *libdir = strdup (R2_LIBDIR);
491 #endif
492 	if (!libdir) {
493 		libdir = R2_LIBDIR;
494 		free_libdir = false;
495 	}
496 	if (!dirlibs || !*dirlibs) {
497 		dirlibs = "." R_SYS_DIR;
498 	}
499 	const char *ldlibrarypath[] = {
500 		dirlibs,
501 		libdir,
502 #ifndef __WINDOWS__
503 		"/usr/local/lib",
504 		"/usr/lib",
505 		"/lib",
506 #endif
507 		"." R_SYS_DIR,
508 		NULL
509 	};
510 	const char * *libpath = (const char * *) &ldlibrarypath;
511 
512 	bool ret = false;
513 #ifdef __WINDOWS__
514 	if (strlen (lib) >= 3 && lib[1] == ':' && lib[2] == '\\') {
515 #else
516 	if (*lib == '/') {
517 #endif
518 		if (try_loadlib (core, lib, libaddr)) {
519 			ret = true;
520 		}
521 	} else {
522 		while (*libpath) {
523 			char *s = r_str_newf ("%s" R_SYS_DIR "%s", *libpath, lib);
524 			if (try_loadlib (core, s, libaddr)) {
525 				ret = true;
526 			}
527 			free (s);
528 			if (ret) {
529 				break;
530 			}
531 			libpath++;
532 		}
533 	}
534 	if (free_libdir) {
535 		free (libdir);
536 	}
537 	return ret;
538 }
539 
540 R_API int r_core_bin_rebase(RCore *core, ut64 baddr) {
541 	if (!core || !core->bin || !core->bin->cur) {
542 		return 0;
543 	}
544 	if (baddr == UT64_MAX) {
545 		return 0;
546 	}
547 	RBinFile *bf = core->bin->cur;
548 	bf->o->baddr = baddr;
549 	bf->o->loadaddr = baddr;
550 	r_bin_object_set_items (bf, bf->o);
551 	return 1;
552 }
553 
554 static void load_scripts_for(RCore *core, const char *name) {
555 	// TODO:
556 	char *file;
557 	RListIter *iter;
558 	char *hdir = r_str_newf (R_JOIN_2_PATHS (R2_HOME_BINRC, "bin-%s"), name);
559 	char *path = r_str_home (hdir);
560 	RList *files = r_sys_dir (path);
561 	if (!r_list_empty (files)) {
562 		eprintf ("[binrc] path: %s\n", path);
563 	}
564 	r_list_foreach (files, iter, file) {
565 		if (*file && *file != '.') {
566 			eprintf ("[binrc] loading %s\n", file);
567 			r_core_cmdf (core, ". %s/%s", path, file);
568 		}
569 	}
570 	r_list_free (files);
571 	free (path);
572 	free (hdir);
573 }
574 
575 typedef struct {
576 	const char *name;
577 	bool found;
578 } MyFileData;
579 
580 static bool filecb(void *user, void *data, ut32 id) {
581 	MyFileData *filedata = user;
582 	RIODesc *desc = (RIODesc *)data;
583 	if (!strcmp (desc->name, filedata->name)) {
584 		filedata->found = true;
585 	}
586 	return true;
587 }
588 
589 static bool file_is_loaded(RCore *core, const char *lib) {
590 	MyFileData filedata = {lib, false};
591 	r_id_storage_foreach (core->io->files, filecb, &filedata);
592 	return filedata.found;
593 }
594 
595 typedef struct {
596 	const char *name;
597 	ut64 addr;
598 	RBin *bin;
599 } RCoreLinkData;
600 
601 static bool linkcb(void *user, void *data, ut32 id) {
602 	RCoreLinkData *ld = user;
603 	RIODesc *desc = (RIODesc *)data;
604 
605 	RBinFile *bf = r_bin_file_find_by_fd (ld->bin, desc->fd);
606 	if (bf) {
607 		RListIter *iter;
608 		RBinSymbol *sym;
609 		RList *symbols = r_bin_file_get_symbols (bf);
610 		r_list_foreach (symbols, iter, sym) {
611 			if (!strcmp (sym->name, ld->name)) {
612 				ld->addr = sym->vaddr;
613 				return false;
614 			}
615 		}
616 	}
617 	return true;
618 }
619 
620 R_API bool r_core_bin_load(RCore *r, const char *filenameuri, ut64 baddr) {
621 	RIODesc *desc = r->io->desc;
622 	ut64 laddr = r_config_get_i (r->config, "bin.laddr");
623 	RBinFile *binfile = NULL;
624 	RBinPlugin *plugin = NULL;
625 	bool is_io_load;
626 	const char *cmd_load;
627 	if (!desc) {
628 		return false;
629 	}
630 	// NULL deref guard
631 	if (desc) {
632 		is_io_load = desc && desc->plugin;
633 		if (!filenameuri || !*filenameuri) {
634 			filenameuri = desc->name;
635 		}
636 	} else {
637 		is_io_load = false;
638 	}
639 
640 	if (!filenameuri) {
641 		eprintf ("r_core_bin_load: no file specified\n");
642 		return false;
643 	}
644 
645 	r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr");
646 	r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf");
647 	if (is_io_load) {
648 		// TODO? necessary to restore the desc back?
649 		// Fix to select pid before trying to load the binary
650 		if ((desc->plugin && desc->plugin->isdbg) || r_config_get_i (r->config, "cfg.debug")) {
651 			r_core_file_do_load_for_debug (r, baddr, filenameuri);
652 		} else {
653 			r_core_file_do_load_for_io_plugin (r, baddr, 0LL);
654 		}
655 		r_io_use_fd (r->io, desc->fd);
656 		// Restore original desc
657 	}
658 	if (binfile && desc) {
659 		binfile->fd = desc->fd;
660 	}
661 	binfile = r_bin_cur (r->bin);
662 	if (r->bin->cur && r->bin->cur->o && r->bin->cur->o->plugin && r->bin->cur->o->plugin->strfilter) {
663 		char msg[2];
664 		msg[0] = r->bin->cur->o->plugin->strfilter;
665 		msg[1] = 0;
666 		r_config_set (r->config, "bin.str.filter", msg);
667 	}
668 	//r_core_bin_set_env (r, binfile);
669 	plugin = r_bin_file_cur_plugin (binfile);
670 	if (plugin && plugin->name) {
671 		load_scripts_for (r, plugin->name);
672 	}
673 	cmd_load = r_config_get (r->config, "cmd.load");
674 	if (cmd_load && *cmd_load) {
675 		r_core_cmd (r, cmd_load, 0);
676 	}
677 
678 	if (plugin && plugin->name) {
679 		if (!strcmp (plugin->name, "any")) {
680 			if (r_str_startswith (desc->name, "rap") && strstr (desc->name, "://")) {
681 				r_io_map_new (r->io, desc->fd, desc->perm, 0, laddr, UT64_MAX);
682 			} else {
683 				r_io_map_new (r->io, desc->fd, desc->perm, 0, laddr, r_io_desc_size (desc));
684 			}
685 			// set use of raw strings
686 			//r_config_set (r->config, "bin.rawstr", "true");
687 			// r_config_set_i (r->config, "io.va", false);
688 			// get bin.minstr
689 			r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr");
690 			r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf");
691 		} else if (binfile) {
692 			RBinObject *obj = r_bin_cur_object (r->bin);
693 			if (obj) {
694 				bool va = obj->info ? obj->info->has_va : 0;
695 				if (!va) {
696 					r_config_set_i (r->config, "io.va", 0);
697 				}
698 				//workaround to map correctly malloc:// and raw binaries
699 				if (r_io_desc_is_dbg (desc) || (!obj->sections || !va)) {
700 					r_io_map_new (r->io, desc->fd, desc->perm, 0, laddr, r_io_desc_size (desc));
701 				}
702 				RBinInfo *info = obj->info;
703 				if (info) {
704 					r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits);
705 				} else {
706 					r_core_bin_set_arch_bits (r, binfile->file,
707 						r_config_get (r->config, "asm.arch"),
708 						r_config_get_i (r->config, "asm.bits"));
709 				}
710 			}
711 		}
712 	} else {
713 		if (desc) {
714 			r_io_map_new (r->io, desc->fd, desc->perm, 0, laddr, r_io_desc_size (desc));
715 		}
716 		if (binfile) {
717 			r_core_bin_set_arch_bits (r, binfile->file,
718 					r_config_get (r->config, "asm.arch"),
719 					r_config_get_i (r->config, "asm.bits"));
720 		}
721 	}
722 	if (desc && r_config_get_i (r->config, "io.exec")) {
723 		desc->perm |= R_PERM_X;
724 	}
725 	if (plugin && plugin->name && !strcmp (plugin->name, "dex")) {
726 		r_core_cmd0 (r, "\"(fix-dex,wx `ph sha1 $s-32 @32` @12 ;"
727 			" wx `ph adler32 $s-12 @12` @8)\"\n");
728 	}
729 	if (!r_config_get_i (r->config, "cfg.debug")) {
730 		loadGP (r);
731 	}
732 	if (r_config_get_i (r->config, "bin.libs")) {
733 		const char *lib;
734 		RListIter *iter;
735 		RList *libs = r_bin_get_libs (r->bin);
736 		r_list_foreach (libs, iter, lib) {
737 			if (file_is_loaded (r, lib)) {
738 				continue;
739 			}
740 			eprintf ("[bin.libs] Opening %s\n", lib);
741 			ut64 baddr = r_io_map_location (r->io, 0x200000);
742 			if (baddr != UT64_MAX) {
743 				r_core_file_loadlib (r, lib, baddr);
744 			}
745 		}
746 		r_core_cmd0 (r, "obb 0;s entry0");
747 		r_config_set_i (r->config, "bin.at", true);
748 		eprintf ("[bin.libs] Linking imports...\n");
749 		RBinImport *imp;
750 		RList *imports = r_bin_get_imports (r->bin);
751 		r_list_foreach (imports, iter, imp) {
752 			// PLT finding
753 			RFlagItem *impsym = r_flag_get (r->flags, sdb_fmt ("sym.imp.%s", imp->name));
754 			if (!impsym) {
755 				//eprintf ("Cannot find '%s' import in the PLT\n", imp->name);
756 				continue;
757 			}
758 			ut64 imp_addr = impsym->offset;
759 			eprintf ("Resolving %s... ", imp->name);
760 			RCoreLinkData linkdata = {imp->name, UT64_MAX, r->bin};
761 			r_id_storage_foreach (r->io->files, linkcb, &linkdata);
762 			if (linkdata.addr != UT64_MAX) {
763 				eprintf ("0x%08"PFMT64x"\n", linkdata.addr);
764 				ut64 a = linkdata.addr;
765 				ut64 b = imp_addr;
766 				r_core_cmdf (r, "ax 0x%08"PFMT64x" 0x%08"PFMT64x, a, b);
767 			} else {
768 				eprintf ("NO\n");
769 			}
770 		}
771 	}
772 
773 	//If type == R_BIN_TYPE_CORE, we need to create all the maps
774 	if (plugin && binfile && plugin->file_type
775 		 && plugin->file_type (binfile) == R_BIN_TYPE_CORE) {
776 		ut64 sp_addr = (ut64)-1;
777 		RIOMap *stack_map = NULL;
778 
779 		// Setting the right arch and bits, so regstate will be shown correctly
780 		if (plugin->info) {
781 			RBinInfo *inf = plugin->info (binfile);
782 			eprintf ("Setting up coredump arch-bits to: %s-%d\n", inf->arch, inf->bits);
783 			r_config_set (r->config, "asm.arch", inf->arch);
784 			r_config_set_i (r->config, "asm.bits", inf->bits);
785 			r_bin_info_free (inf);
786 		}
787 		if (binfile->o->regstate) {
788 			if (r_reg_arena_set_bytes (r->anal->reg, binfile->o->regstate)) {
789 				eprintf ("Setting up coredump: Problem while setting the registers\n");
790 			} else {
791 				eprintf ("Setting up coredump: Registers have been set\n");
792 				const char *regname = r_reg_get_name (r->anal->reg, R_REG_NAME_SP);
793 				if (regname) {
794 					RRegItem *reg = r_reg_get (r->anal->reg, regname, -1);
795 					if (reg) {
796 						sp_addr = r_reg_get_value (r->anal->reg, reg);
797 						stack_map = r_io_map_get (r->io, sp_addr);
798 					}
799 				}
800 				regname = r_reg_get_name (r->anal->reg, R_REG_NAME_PC);
801 				if (regname) {
802 					RRegItem *reg = r_reg_get (r->anal->reg, regname, -1);
803 					if (reg) {
804 						ut64 seek = r_reg_get_value (r->anal->reg, reg);
805 						r_core_seek (r, seek, true);
806 					}
807 				}
808 			}
809 		}
810 
811 		RBinObject *o = binfile->o;
812 		int map = 0;
813 		if (o && o->maps) {
814 			RList *maps = o->maps;
815 			RListIter *iter;
816 			RBinMap *mapcore;
817 
818 			r_list_foreach (maps, iter, mapcore) {
819 				RIOMap *iomap = r_io_map_get (r->io, mapcore->addr);
820 				if (iomap && (mapcore->file || stack_map == iomap)) {
821 					r_io_map_set_name (iomap, r_str_get_fail (mapcore->file, "[stack]"));
822 				}
823 				map++;
824 			}
825 			r_list_free (maps);
826 			o->maps = NULL;
827 		}
828 		eprintf ("Setting up coredump: %d maps have been found and created\n", map);
829 		goto beach;
830 	}
831 beach:
832 	return true;
833 }
834 
835 R_API RIODesc *r_core_file_open_many(RCore *r, const char *file, int perm, ut64 loadaddr) {
836 	const bool openmany = r_config_get_i (r->config, "file.openmany");
837 	int opened_count = 0;
838 	RListIter *fd_iter, *iter2;
839 	RIODesc *fd;
840 
841 	RList *list_fds = r_io_open_many (r->io, file, perm, 0644);
842 
843 	if (!list_fds || r_list_length (list_fds) == 0) {
844 		r_list_free (list_fds);
845 		return NULL;
846 	}
847 
848 	r_list_foreach_safe (list_fds, fd_iter, iter2, fd) {
849 		opened_count++;
850 		if (openmany && opened_count > 1) {
851 			// XXX - Open Many should limit the number of files
852 			// loaded in io plugin area this needs to be more premptive
853 			// like down in the io plugin layer.
854 			// start closing down descriptors
855 			r_list_delete (list_fds, fd_iter);
856 			continue;
857 		}
858 		r_core_bin_load (r, fd->name, loadaddr);
859 	}
860 	return NULL;
861 }
862 
863 /* loadaddr is r2 -m (mapaddr) */
864 R_API RIODesc *r_core_file_open(RCore *r, const char *file, int flags, ut64 loadaddr) {
865 	r_return_val_if_fail (r && file, NULL);
866 	ut64 prev = r_time_now_mono ();
867 	const bool openmany = r_config_get_i (r->config, "file.openmany");
868 
869 	if (!strcmp (file, "-")) {
870 		file = "malloc://512";
871 	}
872 	//if not flags was passed open it with -r--
873 	if (!flags) {
874 		flags = R_PERM_R;
875 	}
876 	r->io->bits = r->rasm->bits; // TODO: we need an api for this
877 	RIODesc *fd = r_io_open_nomap (r->io, file, flags, 0644);
878 	if (r_cons_is_breaked()) {
879 		goto beach;
880 	}
881 	if (!fd && openmany) {
882 		// XXX - make this an actual option somewhere?
883 		fd = r_core_file_open_many (r, file, flags, loadaddr);
884 		if (fd) {
885 			goto beach;
886 		}
887 	}
888 	if (!fd) {
889 		if (flags & R_PERM_W) {
890 		//	flags |= R_IO_CREAT;
891 			if (!(fd = r_io_open_nomap (r->io, file, flags, 0644))) {
892 				goto beach;
893 			}
894 		} else {
895 			goto beach;
896 		}
897 	}
898 	if (r_io_is_listener (r->io)) {
899 		r_core_serve (r, fd);
900 		r_io_desc_free (fd);
901 		fd = NULL;
902 		goto beach;
903 	}
904 
905 	{
906 		const char *cp = r_config_get (r->config, "cmd.open");
907 		if (cp && *cp) {
908 			r_core_cmd (r, cp, 0);
909 		}
910 	}
911 
912 	r_io_use_fd (r->io, fd->fd);
913 
914 	if (r_config_get_i (r->config, "cfg.debug")) {
915 		bool swstep = true;
916 		if (r->dbg->h && r->dbg->h->canstep) {
917 			swstep = false;
918 		}
919 		r_config_set_i (r->config, "dbg.swstep", swstep);
920 		// Set the correct debug handle
921 		if (fd->plugin && fd->plugin->isdbg) {
922 			char *dh = r_str_ndup (file, (strstr (file, "://") - file));
923 			if (dh) {
924 				r_debug_use (r->dbg, dh);
925 				free (dh);
926 			}
927 		}
928 	}
929 	//used by r_core_bin_load otherwise won't load correctly
930 	//this should be argument of r_core_bin_load <shrug>
931 	if (loadaddr != UT64_MAX) {
932 		r_config_set_i (r->config, "bin.laddr", loadaddr);
933 	}
934 	r_core_cmd0 (r, "=!");
935 beach:
936 	r->times->file_open_time = r_time_now_mono () - prev;
937 	return fd;
938 }
939