1 /* radare - LGPL - Copyright 2009-2021 - pancake */
2 
3 #include <r_bin.h>
4 #include <r_debug.h>
5 
6 static const char *help_msg_o[] = {
7 	"Usage: o","[com- ] [file] ([offset])","",
8 	"o"," [file] 0x4000 rwx", "map file at 0x4000",
9 	"o"," [file]","open [file] file in read-only",
10 	"o","","list opened files",
11 	"o","-1","close file descriptor 1",
12 	"o*","","list opened files in r2 commands",
13 	"o+"," [file]","open file in read-write mode",
14 	"o-","!*","close all opened files",
15 	"o--","","close all files, analysis, binfiles, flags, same as !r2 --",
16 	"o.","","show current filename (or o.q/oq to get the fd)",
17 	"o:"," [len]","open a malloc://[len] copying the bytes from current offset",
18 	"o=","","list opened files (ascii-art bars)",
19 	"oL","","list all IO plugins registered",
20 	"oa","[-] [A] [B] [filename]","Specify arch and bits for given file",
21 	"ob","[?] [lbdos] [...]","list opened binary files backed by fd",
22 	"oc"," [file]","open core file, like relaunching r2",
23 	"of"," [file]","open file and map it at addr 0 as read-only",
24 	"oj","[?]	","list opened files in JSON format",
25 	"om","[?]","create, list, remove IO maps",
26 	"on"," [file] 0x4000","map raw file at 0x4000 (no r_bin involved)",
27 	"onn"," [file] ([rwx])","open file without creating any map or parsing headers with rbin)",
28 	"oo","[?+bcdnm]","reopen current file (see oo?) (reload in rw or debugger)",
29 	"op","[r|n|p|fd]", "select priorized file by fd (see ob), opn/opp/opr = next/previous/rotate",
30 	"oq","","list all open files",
31 	"ox", " fd fdx", "exchange the descs of fd and fdx and keep the mapping",
32 	NULL
33 };
34 
35 static const char *help_msg_o_[] = {
36 	"Usage: o-","[#!*]", "",
37 	"o-*","","close all opened files",
38 	"o-!","","close all files except the current one",
39 	"o-3","","close fd=3",
40 	NULL
41 };
42 
43 static const char *help_msg_op[] = {
44 	"Usage:", "op[rnp] [fd]", "",
45 	"opr", "", "open next file rotating",
46 	"opn", "", "open next file",
47 	"opp", "", "open previous file",
48 	"op", " [fd]", "open priorizing fd",
49 	NULL
50 };
51 
52 static const char *help_msg_o_star[] = {
53 	"Usage:", "o* [> files.r2]", "",
54 	"o*", "", "list opened files in r2 commands", NULL
55 };
56 
57 static const char *help_msg_oa[] = {
58 	"Usage:", "oba [addr] ([filename])", " # load bininfo and update flags",
59 	"oba", " [addr]", "Open bin info from the given address",
60 	"oba", " [addr] [baddr]", "Open file and load bin info at given address",
61 	"oba", " [addr] [/abs/filename]", "Open file and load bin info at given address",
62 	NULL
63 };
64 
65 static const char *help_msg_ob[] = {
66 	"Usage:", "ob", " # List open binary files backed by fd",
67 	"ob", " [bfid]", "Switch to open given objid",
68 	"ob", "", "List opened binary files and objid",
69 	"ob*", "", "List opened binary files and objid (r2 commands)",
70 	"ob-", "*", "Delete all binfiles",
71 	"ob-", "[objid]", "Delete binfile by binobjid",
72 	"ob.", " ([addr])", "Show bfid at current address",
73 	"ob=", "", "Show ascii art table having the list of open files",
74 	"obL", "", "Same as iL or Li",
75 	"oba", " [addr] [baddr]", "Open file and load bin info at given address",
76 	"oba", " [addr] [filename]", "Open file and load bin info at given address",
77 	"oba", " [addr]", "Open bin info from the given address",
78 	"obf", " ([file])", "Load bininfo for current file (useful for r2 -n)",
79 	"obj", "", "List opened binary files and objid (JSON format)",
80 	"obn", " [name]", "Select binfile by name",
81 	"obo", " [fd]", "Switch to open binfile by fd number",
82 	"obr", " [baddr]", "Rebase current bin object",
83 	NULL
84 };
85 
86 static const char *help_msg_oj[] = {
87 	"Usage:", "oj [~{}]", " # Use ~{} to indent the JSON",
88 	"oj", "", "list opened files in JSON format", NULL
89 };
90 
91 static const char *help_msg_om[] = {
92 	"Usage:", "om[-] [arg]", " # map opened files",
93 	"om", " [fd]", "list all defined IO maps for a specific fd",
94 	"om", " fd vaddr [size] [paddr] [rwx] [name]", "create new io map",
95 	"om", "", "list all defined IO maps",
96 	"om*", "", "list all maps in r2 commands format",
97 	"om-", "mapid", "remove the map with corresponding id",
98 	"om-*", "", "remove all maps",
99 	"om-..", "", "hud view of all the maps to select the one to remove",
100 	"om.", "", "show map, that is mapped to current offset",
101 	"om=", "", "list all maps in ascii art",
102 	"oma"," [fd]", "create a map covering all VA for given fd",
103 	"omb", " mapid addr", "relocate map with corresponding id",
104 	"omb.", " addr", "relocate current map",
105 	"omf", " [mapid] rwx", "change flags/perms for current/given map",
106 	"omfg", "[+-]rwx", "change flags/perms for all maps (global)",
107 	"omj", "", "list all maps in json format",
108 	"omm"," [fd]", "create default map for given fd. (omm `oq`)",
109 	"omn", " mapaddr [name]", "set/delete name for map which spans mapaddr",
110 	"omn.", "([-|name])", "show/set/delete name for current map",
111 	"omni", " mapid [name]", "set/delete name for map with mapid",
112 	"omo", " fd", "map the given fd with lowest priority",
113 	"omp", " mapid", "prioritize map with corresponding id",
114 	"ompb", " [fd]", "prioritize maps of the bin associated with the binid",
115 	"ompd", " mapid", "deprioritize map with corresponding id",
116 	"ompf", " [fd]", "prioritize map by fd",
117 	"omq", "", "list all maps and their fds",
118 	"omqq", "", "list all maps addresses (See $MM to get the size)",
119 	"omr", " mapid newsize", "resize map with corresponding id",
120 	"omt", " [query]", "list maps using table api",
121 	NULL
122 };
123 
124 static const char *help_msg_oo[] = {
125 	"Usage:", "oo[-] [arg]", " # map opened files",
126 	"oo", "", "reopen current file",
127 	"oo+", "", "reopen in read-write",
128 	"oob", " [baddr]", "reopen loading rbin info (change base address?)",
129 	"ooc", "", "reopen core with current file",
130 	"ood", "", "reopen in debug mode",
131 	"oom", "", "reopen in malloc://",
132 	"oon", "", "reopen without loading rbin info",
133 	"oon+", "", "reopen in read-write mode without loading rbin info",
134 	"oonn", "", "reopen without loading rbin info, but with header flags",
135 	"oonn+", "", "reopen in read-write mode without loading rbin info, but with",
136 	NULL
137 };
138 
139 static const char *help_msg_oo_plus[] = {
140 	"Usage:", "oo+", " # reopen in read-write",
141 	NULL
142 };
143 
144 static const char *help_msg_oob[] = {
145 	"Usage:", "oob", " # reopen loading rbin info",
146 	NULL
147 };
148 
149 static const char *help_msg_ood[] = {
150 	"Usage:", "ood", " # Debug (re)open commands",
151 	"ood", " [args]", " # reopen in debug mode (with args)",
152 	"oodf", " [file]", " # reopen in debug mode using the given file",
153 	"oodr", " [rarun2]", " # same as dor ..;ood",
154 	NULL
155 };
156 
157 static const char *help_msg_oon[] = {
158 	"Usage:", "oon[+]", " # reopen without loading rbin info",
159 	"oon", "", "reopen without loading rbin info",
160 	"oon+", "", "reopen in read-write mode without loading rbin info",
161 	NULL
162 };
163 
164 static const char *help_msg_oonn[] = {
165 	"Usage:", "oonn", " # reopen without loading rbin info, but with header flags",
166 	"oonn", "", "reopen without loading rbin info, but with header flags",
167 	"oonn+", "", "reopen in read-write mode without loading rbin info, but with",
168 	NULL
169 };
170 
cmd_open_init(RCore * core,RCmdDesc * parent)171 static void cmd_open_init(RCore *core, RCmdDesc *parent) {
172 	DEFINE_CMD_DESCRIPTOR (core, o);
173 	DEFINE_CMD_DESCRIPTOR_SPECIAL (core, o*, o_star);
174 	DEFINE_CMD_DESCRIPTOR (core, oa);
175 	DEFINE_CMD_DESCRIPTOR (core, ob);
176 	DEFINE_CMD_DESCRIPTOR (core, oj);
177 	DEFINE_CMD_DESCRIPTOR (core, om);
178 	DEFINE_CMD_DESCRIPTOR (core, oo);
179 	DEFINE_CMD_DESCRIPTOR_SPECIAL (core, oo+, oo_plus);
180 	DEFINE_CMD_DESCRIPTOR (core, oob);
181 	DEFINE_CMD_DESCRIPTOR (core, ood);
182 	DEFINE_CMD_DESCRIPTOR (core, oon);
183 	DEFINE_CMD_DESCRIPTOR (core, oonn);
184 }
185 
186 // HONOR bin.at
cmd_open_bin(RCore * core,const char * input)187 static void cmd_open_bin(RCore *core, const char *input) {
188 	const char *value = NULL;
189 	ut32 binfile_num = -1;
190 
191 	switch (input[1]) {
192 	case 'L': // "obL"
193 		r_core_cmd0 (core, "iL");
194 		break;
195 	case '\0': // "ob"
196 	case 'q': // "obj"
197 	case 'j': // "obj"
198 	case '*': // "ob*"
199 		r_core_bin_list (core, input[1]);
200 		if (input[1] == 'j') {
201 			r_cons_newline ();
202 		}
203 		break;
204 	case '.': // "ob."
205 		{
206 			const char *arg = r_str_trim_head_ro (input + 2);
207 			ut64 at = core->offset;
208 			if (*arg) {
209 				at = r_num_math (core->num, arg);
210 				if (at == 0 && *arg != '0') {
211 					at = core->offset;
212 				}
213 			}
214 			RBinFile *bf = r_bin_file_at (core->bin, at);
215 			if (bf) {
216 				r_cons_printf ("%d\n", bf->id);
217 			}
218 		}
219 		break;
220 	case 'a': // "oba"
221 		if ('?' == input[2]) {
222 			r_core_cmd_help (core, help_msg_oa);
223 			break;
224 		}
225 		if (input[2] && input[3]) {
226 			char *arg = strdup (input + 3);
227 			char *filename = strchr (arg, ' ');
228 			if (filename && *filename && (filename[1] == '/' || filename[1] == '.')) {
229 				int saved_fd = r_io_fd_get_current (core->io);
230 				RIODesc *desc = r_io_open (core->io, filename + 1, R_PERM_RX, 0);
231 				if (desc) {
232 					*filename = 0;
233 					ut64 addr = r_num_math (core->num, arg);
234 					RBinOptions opt;
235 					r_bin_options_init (&opt, desc->fd, addr, 0, core->bin->rawstr);
236 					r_bin_open_io (core->bin, &opt);
237 					r_io_desc_close (desc);
238 					r_core_cmd0 (core, ".is*");
239 					r_io_use_fd (core->io, saved_fd);
240 				} else {
241 					eprintf ("Cannot open %s\n", filename + 1);
242 				}
243 			} else if (filename && *filename) {
244 				ut64 baddr = r_num_math (core->num, filename);
245 				ut64 addr = r_num_math (core->num, input + 2); // mapaddr
246 				int fd = r_io_fd_get_current (core->io);
247 				RIODesc *desc = r_io_desc_get (core->io, fd);
248 				if (desc) {
249 					RBinOptions opt;
250 					opt.baseaddr = baddr;
251 					opt.loadaddr = addr;
252 					opt.sz = 1024*1024*1;
253 					r_bin_options_init (&opt, desc->fd, baddr, addr, core->bin->rawstr);
254 					r_bin_open_io (core->bin, &opt);
255 					r_core_cmd0 (core, ".is*");
256 				} else {
257 					eprintf ("No file to load bin from?\n");
258 				}
259 			} else {
260 				ut64 addr = r_num_math (core->num, input + 2);
261 				int fd = r_io_fd_get_current (core->io);
262 				RIODesc *desc = r_io_desc_get (core->io, fd);
263 				if (desc) {
264 					RBinOptions opt;
265 					opt.baseaddr = addr;
266 					opt.loadaddr = addr;
267 					opt.sz = 1024 * 1024 * 1;
268 					r_bin_options_init (&opt, desc->fd, addr, addr, core->bin->rawstr);
269 					r_bin_open_io (core->bin, &opt);
270 					r_core_cmd0 (core, ".is*");
271 				} else {
272 					eprintf ("No file to load bin from?\n");
273 				}
274 			}
275 			free (arg);
276 		} else {
277 			RList *ofiles = r_id_storage_list (core->io->files);
278 			RIODesc *desc;
279 			RListIter *iter;
280 			RList *files = r_list_newf (NULL);
281 			r_list_foreach (ofiles, iter, desc) {
282 				r_list_append (files, (void*)(size_t)desc->fd);
283 			}
284 
285 			void *_fd;
286 			r_list_foreach (files, iter, _fd) {
287 				int fd = (size_t)_fd;
288 				RBinOptions opt;
289 				r_bin_options_init (&opt, fd, core->offset, 0, core->bin->rawstr);
290 				r_bin_open_io (core->bin, &opt);
291 				r_core_cmd0 (core, ".ies*");
292 				break;
293 			}
294 			r_list_free (files);
295 		}
296 		break;
297 	case ' ': // "ob "
298 	{
299 		ut32 id;
300 		int n;
301 		const char *tmp;
302 		char *v;
303 		v = input[2] ? strdup (input + 2) : NULL;
304 		if (!v) {
305 			eprintf ("Invalid arguments");
306 			break;
307 		}
308 		n = r_str_word_set0 (v);
309 		if (n < 1 || n > 2) {
310 			eprintf ("Usage: ob [file|objid]\n");
311 			free (v);
312 			break;
313 		}
314 		tmp = r_str_word_get0 (v, 0);
315 		id = *v && r_is_valid_input_num_value (core->num, tmp)
316 			? r_get_input_num_value (core->num, tmp): UT32_MAX;
317 		if (n == 2) {
318 			tmp = r_str_word_get0 (v, 1);
319 		} else {
320 			binfile_num = id;
321 		}
322 		r_core_bin_raise (core, binfile_num);
323 		free (v);
324 		break;
325 	}
326 	case 'r': // "obr"
327 		r_core_bin_rebase (core, r_num_math (core->num, input + 3));
328 		r_core_cmd0 (core, ".is*");
329 		break;
330 	case 'f':
331 		if (input[2] == ' ') {
332 			r_core_cmdf (core, "oba 0 %s", input + 3);
333 		} else {
334 			r_core_bin_load (core, NULL, UT64_MAX);
335 			value = input[2] ? input + 2 : NULL;
336 		}
337 		break;
338 	case 'o': // "obo"
339 		if (input[2] == ' ') {
340 			ut32 fd = r_num_math (core->num, input + 3);
341 			RBinFile *bf = r_bin_file_find_by_fd (core->bin, fd);
342 			if (!bf || !r_core_bin_raise (core, bf->id)) {
343 				eprintf ("Invalid RBinFile.id number.\n");
344 			}
345 		} else {
346 			eprintf ("Usage: obb [bfid]\n");
347 		}
348 		break;
349 	case '-': // "ob-"
350 		if (input[2] == '*') {
351 			r_bin_file_delete_all (core->bin);
352 		} else {
353 			ut32 id;
354 			value = r_str_trim_head_ro (input + 2);
355 			if (!value) {
356 				eprintf ("Invalid argument\n");
357 				break;
358 			}
359 			id = (*value && r_is_valid_input_num_value (core->num, value)) ?
360 					r_get_input_num_value (core->num, value) : UT32_MAX;
361 			RBinFile *bf = r_bin_file_find_by_id (core->bin, id);
362 			if (!bf) {
363 				eprintf ("Invalid binid\n");
364 				break;
365 			}
366 			if (!r_core_bin_delete (core, bf->id)) {
367 				eprintf ("Cannot find an RBinFile associated with that id.\n");
368 			}
369 		}
370 		break;
371 	case '=': // "ob="
372 		{
373 			RListIter *iter;
374 			RList *list = r_list_newf ((RListFree) r_listinfo_free);
375 			RBinFile *bf = NULL;
376 			RBin *bin = core->bin;
377 			if (!bin) {
378 				return;
379 			}
380 			r_list_foreach (bin->binfiles, iter, bf) {
381 				char temp[4];
382 				RInterval inter = (RInterval) {bf->o->baddr, bf->o->size};
383 				RListInfo *info = r_listinfo_new (bf->file, inter, inter, -1,  sdb_itoa (bf->fd, temp, 10));
384 				if (!info) {
385 					break;
386 				}
387 				r_list_append (list, info);
388 			}
389 			RTable *table = r_core_table (core, "bins");
390 			r_table_visual_list (table, list, core->offset, core->blocksize,
391 				r_cons_get_size (NULL), r_config_get_i (core->config, "scr.color"));
392 			char *table_text = r_table_tostring (table);
393 			if (table_text) {
394 				r_cons_printf ("\n%s\n", table_text);
395 				r_free (table_text);
396 			}
397 			r_table_free (table);
398 			r_list_free (list);
399 		} break;
400 	case '?': // "ob?"
401 		r_core_cmd_help (core, help_msg_ob);
402 		break;
403 	}
404 }
405 
406 // TODO: discuss the output format
map_list(RIO * io,int mode,RPrint * print,int fd)407 static void map_list(RIO *io, int mode, RPrint *print, int fd) {
408 	r_return_if_fail (io && print && print->cb_printf);
409 	PJ *pj = NULL;
410 	if (mode == 'j') {
411 		pj = pj_new ();
412 		if (!pj) {
413 			return;
414 		}
415 		pj_a (pj);
416 	}
417 	char *om_cmds = NULL;
418 
419 	void **it;
420 	r_pvector_foreach_prev (&io->maps, it) { //this must be prev (LIFO)
421 		RIOMap *map = *it;
422 		if (fd >= 0 && map->fd != fd) {
423 			continue;
424 		}
425 		switch (mode) {
426 		case 'q':
427 			if (fd == -2) {
428 				print->cb_printf ("0x%08"PFMT64x"\n", r_io_map_begin (map));
429 			} else {
430 				print->cb_printf ("%d %d\n", map->fd, map->id);
431 			}
432 			break;
433 		case 'j':
434 			pj_o (pj);
435 			pj_ki (pj, "map", map->id);
436 			pj_ki (pj, "fd", map->fd);
437 			pj_kn (pj, "delta", map->delta);
438 			pj_kn (pj, "from", r_io_map_begin (map));
439 			pj_kn (pj, "to", r_io_map_end (map));
440 			pj_ks (pj, "perm", r_str_rwx_i (map->perm));
441 			pj_ks (pj, "name", r_str_get (map->name));
442 			pj_end (pj);
443 			break;
444 		case 1:
445 		case '*':
446 		case 'r': {
447 			// Need FIFO order here
448 			char *om_cmd = r_str_newf ("om %d 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" %s%s%s\n",
449 					map->fd, r_io_map_begin (map), r_io_map_size (map), map->delta, r_str_rwx_i (map->perm),
450 					R_STR_ISEMPTY (map->name)? "" : " ", r_str_get (map->name));
451 			if (om_cmd) {
452 				om_cmds = r_str_prepend (om_cmds, om_cmd);
453 				free (om_cmd);
454 			}
455 			break;
456 		}
457 		default:
458 			print->cb_printf ("%2d fd: %i +0x%08"PFMT64x" 0x%08"PFMT64x
459 					" - 0x%08"PFMT64x" %s %s\n", map->id, map->fd,
460 					map->delta, r_io_map_begin (map), r_io_map_to (map),
461 					r_str_rwx_i (map->perm), r_str_get (map->name));
462 			break;
463 		}
464 	}
465 	if (om_cmds) {
466 		print->cb_printf ("%s", om_cmds);
467 		free (om_cmds);
468 	}
469 	if (mode == 'j') {
470 		pj_end (pj);
471 		print->cb_printf ("%s\n", pj_string (pj));
472 		pj_free (pj);
473 	}
474 }
475 
cmd_omfg(RCore * core,const char * input)476 static void cmd_omfg(RCore *core, const char *input) {
477 	input = r_str_trim_head_ro (input);
478 	if (input) {
479 		int perm = *input
480 		? (*input == '+' || *input == '-')
481 			? r_str_rwx (input + 1)
482 			: r_str_rwx (input)
483 		: 7;
484 		void **it;
485 		switch (*input) {
486 		case '+':
487 			r_pvector_foreach (&core->io->maps, it) {
488 				RIOMap *map = *it;
489 				map->perm |= perm;
490 			}
491 			break;
492 		case '-':
493 			r_pvector_foreach (&core->io->maps, it) {
494 				RIOMap *map = *it;
495 				map->perm &= ~perm;
496 			}
497 			break;
498 		default:
499 			r_pvector_foreach (&core->io->maps, it) {
500 				RIOMap *map = *it;
501 				map->perm = perm;
502 			}
503 			break;
504 		}
505 	}
506 }
507 
cmd_omf(RCore * core,const char * input)508 static void cmd_omf(RCore *core, const char *input) {
509 	char *arg = strdup (r_str_trim_head_ro (input));
510 	if (!arg) {
511 		return;
512 	}
513 	char *sp = strchr (arg, ' ');
514 	if (sp) {
515 		// change perms of Nth map
516 		*sp++ = 0;
517 		int id = r_num_math (core->num, arg);
518 		int perm = (*sp)? r_str_rwx (sp): R_PERM_RWX;
519 		void **it;
520 		r_pvector_foreach (&core->io->maps, it) {
521 			RIOMap *map = *it;
522 			if (map->id == id) {
523 				map->perm = perm;
524 				break;
525 			}
526 		}
527 	} else {
528 		// change perms of current map
529 		int perm = (arg && *arg)? r_str_rwx (arg): R_PERM_RWX;
530 		void **it;
531 		r_pvector_foreach (&core->io->maps, it) {
532 			RIOMap *map = *it;
533 			if (r_io_map_contain (map, core->offset)) {
534 				map->perm = perm;
535 			}
536 		}
537 	}
538 	free (arg);
539 }
540 
r_core_cmd_omt(RCore * core,const char * arg)541 static void r_core_cmd_omt(RCore *core, const char *arg) {
542 	RTable *t = r_table_new ("iomaps");
543 
544 	r_table_set_columnsf (t, "nnnnnnnss", "id", "fd", "pa", "pa_end", "size", "va", "va_end", "perm", "name", NULL);
545 
546 	void **it;
547 	r_pvector_foreach (&core->io->maps, it) {
548 		RIOMap *m = *it;
549 		ut64 va = r_itv_begin (m->itv);
550 		ut64 va_end = r_itv_end (m->itv);
551 		ut64 pa = m->delta;
552 		ut64 pa_size = r_itv_size (m->itv);
553 		ut64 pa_end = pa + pa_size;
554 		const char *name = r_str_get (m->name);
555 		r_table_add_rowf (t, "ddxxxxxss", m->id, m->fd, pa, pa_end, pa_size, va, va_end, r_str_rwx_i (m->perm), name);
556 	}
557 
558 	if (r_table_query (t, arg)) {
559 		char *ts = r_table_tofancystring (t);
560 		r_cons_printf ("%s", ts);
561 		free (ts);
562 	}
563 	r_table_free (t);
564 }
565 
cmd_om(RCore * core,const char * input)566 static bool cmd_om(RCore *core, const char *input) {
567 	char *s = strdup (input + 2);
568 	if (!s) {
569 		return false;
570 	}
571 	if (strchr (s, ' ')) {
572 		int fd = 0, rwx = 0;
573 		ut64 size = 0, vaddr = 0, paddr = 0;
574 		const char *name = NULL;
575 		bool rwx_arg = false;
576 		RIODesc *desc = NULL;
577 		int words = r_str_word_set0 (s);
578 		switch (words) {
579 		case 6:
580 			name = r_str_word_get0 (s, 5);
581 			// fallthrough
582 		case 5:
583 			rwx = r_str_rwx (r_str_word_get0 (s, 4));
584 			rwx_arg = true;
585 			// fallthrough
586 		case 4:
587 			paddr = r_num_math (core->num, r_str_word_get0 (s, 3));
588 			// fallthrough
589 		case 3:
590 			size = r_num_math (core->num, r_str_word_get0 (s, 2));
591 			// fallthrough
592 		case 2:
593 			vaddr = r_num_math (core->num, r_str_word_get0 (s, 1));
594 			// fallthrough
595 		case 1:
596 			fd = r_num_math (core->num, r_str_word_get0 (s, 0));
597 			break;
598 		}
599 		if (fd < 3) {
600 			eprintf ("wrong fd, it must be greater than 3\n");
601 			return false;
602 		}
603 		desc = r_io_desc_get (core->io, fd);
604 		if (desc) {
605 			if (!size) {
606 				size = r_io_fd_size (core->io, fd);
607 			}
608 			RIOMap *map = r_io_map_add (core->io, fd, rwx_arg ? rwx : desc->perm, paddr, vaddr, size);
609 			if (map) {
610 				if (name) {
611 					r_io_map_set_name (map, name);
612 				}
613 			} else {
614 				eprintf ("Cannot add map.\n");
615 			}
616 		}
617 	} else {
618 		int fd = r_io_fd_get_current (core->io);
619 		if (r_io_desc_get (core->io, fd)) {
620 			map_list (core->io, 0, core->print, fd);
621 		} else {
622 			eprintf ("Invalid fd %d\n", (int)fd);
623 		}
624 	}
625 	free (s);
626 	return true;
627 }
628 
cmd_open_map(RCore * core,const char * input)629 static void cmd_open_map(RCore *core, const char *input) {
630 	ut64 fd = 0LL;
631 	ut32 id = 0;
632 	ut64 addr = 0;
633 	char *s = NULL, *p = NULL, *q = NULL;
634 	ut64 new;
635 	RIOMap *map = NULL;
636 	const char *P;
637 	PJ *pj;
638 
639 	switch (input[1]) {
640 	case '.': // "om."
641 		map = r_io_map_get (core->io, core->offset);
642 		if (map) {
643 			if (input[2] == 'j') { // "om.j"
644 				pj = pj_new ();
645 				if (!pj) {
646 					return;
647 				}
648 				pj_o (pj);
649 				pj_ki (pj, "map", map->id);
650 				pj_ki (pj, "fd", map->fd);
651 				pj_kn (pj, "delta", map->delta);
652 				pj_kn (pj, "from", r_io_map_begin (map));
653 				pj_kn (pj, "to", r_io_map_end (map));
654 				pj_ks (pj, "perm", r_str_rwx_i (map->perm));
655 				pj_ks (pj, "name", r_str_get (map->name));
656 				pj_end (pj);
657 
658 				core->print->cb_printf ("%s\n", pj_string (pj));
659 
660 				pj_free (pj);
661 			} else {
662 				core->print->cb_printf ("%2d fd: %i +0x%08"PFMT64x" 0x%08"PFMT64x
663 					" - 0x%08"PFMT64x" %s %s\n", map->id, map->fd,
664 					map->delta, r_io_map_begin (map), r_io_map_to (map),
665 					r_str_rwx_i (map->perm), r_str_get (map->name));
666 			}
667 		}
668 		break;
669 	case 'r': // "omr"
670 		if (input[2] != ' ') {
671 			break;
672 		}
673 		P = strchr (input+3, ' ');
674 		if (P) {
675 			id = (ut32)r_num_math (core->num, input+3);	//mapid
676 			new = r_num_math (core->num, P+1);
677 			r_io_map_resize (core->io, id, new);
678 		}
679 		break;
680 	case 'b': // "omb"
681 		if (input[2] == '.') {
682 			RIOMap *map = r_io_map_get (core->io, core->offset);
683 			if (map) {
684 				ut64 dst = r_num_math (core->num, input + 3);
685 				r_io_map_remap (core->io, map->id, dst);
686 			}
687 		} else {
688 			if (input[2] != ' ') {
689 				break;
690 			}
691 			P = strchr (input + 3, ' ');
692 			if (P) {
693 				id = (ut32)r_num_math (core->num, input+3);	//mapid
694 				new = r_num_math (core->num, P + 1);
695 				r_io_map_remap (core->io, id, new);
696 			}
697 		}
698 		break;
699 	case 'o': // "omo"
700 		if (input[2] == ' ') {
701 			r_core_cmdf (core, "om %s 0x%08" PFMT64x " $s r omo", input + 2, core->offset);
702 		} else {
703 			r_core_cmd0 (core, "om `oq.` $B $s r");
704 		}
705 		r_core_cmd0 (core, "ompd `omq.`");
706 		break;
707 	case 'p':
708 		switch (input[2]) {
709 		case 'd': // "ompf"
710 			id = r_num_math (core->num, input + 3);		//mapid
711 			if (r_io_map_exists_for_id (core->io, id)) {
712 				r_io_map_depriorize (core->io, id);
713 			} else {
714 				eprintf ("Cannot find any map with mapid %d\n", id);
715 			}
716 			break;
717 		case 'f': // "ompf"
718 			fd = r_num_math (core->num, input + 3);
719 			if (!r_io_map_priorize_for_fd (core->io, (int)fd)) {
720 				eprintf ("Cannot prioritize any map for fd %d\n", (int)fd);
721 			}
722 			break;
723 		case 'b': // "ompb"
724 			id = (ut32)r_num_math (core->num, input + 4);
725 			if (!r_bin_file_set_cur_by_id (core->bin, id)) {
726 				eprintf ("Cannot prioritize bin with fd %d\n", id);
727 			}
728 			break;
729 		case ' ': // "omp"
730 			id = r_num_math (core->num, input + 3);		//mapid
731 			if (r_io_map_exists_for_id (core->io, id)) {
732 				r_io_map_priorize (core->io, id);
733 				r_core_block_read (core);
734 			} else {
735 				eprintf ("Cannot find any map with mapid %d\n", id);
736 			}
737 			break;
738 		}
739 		break;
740 	case 't': // "omt"
741 		r_core_cmd_omt (core, input + 2);
742 		break;
743 	case ' ': // "om"
744 		cmd_om (core, input);
745 		break;
746 	case 'n': // "omn"
747 		if (input[2] == '.') { // "omn."
748 			RIOMap *map = r_io_map_get (core->io, core->offset);
749 			if (map) {
750 				switch (input[3]) {
751 				case '-':
752 					r_io_map_del_name (map);
753 					break;
754 				case 0:
755 					r_cons_printf ("%s\n", map->name);
756 					break;
757 				default:
758 					r_io_map_set_name (map, r_str_trim_head_ro (input + 3));
759 					break;
760 				}
761 			}
762 		} else {
763 			bool use_id = (input[2] == 'i') ? true : false;
764 			s = strdup ( use_id ? &input[3] : &input[2]);
765 			if (!s) {
766 				break;
767 			}
768 			p = s;
769 
770 			while (*s == ' ') {
771 				s++;
772 			}
773 			if (*s == '\0') {
774 				s = p;
775 				break;
776 			}
777 			if (!(q = strchr (s, ' '))) {
778 				if (use_id) {
779 					id = (ut32)r_num_math (core->num, s);
780 					map = r_io_map_resolve (core->io, id);
781 				} else {
782 					addr = r_num_math (core->num, s);
783 					map = r_io_map_get (core->io, addr);
784 				}
785 				r_io_map_del_name (map);
786 				s = p;
787 				break;
788 			}
789 			*q = '\0';
790 			q++;
791 			if (use_id) {
792 				id = (ut32)r_num_math (core->num, s);
793 				map = r_io_map_resolve (core->io, id);
794 			} else {
795 				addr = r_num_math (core->num, s);
796 				map = r_io_map_get (core->io, addr);
797 			}
798 			if (map) {
799 				if (*q) {
800 					r_io_map_set_name (map, q);
801 				} else {
802 					r_io_map_del_name (map);
803 				}
804 			}
805 			s = p;
806 		}
807 		break;
808 	case 'a': // "oma"
809 		{
810 			ut32 fd = input[2]? r_num_math (core->num, input + 2): r_io_fd_get_current (core->io);
811 			RIODesc *desc = r_io_desc_get (core->io, fd);
812 			if (desc) {
813 				map = r_io_map_add (core->io, fd, desc->perm, 0, 0, UT64_MAX);
814 				if (map) {
815 					r_io_map_set_name (map, desc->name);
816 				}
817 			} else {
818 				eprintf ("Usage: omm [fd]\n");
819 			}
820 		}
821 		break;
822 	case 'm': // "omm"
823 		{
824 			ut32 fd = input[2]? r_num_math (core->num, input + 2): r_io_fd_get_current (core->io);
825 			RIODesc *desc = r_io_desc_get (core->io, fd);
826 			if (desc) {
827 				ut64 size = r_io_desc_size (desc);
828 				map = r_io_map_add (core->io, fd, desc->perm, 0, 0, size);
829 				if (map && desc->name) {
830 					r_io_map_set_name (map, desc->name);
831 				}
832 			} else {
833 				eprintf ("Usage: omm [fd]\n");
834 			}
835 		}
836 		break;
837 	case '-': // "om-"
838 		if (!strcmp (input + 2, "..")) {
839 			r_core_cmd0 (core, "om-`om~...`~[0]");
840 		} else if (input[2] == '*') {
841 			r_io_map_reset (core->io);
842 		} else {
843 			r_io_map_del (core->io, r_num_math (core->num, input + 2));
844 		}
845 		break;
846 	case 'f': // "omf"
847 		switch (input[2]) {
848 		case 'g': // "omfg"
849 			cmd_omfg (core, input + 3);
850 			break;
851 		case ' ': // "omf"
852 			cmd_omf (core, input + 3);
853 			break;
854 		default:
855 			r_core_cmd_help (core, help_msg_om);
856 			break;
857 		}
858 		break;
859 	case '\0': // "om"
860 	case 'j': // "omj"
861 	case '*': // "om*"
862 	case 'q': // "omq"
863 		if (input[1] && input[2] == '.') {
864 			map = r_io_map_get (core->io, core->offset);
865 			if (map) {
866 				core->print->cb_printf ("%i\n", map->id);
867 			}
868 		} else {
869 			if (input[1] && input[2] == 'q') { // "omqq"
870 				map_list (core->io, input[1], core->print, -2);
871 			} else {
872 				map_list (core->io, input[1], core->print, -1);
873 			}
874 		}
875 		break;
876 	case '=': // "om="
877 		{
878 		RList *list = r_list_newf ((RListFree) r_listinfo_free);
879 		if (!list) {
880 			return;
881 		}
882 		void **it;
883 		r_pvector_foreach_prev (&core->io->maps, it) {
884 			RIOMap *map = *it;
885 			char temp[32];
886 			snprintf (temp, sizeof (temp), "%d", map->fd);
887 			RListInfo *info = r_listinfo_new (map->name, map->itv, map->itv, map->perm, temp);
888 			if (!info) {
889 				break;
890 			}
891 			r_list_append (list, info);
892 		}
893 		RTable *table = r_core_table (core, "maps");
894 		r_table_visual_list (table, list, core->offset, core->blocksize,
895 			r_cons_get_size (NULL), r_config_get_i (core->config, "scr.color"));
896 		char *tablestr = r_table_tostring (table);
897 		r_cons_printf ("\n%s\n", tablestr);
898 		r_table_free (table);
899 		r_list_free (list);
900 		free (tablestr);
901 		} break;
902 	default:
903 	case '?':
904 		r_core_cmd_help (core, help_msg_om);
905 		break;
906 	}
907 	R_FREE (s);
908 	r_core_block_read (core);
909 }
910 
reopen_in_malloc_cb(void * user,void * data,ut32 id)911 static bool reopen_in_malloc_cb(void *user, void *data, ut32 id) {
912 	RIO *io = (RIO *)user;
913 	RIODesc *desc = (RIODesc *)data;
914 
915 	if (r_io_desc_is_blockdevice (desc) || r_io_desc_is_dbg (desc)) {
916 		return true;
917 	}
918 
919 	if (strstr (desc->uri, "://")) {
920 		return true;
921 	}
922 
923 	ut64 size = r_io_desc_size (desc);
924 
925 	char *uri = r_str_newf ("malloc://%"PFMT64u, size);
926 	if (!uri) {
927 		return false;
928 	}
929 
930 	ut8 *buf = malloc (size);
931 // if malloc fails, we can just abort the loop by returning false
932 	if (!buf) {
933 		free (uri);
934 		return false;
935 	}
936 
937 	RIODesc *ndesc = r_io_open_nomap (io, uri, R_PERM_RW, 0);
938 	free (uri);
939 	if (!ndesc) {
940 		free (buf);
941 		return false;
942 	}
943 
944 	r_io_desc_read_at (desc, 0LL, buf, (int)size);	//that cast o_O
945 	r_io_desc_write_at (ndesc, 0LL, buf, (int)size);
946 	free (buf);
947 	r_io_desc_exchange (io, desc->fd, ndesc->fd);
948 
949 	r_io_desc_close (desc);
950 	return true;
951 }
952 
r_core_file_reopen_in_malloc(RCore * core)953 R_API void r_core_file_reopen_in_malloc(RCore *core) {
954 	if (core && core->io && core->io->files) {
955 		r_id_storage_foreach (core->io->files, reopen_in_malloc_cb, core->io);
956 	}
957 }
958 
__save_old_sections(RCore * core)959 static RList *__save_old_sections(RCore *core) {
960 	RList *sections = r_bin_get_sections (core->bin);
961 	RListIter *it;
962 	RBinSection *sec;
963 	RList *old_sections = r_list_new ();
964 
965 	// Return an empty list
966 	if (!sections) {
967 		eprintf ("WARNING: No sections found, functions and flags won't be rebased");
968 		return old_sections;
969 	}
970 
971 	old_sections->free = sections->free;
972 	r_list_foreach (sections, it, sec) {
973 		RBinSection *old_sec = R_NEW0 (RBinSection);
974 		if (!old_sec) {
975 			break;
976 		}
977 		*old_sec = *sec;
978 		old_sec->name = strdup (sec->name);
979 		old_sec->format = NULL;
980 		r_list_append (old_sections, old_sec);
981 	}
982 	return old_sections;
983 }
984 
985 struct __rebase_struct {
986 	RCore *core;
987 	RList *old_sections;
988 	ut64 old_base;
989 	ut64 diff;
990 	int type;
991 };
992 
993 #define __is_inside_section(item_addr, section)\
994 	(item_addr >= old_base + section->vaddr && item_addr <= old_base + section->vaddr + section->vsize)
995 
__rebase_flags(RFlagItem * flag,void * user)996 static bool __rebase_flags(RFlagItem *flag, void *user) {
997 	struct __rebase_struct *reb = user;
998 	ut64 old_base = reb->old_base;
999 	RListIter *it;
1000 	RBinSection *sec;
1001 	// Only rebase flags that were in the rebased sections, otherwise it will take too long
1002 	r_list_foreach (reb->old_sections, it, sec) {
1003 		if (__is_inside_section (flag->offset, sec)) {
1004 			r_flag_set (reb->core->flags, flag->name, flag->offset + reb->diff, flag->size);
1005 			break;
1006 		}
1007 	}
1008 	return true;
1009 }
1010 
__rebase_refs_i(void * user,const ut64 k,const void * v)1011 static bool __rebase_refs_i(void *user, const ut64 k, const void *v) {
1012 	struct __rebase_struct *reb = (void *)user;
1013 	RAnalRef *ref = (RAnalRef *)v;
1014 	ref->addr += reb->diff;
1015 	ref->at += reb->diff;
1016 	if (reb->type) {
1017 		r_anal_xrefs_set (reb->core->anal, ref->addr, ref->at, ref->type);
1018 	} else {
1019 		r_anal_xrefs_set (reb->core->anal, ref->at, ref->addr, ref->type);
1020 	}
1021 	return true;
1022 }
1023 
__rebase_refs(void * user,const ut64 k,const void * v)1024 static bool __rebase_refs(void *user, const ut64 k, const void *v) {
1025 	HtUP *ht = (HtUP *)v;
1026 	ht_up_foreach (ht, __rebase_refs_i, user);
1027 	return true;
1028 }
1029 
__rebase_everything(RCore * core,RList * old_sections,ut64 old_base)1030 static void __rebase_everything(RCore *core, RList *old_sections, ut64 old_base) {
1031 	RListIter *it, *itit, *ititit;
1032 	RAnalFunction *fcn;
1033 	ut64 new_base = core->bin->cur->o->baddr_shift;
1034 	RBinSection *old_section;
1035 	ut64 diff = new_base - old_base;
1036 	if (!diff) {
1037 		return;
1038 	}
1039 	// FUNCTIONS
1040 	r_list_foreach (core->anal->fcns, it, fcn) {
1041 		r_list_foreach (old_sections, itit, old_section) {
1042 			if (!__is_inside_section (fcn->addr, old_section)) {
1043 				continue;
1044 			}
1045 				r_anal_function_rebase_vars (core->anal, fcn);
1046 			r_anal_function_relocate (fcn, fcn->addr + diff);
1047 			RAnalBlock *bb;
1048 			ut64 new_sec_addr = new_base + old_section->vaddr;
1049 			r_list_foreach (fcn->bbs, ititit, bb) {
1050 				if (bb->addr >= new_sec_addr && bb->addr <= new_sec_addr + old_section->vsize) {
1051 					// Todo: Find better way to check if bb was already rebased
1052 					continue;
1053 				}
1054 				r_anal_block_relocate (bb, bb->addr + diff, bb->size);
1055 				if (bb->jump != UT64_MAX) {
1056 					bb->jump += diff;
1057 				}
1058 				if (bb->fail != UT64_MAX) {
1059 					bb->fail += diff;
1060 				}
1061 			}
1062 			break;
1063 		}
1064 	}
1065 
1066 	// FLAGS
1067 	struct __rebase_struct reb = {
1068 		core,
1069 		old_sections,
1070 		old_base,
1071 		diff
1072 	};
1073 	r_flag_foreach (core->flags, __rebase_flags, &reb);
1074 
1075 	// META
1076 	r_meta_rebase (core->anal, diff);
1077 
1078 	// REFS
1079 	HtUP *old_refs = core->anal->dict_refs;
1080 	HtUP *old_xrefs = core->anal->dict_xrefs;
1081 	core->anal->dict_refs = NULL;
1082 	core->anal->dict_xrefs = NULL;
1083 	r_anal_xrefs_init (core->anal);
1084 	reb.type = 0;
1085 	ht_up_foreach (old_refs, __rebase_refs, &reb);
1086 	reb.type = 1;
1087 	ht_up_foreach (old_xrefs, __rebase_refs, &reb);
1088 	ht_up_free (old_refs);
1089 	ht_up_free (old_xrefs);
1090 
1091 	// BREAKPOINTS
1092 	r_debug_bp_rebase (core->dbg, old_base, new_base);
1093 }
1094 
r_core_file_reopen_remote_debug(RCore * core,char * uri,ut64 addr)1095 R_API void r_core_file_reopen_remote_debug(RCore *core, char *uri, ut64 addr) {
1096 	RIODesc *desc = core->io->desc;
1097 	RIODesc *file;
1098 	int fd;
1099 
1100 	if (!desc || !desc->uri) {
1101 		eprintf ("No file open?\n");
1102 		return;
1103 	}
1104 
1105 	RList *old_sections = __save_old_sections (core);
1106 	ut64 old_base = core->bin->cur->o->baddr_shift;
1107 	int bits = core->rasm->bits;
1108 	r_config_set_i (core->config, "asm.bits", bits);
1109 	r_config_set_b (core->config, "cfg.debug", true);
1110 	// Set referer as the original uri so we could return to it with `oo`
1111 	desc->referer = desc->uri;
1112 	desc->uri = strdup (uri);
1113 
1114 	if ((file = r_core_file_open (core, uri, R_PERM_RW, addr))) {
1115 		fd = file->fd;
1116 		core->num->value = fd;
1117 		// if no baddr is defined, use the one provided by the file
1118 		if (addr == 0) {
1119 			desc = r_io_desc_get (core->io, file->fd);
1120 			if (desc->plugin->isdbg) {
1121 				addr = r_debug_get_baddr (core->dbg, desc->name);
1122 			} else {
1123 				addr = r_bin_get_baddr (core->bin);
1124 			}
1125 		}
1126 		r_core_bin_load (core, uri, addr);
1127 	} else {
1128 		eprintf ("cannot open file %s\n", uri);
1129 		r_list_free (old_sections);
1130 		return;
1131 	}
1132 	r_core_block_read (core);
1133 	if (r_config_get_i (core->config, "dbg.rebase")) {
1134 		__rebase_everything (core, old_sections, old_base);
1135 	}
1136 	r_list_free (old_sections);
1137 	r_core_cmd0 (core, "sr PC");
1138 }
1139 
r_core_file_reopen_debug(RCore * core,const char * args)1140 R_API void r_core_file_reopen_debug(RCore *core, const char *args) {
1141 	RIODesc *desc = core->io->desc;
1142 
1143 	if (!desc || !desc->uri) {
1144 		eprintf ("No file open?\n");
1145 		return;
1146 	}
1147 
1148 	// Reopen the original file as read only since we can't open native debug while the
1149 	// file is open with write permissions
1150 	if (!(desc->plugin && desc->plugin->isdbg) && (desc->perm & R_PERM_W)) {
1151 		eprintf ("Cannot debug file (%s) with permissions set to 0x%x.\n"
1152 			"Reopening the original file in read-only mode.\n", desc->name, desc->perm);
1153 		int fd = desc->fd;
1154 		r_io_reopen (core->io, fd, R_PERM_RX, 755);
1155 		desc = r_io_desc_get (core->io, fd);
1156 	}
1157 
1158 	RBinFile *bf = r_bin_file_find_by_fd (core->bin, desc->fd);
1159 	char *binpath = (bf && bf->file) ? strdup (bf->file) : NULL;
1160 	if (!binpath) {
1161 		if (r_file_exists (desc->name)) {
1162 			binpath = strdup (desc->name);
1163 		}
1164 	}
1165 	if (!binpath) {
1166 		/* fallback to oo */
1167 		(void)r_core_cmd0 (core, "oo");
1168 		return;
1169 	}
1170 
1171 	RList *old_sections = __save_old_sections (core);
1172 	ut64 old_base = core->bin->cur->o->baddr_shift;
1173 	int bits = core->rasm->bits;
1174 	char *bin_abspath = r_file_abspath (binpath);
1175 	char *escaped_path = r_str_arg_escape (bin_abspath);
1176 	char *newfile = r_str_newf ("dbg://%s %s", escaped_path, args);
1177 	desc->uri = newfile;
1178 	desc->referer = NULL;
1179 	r_config_set_i (core->config, "asm.bits", bits);
1180 	r_config_set_b (core->config, "cfg.debug", true);
1181 	r_core_file_reopen (core, newfile, 0, 2);
1182 	if (r_config_get_i (core->config, "dbg.rebase")) {
1183 		__rebase_everything (core, old_sections, old_base);
1184 	}
1185 	r_list_free (old_sections);
1186 	r_core_cmd0 (core, "sr PC");
1187 	free (bin_abspath);
1188 	free (escaped_path);
1189 	free (binpath);
1190 }
1191 
1192 static int fdsz = 0;
1193 
init_desc_list_visual_cb(void * user,void * data,ut32 id)1194 static bool init_desc_list_visual_cb(void *user, void *data, ut32 id) {
1195 	RIODesc *desc = (RIODesc *)data;
1196 	ut64 sz = r_io_desc_size (desc);
1197 	if (sz > fdsz) {
1198 		fdsz = sz;
1199 	}
1200 	return true;
1201 }
1202 
desc_list_visual_cb(void * user,void * data,ut32 id)1203 static bool desc_list_visual_cb(void *user, void *data, ut32 id) {
1204 	RPrint *p = (RPrint *)user;
1205 	RIODesc *desc = (RIODesc *)data;
1206 	ut64 sz = r_io_desc_size (desc);
1207 	r_cons_printf ("%2d %c %s 0x%08"PFMT64x" ", desc->fd,
1208 			(desc->io && (desc->io->desc == desc)) ? '*' : '-', r_str_rwx_i (desc->perm), sz);
1209 	int flags = p->flags;
1210 	p->flags &= ~R_PRINT_FLAGS_HEADER;
1211 	r_print_progressbar (p, sz * 100 / fdsz, r_cons_get_size (NULL) - 40);
1212 	p->flags = flags;
1213 	r_cons_printf (" %s\n", desc->uri);
1214 #if 0
1215 	RIOMap *map;
1216 	SdbListIter *iter;
1217 	if (desc->io && desc->io->va && desc->io->maps) {
1218 		ls_foreach_prev (desc->io->maps, iter, map) {
1219 			if (map->fd == desc->fd) {
1220 				p->cb_printf ("  +0x%"PFMT64x" 0x%"PFMT64x
1221 					" - 0x%"PFMT64x" : %s : %s : %s\n", map->delta,
1222 					map->from, map->to, r_str_rwx_i (map->flags), "",
1223 					r_str_get (map));
1224 			}
1225 		}
1226 	}
1227 #endif
1228 	return true;
1229 }
1230 
desc_list_quiet2_cb(void * user,void * data,ut32 id)1231 static bool desc_list_quiet2_cb(void *user, void *data, ut32 id) {
1232 	RPrint *p = (RPrint *)user;
1233 	RIODesc *desc = (RIODesc *)data;
1234 	p->cb_printf ("%d\n", desc->fd);
1235 	return false;
1236 }
1237 
desc_list_quiet_cb(void * user,void * data,ut32 id)1238 static bool desc_list_quiet_cb(void *user, void *data, ut32 id) {
1239 	RPrint *p = (RPrint *)user;
1240 	RIODesc *desc = (RIODesc *)data;
1241 	p->cb_printf ("%d\n", desc->fd);
1242 	return true;
1243 }
1244 
desc_list_cmds_cb(void * user,void * data,ut32 id)1245 static bool desc_list_cmds_cb(void *user, void *data, ut32 id) {
1246 	RCore *core = (RCore *)user;
1247 	RPrint *p = core->print;
1248 	RIODesc *desc = (RIODesc *)data;
1249 	RBinFile *bf = r_bin_file_find_by_fd (core->bin, desc->fd);
1250 	if (bf) {
1251 		p->cb_printf ("o %s 0x%08"PFMT64x" %s\n", desc->uri, bf->o->baddr, r_str_rwx_i (desc->perm));
1252 	} else {
1253 		p->cb_printf ("onn %s %s\n", desc->uri, r_str_rwx_i (desc->perm));
1254 	}
1255 	if (strstr (desc->uri, "null://")) {
1256 		// null descs dont want to be mapped
1257 		return true;
1258 	}
1259 
1260 	RList *list = r_bin_get_sections (core->bin);
1261 	RList *maps = r_io_map_get_for_fd (core->io, desc->fd);
1262 	RListIter *iter, *iter2;
1263 	RBinSection *sec;
1264 	RIOMap *map;
1265 	r_list_foreach (maps, iter, map) {
1266 		bool map_from_bin = false;
1267 		r_list_foreach (list, iter2, sec) {
1268 			if (sec->is_segment) {
1269 				if (sec->vaddr == map->itv.addr && sec->size == map->itv.size) {
1270 					map_from_bin = true;
1271 					break;
1272 				}
1273 			}
1274 		}
1275 		if (!map_from_bin) {
1276 			// ut64 paddr = 0; // map->itv.addr;
1277 			ut64 paddr = map->itv.addr;
1278 			if (paddr == map->itv.addr) {
1279 				paddr = 0;
1280 			}
1281 			ut64 vaddr = map->itv.addr + map->delta;
1282 			ut64 vsize = map->itv.size;
1283 			p->cb_printf ("om $d 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" %s %s\n",
1284 				vaddr, vsize, paddr, r_str_rwx_i (map->perm), r_str_get (map->name));
1285 		}
1286 	}
1287 	return true;
1288 }
desc_list_cb(void * user,void * data,ut32 id)1289 static bool desc_list_cb(void *user, void *data, ut32 id) {
1290 	RPrint *p = (RPrint *)user;
1291 	RIODesc *desc = (RIODesc *)data;
1292 	p->cb_printf ("%2d %c %s 0x%08"PFMT64x" %s\n", desc->fd,
1293 			(desc->io && (desc->io->desc == desc)) ? '*' : '-',
1294 			r_str_rwx_i (desc->perm), r_io_desc_size (desc), desc->uri);
1295 	return true;
1296 }
1297 
desc_list_json_cb(void * user,void * data,ut32 id)1298 static bool desc_list_json_cb(void *user, void *data, ut32 id) {
1299 	PJ *pj = (PJ *)user;
1300 	RIODesc *desc = (RIODesc *)data;
1301 	// TODO: from is always 0? See libr/core/file.c:945
1302 	ut64 from = 0LL;
1303 	pj_o (pj);
1304 	pj_kb (pj, "raised", desc->io && (desc->io->desc == desc));
1305 	pj_kN (pj, "fd", desc->fd);
1306 	pj_ks (pj, "uri", desc->uri);
1307 	pj_kn (pj, "from", from);
1308 	pj_kb (pj, "writable", desc->perm & R_PERM_W);
1309 	pj_kN (pj, "size", r_io_desc_size (desc));
1310 	pj_end (pj);
1311 	return true;
1312 }
1313 
cmd_op(RCore * core,char mode,int fd)1314 static bool cmd_op(RCore *core, char mode, int fd) {
1315 	int cur_fd = r_io_fd_get_current (core->io);
1316 	int next_fd = cur_fd;
1317 	switch (mode) {
1318 	case 0:
1319 		next_fd = fd;
1320 		break;
1321 	case 'n':
1322 		next_fd = r_io_fd_get_next (core->io, cur_fd);
1323 		break;
1324 	case 'p':
1325 		next_fd = r_io_fd_get_prev (core->io, cur_fd);
1326 		break;
1327 	case 'r':
1328 		next_fd = r_io_fd_get_next (core->io, cur_fd);
1329 		if (next_fd == -1) {
1330 			next_fd = r_io_fd_get_lowest (core->io);
1331 		}
1332 		break;
1333 	}
1334 	if (next_fd >= 0 && next_fd != cur_fd && r_io_use_fd (core->io, next_fd)) {
1335 		RBinFile *bf = r_bin_file_find_by_fd (core->bin, next_fd);
1336 		if (bf && r_core_bin_raise (core, bf->id)) {
1337 			r_core_block_read (core);
1338 			return true;
1339 		}
1340 		eprintf ("Invalid RBinFile.id number.\n");
1341 	}
1342 	return false;
1343 }
1344 
cmd_onn(RCore * core,const char * input)1345 static bool cmd_onn(RCore *core, const char* input) {
1346 	char *ptr = r_str_trim_dup (input + 2);
1347 	int perms = R_PERM_R;
1348 	char *arg_perm = strchr (ptr, ' ');
1349 	if (arg_perm) {
1350 		*arg_perm++ = 0;
1351 		perms = r_str_rwx (arg_perm);
1352 	}
1353 	ut64 addr = 0LL;
1354 	RIODesc *desc = r_io_open_at (core->io, ptr, perms, 0644, addr);
1355 	if (!desc || desc->fd == -1) {
1356 		eprintf ("Cannot open file '%s'\n", ptr);
1357 		free (ptr);
1358 		return false;
1359 	}
1360 	RList *maps = r_io_map_get_for_fd (core->io, desc->fd);
1361 	if (maps) {
1362 		RIOMap *map;
1363 		RListIter *iter;
1364 		r_list_foreach (maps, iter, map) {
1365 			r_io_map_del (core->io, map->id);
1366 		}
1367 		r_list_free (maps);
1368 	}
1369 	free (ptr);
1370 	return true;
1371 }
1372 
cmd_open(void * data,const char * input)1373 static int cmd_open(void *data, const char *input) {
1374 	RCore *core = (RCore*)data;
1375 	int perms = R_PERM_R;
1376 	ut64 baddr = r_config_get_i (core->config, "bin.baddr");
1377 	ut64 addr = 0LL;
1378 	int argc, fd = -1;
1379 	RIODesc *file;
1380 	RIODesc *desc;
1381 	bool write = false;
1382 	const char *ptr = NULL;
1383 	char **argv = NULL;
1384 
1385 	switch (*input) {
1386 	case 'a':
1387 		switch (input[1]) {
1388 		case '*': // "oa*"
1389 			{
1390 				RListIter *iter;
1391 				RBinFile *bf = NULL;
1392 				r_list_foreach (core->bin->binfiles, iter, bf) {
1393 					if (bf && bf->o && bf->o->info) {
1394 						eprintf ("oa %s %d %s\n", bf->o->info->arch, bf->o->info->bits, bf->file);
1395 					}
1396 				}
1397 				return 1;
1398 			}
1399 		case '?': // "oa?"
1400 		case ' ': // "oa "
1401 			{
1402 				int i;
1403 				char *ptr = strdup (input+2);
1404 				const char *arch = NULL;
1405 				ut16 bits = 0;
1406 				const char *filename = NULL;
1407 				i = r_str_word_set0 (ptr);
1408 				if (i < 2) {
1409 					eprintf ("Missing argument\n");
1410 					free (ptr);
1411 					return 0;
1412 				}
1413 				if (i == 3) {
1414 					filename = r_str_word_get0 (ptr, 2);
1415 				}
1416 				bits = r_num_math (core->num, r_str_word_get0 (ptr, 1));
1417 				arch = r_str_word_get0 (ptr, 0);
1418 				r_core_bin_set_arch_bits (core, filename, arch, bits);
1419 				RBinFile *file = r_bin_file_find_by_name (core->bin, filename);
1420 				if (!file) {
1421 					eprintf ("Cannot find file %s\n", filename);
1422 					free (ptr);
1423 					return 0;
1424 				}
1425 				if (file->o && file->o->info) {
1426 					file->o->info->arch = strdup(arch);
1427 					file->o->info->bits = bits;
1428 					r_core_bin_set_env (core, file);
1429 				}
1430 				free (ptr);
1431 				return 1;
1432 			}
1433 		break;
1434 		default:
1435 			eprintf ("Usage: oa[-][arch] [bits] [filename]\n");
1436 			return 0;
1437 	}
1438 	case 'n': // "on"
1439 		if (input[1] == 'n') {
1440 			cmd_onn (core, input);
1441 			return 0;
1442 		}
1443 		if (input[1] == '*') {
1444 			eprintf ("OTDO%c", 10); // r_core_file_list (core, 'n');
1445 			return 0;
1446 		}
1447 		if (input[1] == '+') { // "on+"
1448 			write = true;
1449 			perms |= R_PERM_W;
1450 			if (input[2] != ' ') {
1451 				eprintf ("Usage: on+ file [addr] [rwx]\n");
1452 				return 0;
1453 			}
1454 			ptr = input + 3;
1455 		} else if (input[1] == ' ') {
1456 			ptr = input + 2;
1457 		} else {
1458 			eprintf ("Usage: on file [addr] [rwx]\n");
1459 			return 0;
1460 		}
1461 		argv = r_str_argv (ptr, &argc);
1462 		if (!argc) {
1463 			eprintf ("Usage: on%s file [addr] [rwx]\n", write?"+":"");
1464 			r_str_argv_free (argv);
1465 			return 0;
1466 		}
1467 		ptr = argv[0];
1468 		if (argc == 2) {
1469 			if (r_num_is_valid_input (core->num, argv[1])) {
1470 				addr = r_num_math (core->num, argv[1]);
1471 			} else {
1472 				perms = r_str_rwx (argv[1]);
1473 			}
1474 		}
1475 		if (argc == 3) {
1476 			addr = r_num_math (core->num, argv[1]);
1477 			perms = r_str_rwx (argv[2]);
1478 		}
1479 		if (!strcmp (ptr, "-")) {
1480 			ptr = "malloc://512";
1481 		}
1482 		if ((desc = r_io_open_at (core->io, ptr, perms, 0644, addr))) {
1483 			fd = desc->fd;
1484 		}
1485 		if (fd == -1) {
1486 			eprintf ("Cannot open file '%s'\n", ptr);
1487 		}
1488 		r_str_argv_free (argv);
1489 		core->num->value = fd;
1490 		r_core_block_read (core);
1491 		return 0;
1492 	// XXX projects use the of command, but i think we should deprecate it... keeping it for now
1493 	case 'f': // "of"
1494 		ptr = r_str_trim_head_ro (input + 2);
1495 		argv = r_str_argv (ptr, &argc);
1496 		if (argc == 0) {
1497 			eprintf ("Usage: of [filename] (rwx)\n");
1498 			r_str_argv_free (argv);
1499 			return 0;
1500 		} else if (argc == 2) {
1501 			perms = r_str_rwx (argv[1]);
1502 		}
1503 		fd = r_io_fd_open (core->io, argv[0], perms, 0);
1504 		core->num->value = fd;
1505 		r_str_argv_free (argv);
1506 		return 0;
1507 	case 'p': // "op"
1508 		/* handle prioritize */
1509 		if (input[1]) {
1510 			switch (input[1]) {
1511 			case 'r': // "opr" - open next file + rotate if not found
1512 			case 'n': // "opn" - open next file
1513 			case 'p': // "opp" - open previous file
1514 				if (!cmd_op (core, input[1], -1)) {
1515 					eprintf ("Cannot find file\n");
1516 				}
1517 				break;
1518 			case ' ':
1519 				{
1520 					int fd = r_num_math (core->num, input + 1);
1521 					if (fd >= 0 || input[1] == '0') {
1522 						cmd_op (core, 0, fd);
1523 					} else {
1524 						eprintf ("Invalid fd number\n");
1525 					}
1526 				}
1527 				break;
1528 			default:
1529 				r_core_cmd_help (core, help_msg_op);
1530 				break;
1531 			}
1532 		} else {
1533 			if (core->io && core->io->desc) {
1534 				r_cons_printf ("%d\n", core->io->desc->fd);
1535 			}
1536 		}
1537 		return 0;
1538 		break;
1539 	case '+': // "o+"
1540 		perms |= R_PERM_W;
1541 		/* fallthrough */
1542 	case ' ': // "o" "o "
1543 		ptr = input + 1;
1544 		argv = r_str_argv (ptr, &argc);
1545 		if (argc == 0) {
1546 			eprintf ("Usage: o (uri://)[/path/to/file] (addr)\n");
1547 			r_str_argv_free (argv);
1548 			return 0;
1549 		}
1550 		if (argv) {
1551 			// Unescape spaces from the path
1552 			r_str_path_unescape (argv[0]);
1553 			if (argc == 2) {
1554 				if (r_num_is_valid_input (core->num, argv[1])) {
1555 					addr = r_num_math (core->num, argv[1]);
1556 				} else {
1557 					perms = r_str_rwx (argv[1]);
1558 				}
1559 			}
1560 			if (argc == 3) {
1561 				addr = r_num_math (core->num, argv[1]);
1562 				perms = r_str_rwx (argv[2]);
1563 			}
1564 		}
1565 		{
1566 			const char *argv0 = argv ? argv[0] : ptr;
1567 			if ((file = r_core_file_open (core, argv0, perms, addr))) {
1568 				fd = file->fd;
1569 				core->num->value = fd;
1570 				if (addr == 0) { // if no baddr defined, use the one provided by the file
1571 					addr = UT64_MAX;
1572 				}
1573 				r_core_bin_load (core, argv0, addr);
1574 				if (*input == '+') { // "o+"
1575 					RIODesc *desc = r_io_desc_get (core->io, fd);
1576 					if (desc && (desc->perm & R_PERM_W)) {
1577 						void **it;
1578 						r_pvector_foreach_prev (&core->io->maps, it) {
1579 							RIOMap *map = *it;
1580 							if (map->fd == fd) {
1581 								map->perm |= R_PERM_WX;
1582 							}
1583 						}
1584 					} else {
1585 						eprintf ("Error: %s is not writable\n", argv0);
1586 					}
1587 				}
1588 			} else {
1589 				eprintf ("cannot open file %s\n", argv0);
1590 			}
1591 			r_str_argv_free (argv);
1592 		}
1593 		r_core_block_read (core);
1594 		return 0;
1595 	}
1596 
1597 	switch (*input) {
1598 	case '=': // "o="
1599 		fdsz = 0;
1600 		r_id_storage_foreach (core->io->files, init_desc_list_visual_cb, core->print);
1601 		r_id_storage_foreach (core->io->files, desc_list_visual_cb, core->print);
1602 		break;
1603 	case 'q': // "oq"
1604 		if (input[1] == '.') {
1605 			r_id_storage_foreach (core->io->files, desc_list_quiet2_cb, core->print);
1606 		} else {
1607 			r_id_storage_foreach (core->io->files, desc_list_quiet_cb, core->print);
1608 		}
1609 		break;
1610 	case '\0': // "o"
1611 		r_id_storage_foreach (core->io->files, desc_list_cb, core->print);
1612 		break;
1613 	case '*': // "o*"
1614 		if ('?' == input[1]) {
1615 			r_core_cmd_help (core, help_msg_o_star);
1616 			break;
1617 		}
1618 		r_id_storage_foreach (core->io->files, desc_list_cmds_cb, core);
1619 		break;
1620 	case 'j': // "oj"
1621 		if ('?' == input[1]) {
1622 			r_core_cmd_help (core, help_msg_oj);
1623 			break;
1624 		}
1625 		PJ *pj = pj_new ();
1626 		pj_a (pj);
1627 		r_id_storage_foreach (core->io->files, desc_list_json_cb, pj);
1628 		pj_end (pj);
1629 		core->print->cb_printf ("%s\n", pj_string (pj));
1630 		pj_free (pj);
1631 		break;
1632 	case 'L': // "oL"
1633 		if (r_sandbox_enable (0)) {
1634 			eprintf ("This command is disabled in sandbox mode\n");
1635 			return 0;
1636 		}
1637 		if (input[1] == ' ') {
1638 			if (r_lib_open (core->lib, input + 2) == -1) {
1639 				eprintf ("Oops\n");
1640 			}
1641 		} else {
1642 			if ('j' == input[1]) {
1643 				r_io_plugin_list_json (core->io);
1644 			} else {
1645 				r_io_plugin_list (core->io);
1646 			}
1647 		}
1648 		break;
1649 	case 'u': { // "ou"
1650 		core->switch_file_view = 0;
1651 		int num = atoi (input + 2);
1652 
1653 		r_io_use_fd (core->io, num);
1654 		RBinFile *bf = r_bin_file_find_by_fd (core->bin, num);
1655 		if (bf) {
1656 			r_core_bin_raise (core, bf->id);
1657 			r_core_block_read (core);
1658 		}
1659 		break;
1660 	}
1661 	case 'b': // "ob"
1662 		cmd_open_bin (core, input);
1663 		break;
1664 	case '-': // "o-"
1665 		switch (input[1]) {
1666 		case '!': // "o-!"
1667 			r_core_file_close_all_but (core);
1668 			break;
1669 		case '*': // "o-*"
1670 			r_io_close_all (core->io);
1671 			r_bin_file_delete_all (core->bin);
1672 			break;
1673 		case '-': // "o--"
1674 			r_io_close_all (core->io);
1675 			r_bin_file_delete_all (core->bin);
1676 
1677 			// TODO: Move to a-- ?
1678 			r_anal_purge (core->anal);
1679 			// TODO: Move to f-- ?
1680 			r_flag_unset_all (core->flags);
1681 			// TODO: rbin?
1682 #if 0
1683 			// delete
1684 			r_core_file_close_fd (core, -1);
1685 			r_io_close_all (core->io);
1686 			r_anal_purge (core->anal);
1687 			r_flag_unset_all (core->flags);
1688 			r_bin_file_delete_all (core->bin);
1689 #endif
1690 			break;
1691 		default:
1692 			{
1693 				int fd = (int)r_num_math (core->num, input + 1);
1694 				if (!r_io_fd_close (core->io, fd)) {
1695 					eprintf ("Unable to find file descriptor %d\n", fd);
1696 				}
1697 			}
1698 			break;
1699 		case 0:
1700 		case '?':
1701 			r_core_cmd_help (core, help_msg_o_);
1702 		}
1703 		break;
1704 	case '.': // "o."
1705 		if (input[1] == 'q') { // "o.q" // same as oq
1706 			RIOMap *map = r_io_map_get (core->io, core->offset);
1707 			if (map) {
1708 				r_cons_printf ("%d\n", map->fd);
1709 			}
1710 		} else {
1711 			RIOMap *map = r_io_map_get (core->io, core->offset);
1712 			if (map) {
1713 				RIODesc *desc = r_io_desc_get (core->io, map->fd);
1714 				if (desc) {
1715 					r_cons_printf ("%s\n", desc->uri);
1716 				}
1717 			}
1718 		}
1719 		break;
1720 	case ':': // "o:"
1721 		{
1722 			int len = r_num_math (core->num, input + 1);
1723 			if (len < 1) {
1724 				len = core->blocksize;
1725 			}
1726 			char *uri = r_str_newf ("malloc://%d", len);
1727 			ut8 *data = calloc (len, 1);
1728 			r_io_read_at (core->io, core->offset, data, len);
1729 			if ((file = r_core_file_open (core, uri, R_PERM_RWX, 0))) {
1730 				fd = file->fd;
1731 				core->num->value = fd;
1732 				r_core_bin_load (core, uri, 0);
1733 				RIODesc *desc = r_io_desc_get (core->io, fd);
1734 				if (desc) {
1735 					// TODO: why r_io_desc_write() fails?
1736 					r_io_desc_write_at (desc, 0, data, len);
1737 				}
1738 			} else {
1739 				eprintf ("Cannot %s\n", uri);
1740 			}
1741 			free (uri);
1742 			free (data);
1743 		}
1744 		break;
1745 	case 'm': // "om"
1746 		cmd_open_map (core, input);
1747 		break;
1748 	case 'o': // "oo"
1749 		switch (input[1]) {
1750 		case 'm': // "oom"
1751 			r_core_file_reopen_in_malloc (core);
1752 			break;
1753 		case 'd': // "ood" : reopen in debugger
1754 			if (input[2] == 'r') { // "oodr"
1755 				r_core_cmdf (core, "dor %s", input + 3);
1756 				r_core_file_reopen_debug (core, "");
1757 			} else if (input[2] == 'f') { // "oodf"
1758 				char **argv = NULL;
1759 				int addr = 0;
1760 				argv = r_str_argv (input + 3, &argc);
1761 				if (argc == 0) {
1762 					eprintf ("Usage: oodf (uri://)[/path/to/file] (addr)\n");
1763 					r_str_argv_free (argv);
1764 					return 0;
1765 				}
1766 				if (argc == 2) {
1767 					if (r_num_is_valid_input (core->num, argv[1])) {
1768 						addr = r_num_math (core->num, argv[1]);
1769 					}
1770 				}
1771 				r_core_file_reopen_remote_debug (core, argv[0], addr);
1772 				r_str_argv_free (argv);
1773 			} else if ('?' == input[2]) {
1774 				r_core_cmd_help (core, help_msg_ood);
1775 			} else {
1776 				r_core_file_reopen_debug (core, input + 2);
1777 			}
1778 			break;
1779 		case 'c': // "oob" : reopen with bin info
1780 			r_core_cmd0 (core, "oc `o.`");
1781 			break;
1782 		case 'b': // "oob" : reopen with bin info
1783 			if ('?' == input[2]) {
1784 				r_core_cmd_help (core, help_msg_oob);
1785 			} else {
1786 				r_core_file_reopen (core, input + 2, 0, 2);
1787 			}
1788 			break;
1789 		case 'n': // "oon"
1790 			switch (input[2]) {
1791 			case 0: // "oon"
1792 				r_core_file_reopen (core, NULL, 0, 0);
1793 				break;
1794 			case '+': // "oon+"
1795 				r_core_file_reopen (core, NULL, R_PERM_RW, 0);
1796 				break;
1797 			case 'n': // "oonn"
1798 				if ('?' == input[3] || !core->io->desc) {
1799 					r_core_cmd_help (core, help_msg_oonn);
1800 					break;
1801 				}
1802 				RIODesc *desc = r_io_desc_get (core->io, core->io->desc->fd);
1803 				if (desc) {
1804 					perms = core->io->desc->perm;
1805 					if (input[3] == '+') {
1806 						perms |= R_PERM_RW;
1807 					}
1808 					char *fname = strdup (desc->name);
1809 					if (fname) {
1810 						r_core_bin_load_structs (core, fname);
1811 						r_core_file_reopen (core, fname, perms, 0);
1812 						free (fname);
1813 					}
1814 					break;
1815 				}
1816 				break;
1817 			case '?':
1818 			default:
1819 				r_core_cmd_help (core, help_msg_oon);
1820 				break;
1821 			}
1822 			break;
1823 		case '+': // "oo+"
1824 			if ('?' == input[2]) {
1825 				r_core_cmd_help (core, help_msg_oo_plus);
1826 			} else if (core && core->io && core->io->desc) {
1827 				int fd;
1828 				int perms = R_PERM_RW;
1829 				if ((ptr = strrchr (input, ' ')) && ptr[1]) {
1830 					fd = (int)r_num_math (core->num, ptr + 1);
1831 				} else {
1832 					fd = core->io->desc->fd;
1833 					perms |= core->io->desc->perm;
1834 				}
1835 				if (r_io_reopen (core->io, fd, perms, 644)) {
1836 					void **it;
1837 					r_pvector_foreach_prev (&core->io->maps, it) {
1838 						RIOMap *map = *it;
1839 						if (map->fd == fd) {
1840 							map->perm |= R_PERM_WX;
1841 						}
1842 					}
1843 				}
1844 			}
1845 			break;
1846 		case '\0': // "oo"
1847 			if (core && core->io && core->io->desc) {
1848 				int fd;
1849 				if ((ptr = strrchr (input, ' ')) && ptr[1]) {
1850 					fd = (int)r_num_math (core->num, ptr + 1);
1851 				} else {
1852 					fd = core->io->desc->fd;
1853 				}
1854 				if (r_config_get_i (core->config, "cfg.debug")) {
1855 					RBinFile *bf = r_bin_cur (core->bin);
1856 					if (bf && r_file_exists (bf->file)) {
1857 						// Escape spaces so that o's argv parse will detect the path properly
1858 						char *file = r_str_path_escape (bf->file);
1859 						// Backup the baddr and sections that were already rebased to
1860 						// revert the rebase after the debug session is closed
1861 						ut64 orig_baddr = core->bin->cur->o->baddr_shift;
1862 						RList *orig_sections = __save_old_sections (core);
1863 
1864 						r_core_cmd0 (core, "ob-*");
1865 						r_io_close_all (core->io);
1866 						r_config_set (core->config, "cfg.debug", "false");
1867 						r_core_cmdf (core, "o %s", file);
1868 
1869 						r_core_block_read (core);
1870 						__rebase_everything (core, orig_sections, orig_baddr);
1871 						r_list_free (orig_sections);
1872 						free (file);
1873 					} else {
1874 						eprintf ("Nothing to do.\n");
1875 					}
1876 				} else {
1877 					// r_io_reopen (core->io, fd, R_PERM_R, 644);
1878 					r_io_reopen (core->io, fd, R_PERM_RX, 755);
1879 				}
1880 			}
1881 			break;
1882 		case '?':
1883 		default:
1884 			 r_core_cmd_help (core, help_msg_oo);
1885 			 break;
1886 		}
1887 		break;
1888 	case 'c': // "oc"
1889 		if (input[1] == '?') {
1890 			eprintf ("Usage: oc [file]\n");
1891 		} else if (input[1] && input[2]) {
1892 			if (r_sandbox_enable (0)) {
1893 				eprintf ("This command is disabled in sandbox mode\n");
1894 				return 0;
1895 			}
1896 			if (core->tasks.current_task != core->tasks.main_task) {
1897 				eprintf ("This command can only be executed on the main task!\n");
1898 				return 0;
1899 			}
1900 			// memleak? lose all settings wtf
1901 			// if load fails does not fallbacks to previous file
1902 			r_core_task_sync_end (&core->tasks);
1903 			r_core_fini (core);
1904 			r_core_init (core);
1905 			r_core_task_sync_begin (&core->tasks);
1906 			if (!r_core_file_open (core, input + 2, R_PERM_RX, 0)) {
1907 				eprintf ("Cannot open file\n");
1908 			}
1909 			(void)r_core_bin_load (core, NULL, baddr);
1910 		} else {
1911 			eprintf ("Missing argument\n");
1912 		}
1913 		break;
1914 	case 'x': // "ox"
1915 		if (input[1] && input[1] != '?') {
1916 			int fd, fdx;
1917 			fd = fdx = -1;
1918 			char *ptr, *inp = strdup (input);
1919 			if ((ptr = strrchr (inp, ' '))) {
1920 				fdx = (int)r_num_math (core->num, ptr + 1);
1921 				*ptr = '\0';
1922 				if ((ptr = strchr (inp, ' '))) {
1923 					fd = r_num_math (core->num, ptr + 1);
1924 				}
1925 			}
1926 			if ((fdx == -1) || (fd == -1) || (fdx == fd)) {
1927 				free (inp);
1928 				break;
1929 			} else {
1930 				free (inp);
1931 			}
1932 			r_io_desc_exchange (core->io, fd, fdx);
1933 			r_core_block_read (core);
1934 		} else {
1935 			eprintf ("Usage: ox [fd] [fdx] - exchange two file descriptors\n");
1936 		}
1937 		break;
1938 	case '?': // "o?"
1939 	default:
1940 		r_core_cmd_help (core, help_msg_o);
1941 		break;
1942 	}
1943 	return 0;
1944 }
1945