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