/* radare - LGPL - Copyright 2009-2016 - pancake */ #include #include #include #define UPDATE_TIME(a) r->times->file_open_time = r_sys_now() - a static int r_core_file_do_load_for_debug (RCore *r, ut64 loadaddr, const char *filenameuri); static int r_core_file_do_load_for_io_plugin (RCore *r, ut64 baseaddr, ut64 loadaddr); R_API int r_core_file_reopen(RCore *core, const char *args, int perm, int loadbin) { int isdebug = r_config_get_i (core->config, "cfg.debug"); char *path; ut64 ofrom = 0, laddr = r_config_get_i (core->config, "bin.laddr"); RCoreFile *file = NULL; RCoreFile *ofile = core->file; RBinFile *bf = (ofile && ofile->desc) ? r_bin_file_find_by_fd (core->bin, ofile->desc->fd) : NULL; RIODesc *odesc = ofile ? ofile->desc : NULL; char *ofilepath = NULL, *obinfilepath = bf ? strdup (bf->file) : NULL; int newpid, ret = false; ut64 origoff = core->offset; if (odesc) { if (odesc->referer) { ofilepath = odesc->referer; } else if (odesc->uri) { ofilepath = odesc->uri; } } if (r_sandbox_enable (0)) { eprintf ("Cannot reopen in sandbox\n"); free (obinfilepath); return false; } if (!core->file) { eprintf ("No file opened to reopen\n"); free (ofilepath); free (obinfilepath); return false; } newpid = odesc ? odesc->fd : -1; if (isdebug) { r_debug_kill (core->dbg, core->dbg->pid, core->dbg->tid, 9); // KILL perm = 7; } else { if (!perm) { perm = 4; //R_IO_READ; } } if (!ofilepath) { eprintf ("Unknown file path"); free (obinfilepath); return false; } // HACK: move last mapped address to higher place // XXX - why does this hack work? if (ofile->map) { ofrom = ofile->map->from; ofile->map->from = UT32_MAX; } // closing the file to make sure there are no collisions // when the new memory maps are created. path = strdup (ofilepath); free (obinfilepath); obinfilepath = strdup(ofilepath); file = r_core_file_open (core, path, perm, laddr); if (file) { int had_rbin_info = 0; ofile->map->from = ofrom; if (r_bin_file_delete (core->bin, ofile->desc->fd)) { had_rbin_info = 1; } r_core_file_close (core, ofile); r_core_file_set_by_file (core, file); r_core_file_set_by_fd (core, file->desc->fd); ofile = NULL; odesc = NULL; // core->file = file; eprintf ("File %s reopened in %s mode\n", path, (perm&R_IO_WRITE)? "read-write": "read-only"); if (loadbin && (loadbin == 2 || had_rbin_info)) { ut64 baddr = r_config_get_i (core->config, "bin.baddr"); ret = r_core_bin_load (core, obinfilepath, baddr); if (!ret) { eprintf ("Error: Failed to reload rbin for: %s", path); } } /* if (core->bin->cur && file->desc) { core->bin->cur->fd = file->desc->fd; ret = true; }*/ // close old file } else if (ofile) { eprintf ("r_core_file_reopen: Cannot reopen file: %s with perms 0x%04x," " attempting to open read-only.\n", path, perm); // lower it down back //ofile = r_core_file_open (core, path, R_IO_READ, addr); r_core_file_set_by_file (core, ofile); ofile->map->from = ofrom; } else { eprintf ("Cannot reopen\n"); } if (isdebug) { // XXX - select the right backend if (core->file && core->file->desc) newpid = core->file->desc->fd; //reopen and attach r_core_setup_debugger (core, "native", true); r_debug_select (core->dbg, newpid, newpid); // } if (core->file) { RCoreFile * cf = core->file; RIODesc *desc = cf ? cf->desc : NULL; if (desc) { #if 0 r_io_raise (core->io, desc->fd); core->switch_file_view = 1; #endif r_core_block_read (core, 0); } else { const char *name = (cf && cf->desc) ? cf->desc->name : "ERROR"; eprintf ("Error: Unable to switch the view to file: %s\n", name); } } r_core_seek (core, origoff, 1); if (isdebug) { r_core_cmd0 (core, ".dm*"); r_core_cmd0 (core, ".dr*"); r_core_cmd0 (core, "sr PC"); } else { ut64 gp = r_num_math (core->num, "loc._gp"); if (gp && gp != UT64_MAX) { r_config_set_i (core->config, "anal.gp", gp); } } // update anal io bind r_io_bind (core->io, &(core->anal->iob)); // This is done to ensure that the file is correctly // loaded into the view free (obinfilepath); //free (ofilepath); free (path); return ret; } // NOTE: probably not all environment vars takes sesnse // because they can be replaced by commands in the given // command.. we should only expose the most essential and // unidirectional ones. R_API void r_core_sysenv_help(const RCore* core) { const char* help_msg[] = { "Usage:", "!", " Run given command as in system(3)", "!", "", "list all historic commands", "!", "ls", "execute 'ls' in shell", "!!", "", "save command history to hist file", "!!", "ls~txt", "print output of 'ls' and grep for 'txt'", ".!", "rabin2 -rpsei ${FILE}", "run each output line as a r2 cmd", "!", "echo $SIZE", "display file size", "!=!", "", "enable remotecmd mode", "=!=", "", "disable remotecmd mode", "\nEnvironment:", "", "", "FILE", "", "file name", "RABIN2_LANG", "", "assume this lang to demangle", "RABIN2_DEMANGLE", "", "demangle or not", "SIZE", "","file size", "OFFSET", "", "10base offset 64bit value", "XOFFSET", "", "same as above, but in 16 base", "BSIZE", "", "block size", "ENDIAN", "", "'big' or 'little'", "ARCH", "", "value of asm.arch", "DEBUG", "", "debug mode enabled? (1,0)", "IOVA", "", "is io.va true? virtual addressing (1,0)", "BLOCK", "", "TODO: dump current block to tmp file", "BYTES", "", "TODO: variable with bytes in curblock", "PDB_SERVER", "", "e pdb.server", NULL }; r_core_cmd_help (core, help_msg); } R_API void r_core_sysenv_end(RCore *core, const char *cmd) { // TODO: remove tmpfilez if (strstr (cmd, "BLOCK")) { // remove temporary BLOCK file char *f = r_sys_getenv ("BLOCK"); if (f) { r_file_rm (f); r_sys_setenv ("BLOCK", NULL); free (f); } } r_sys_setenv ("BYTES", NULL); r_sys_setenv ("OFFSET", NULL); } #if DISCUSS EDITOR r_sys_setenv ("EDITOR", r_config_get (core->config, "cfg.editor")); CURSOR cursor position (offset from curseek) VERBOSE cfg.verbose #endif R_API char *r_core_sysenv_begin(RCore *core, const char *cmd) { char *f, *ret = strdup (cmd); if (strstr (cmd, "R2_BYTES")) { char *s = r_hex_bin2strdup (core->block, core->blocksize); r_sys_setenv ("R2_BYTES", s); free (s); } r_sys_setenv ("PDB_SERVER", r_config_get (core->config, "pdb.server")); if (core->file && core->file->desc && core->file->desc->name) { r_sys_setenv ("R2_FILE", core->file->desc->name); r_sys_setenv ("R2_SIZE", sdb_fmt (0, "%"PFMT64d, r_io_desc_size (core->io, core->file->desc))); if (strstr (cmd, "R2_BLOCK")) { // replace BLOCK in RET string if ((f = r_file_temp ("r2block"))) { if (r_file_dump (f, core->block, core->blocksize, 0)) { r_sys_setenv ("R2_BLOCK", f); } free (f); } } } r_sys_setenv ("RABIN2_LANG", r_config_get (core->config, "bin.lang")); r_sys_setenv ("RABIN2_DEMANGLE", r_config_get (core->config, "bin.demangle")); r_sys_setenv ("R2_OFFSET", sdb_fmt (0, "%"PFMT64d, core->offset)); r_sys_setenv ("R2_XOFFSET", sdb_fmt (0, "0x%08"PFMT64x, core->offset)); r_sys_setenv ("R2_ENDIAN", core->assembler->big_endian? "big": "little"); r_sys_setenv ("R2_BSIZE", sdb_fmt (0, "%d", core->blocksize)); r_sys_setenv ("R2_ARCH", r_config_get (core->config, "asm.arch")); r_sys_setenv ("R2_COLOR", r_config_get_i (core->config, "scr.color")? "1": "0"); r_sys_setenv ("R2_DEBUG", r_config_get_i (core->config, "cfg.debug")?"1":"0"); r_sys_setenv ("R2_IOVA", r_config_get_i (core->config, "io.va")?"1":"0"); return ret; } #if !__linux__ static ut64 get_base_from_maps(RCore *core, const char *file) { RDebugMap *map; RListIter *iter; ut64 b = 0LL; r_debug_map_sync (core->dbg); // update process memory maps r_list_foreach (core->dbg->maps, iter, map) { if ((map->perm & 5) == 5) { // TODO: make this more flexible // XXX - why "copy/" here? if (map->name && strstr (map->name, "copy/")) return map->addr; if (map->file && !strcmp (map->file, file)) return map->addr; if (map->name && !strcmp (map->name, file)) return map->addr; // XXX - Commented out, as this could unexpected results //b = map->addr; } } return b; } #endif R_API int r_core_bin_reload(RCore *r, const char *file, ut64 baseaddr) { int result = 0; RCoreFile *cf = r_core_file_cur (r); RIODesc *desc = cf ? cf->desc : NULL; RBinFile *bf = NULL; if (desc) result = r_bin_reload (r->bin, desc, baseaddr); bf = r_bin_cur (r->bin); r_core_bin_set_env (r, bf); return result; } static bool setbpint(RCore *r, const char *mode, const char *sym) { RBreakpointItem *bp; RFlagItem *fi = r_flag_get (r->flags, sym); if (!fi) return false; bp = r_bp_add_sw (r->dbg->bp, fi->offset, 1, R_BP_PROT_EXEC); if (bp) { bp->internal = true; #if __linux__ bp->data = r_str_newf ("?e %s: %s;dd", mode, sym); #else bp->data = r_str_newf ("?e %s: %s;ps@rdi", mode, sym); #endif return true; } eprintf ("Cannot set breakpoint at %s\n", sym); return false; } // XXX - need to handle index selection during debugging static int r_core_file_do_load_for_debug (RCore *r, ut64 baseaddr, const char *filenameuri) { RCoreFile *cf = r_core_file_cur (r); RIODesc *desc = cf ? cf->desc : NULL; RBinFile *binfile = NULL; RBinPlugin *plugin; int xtr_idx = 0; // if 0, load all if xtr is used int treat_as_rawstr = false; if (!desc) return false; if (cf && desc) { int newpid = desc->fd; #if __WINDOWS__ r_debug_select (r->dbg, r->dbg->pid, r->dbg->tid); #else r_debug_select (r->dbg, newpid, newpid); #endif } #if !__linux__ #if !__WINDOWS__ baseaddr = get_base_from_maps (r, filenameuri); #endif if (baseaddr != UT64_MAX) { r_config_set_i (r->config, "bin.baddr", baseaddr); } #endif // HACK if its a relative path, load from disk instead of memory #if __APPLE__ int fd = (filenameuri[0] == '.')? -1: desc->fd; #else int fd = desc->fd; #endif if (!r_bin_load (r->bin, filenameuri, baseaddr, UT64_MAX, xtr_idx, fd, treat_as_rawstr)) { eprintf ("Cannot open %s\n", filenameuri); if (r_config_get_i (r->config, "bin.rawstr")) { treat_as_rawstr = true; if (!r_bin_load (r->bin, filenameuri, baseaddr, UT64_MAX, xtr_idx, desc->fd, treat_as_rawstr)) { return false; } } } if (*r_config_get (r->config, "dbg.libs")) { r_core_cmd0 (r, ".dmm*"); #if __linux__ setbpint(r, "dbg.libs", "sym._dl_map_object_from_fd"); setbpint(r, "dbg.libs", "sym._dl_open"); setbpint(r, "dbg.unlibs", "sym._dl_unmap"); setbpint(r, "dbg.unlibs", "sym._dl_close"); #elif __APPLE__ setbpint(r, "dbg.libs", "sym._dlopen"); setbpint(r, "dbg.libs", "sym._dlclose"); #endif } binfile = r_bin_cur (r->bin); r_core_bin_set_env (r, binfile); plugin = r_bin_file_cur_plugin (binfile); if (plugin && !strncmp (plugin->name, "any", 5)) { // set use of raw strings r_config_set_i (r->config, "io.va", false); //\\ r_config_set (r->config, "bin.rawstr", "true"); // get bin.minstr r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr"); r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf"); } else if (binfile) { RBinObject *obj = r_bin_get_object (r->bin); RBinInfo * info = obj ? obj->info : NULL; if (plugin && strcmp (plugin->name, "any") && info) { r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits); } } if (plugin && !strcmp (plugin->name, "dex")) { r_core_cmd0 (r, "\"(fix-dex,wx `#sha1 $s-32 @32` @12 ; wx `#adler32 $s-12 @12` @8)\"\n"); } return true; } static int r_core_file_do_load_for_io_plugin (RCore *r, ut64 baseaddr, ut64 loadaddr) { RCoreFile *cf = r_core_file_cur (r); RIODesc *desc = cf ? cf->desc : NULL; RBinFile *binfile = NULL; int xtr_idx = 0; // if 0, load all if xtr is used RBinPlugin * plugin; if (!desc) return false; r_io_use_desc (r->io, desc); if ( !r_bin_load_io (r->bin, desc, baseaddr, loadaddr, xtr_idx)) { //eprintf ("Failed to load the bin with an IO Plugin.\n"); return false; } binfile = r_bin_cur (r->bin); r_core_bin_set_env (r, binfile); plugin = r_bin_file_cur_plugin (binfile); if (plugin && !strcmp (plugin->name, "any") ) { RBinObject *obj = r_bin_get_object (r->bin); RBinInfo * info = obj ? obj->info : NULL; if (!info) return false; // set use of raw strings r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits); r_config_set_i (r->config, "io.va", false); // r_config_set (r->config, "bin.rawstr", "true"); // get bin.minstr r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr"); r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf"); } else if (binfile) { RBinObject *obj = r_bin_get_object (r->bin); RBinInfo * info = obj ? obj->info : NULL; if (!info) return false; if (plugin && strcmp (plugin->name, "any") && info) { r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits); } else { r_config_set_i (r->config, "io.va", false); } } if (plugin && !strcmp (plugin->name, "dex")) { r_core_cmd0 (r, "\"(fix-dex,wx `#sha1 $s-32 @32` @12 ; wx `#adler32 $s-12 @12` @8)\"\n"); } return true; } static int try_loadlib(RCore *core, const char *lib, ut64 addr) { RCoreFile *cf = r_core_file_open (core, lib, 0, addr); if (!cf) { return false; } return true; } R_API bool r_core_file_loadlib(RCore *core, const char *lib, ut64 libaddr) { const char *ldlibrarypath[] = { "/usr/local/lib", "/usr/lib", "/lib", "./", NULL }; const char **libpath = (const char **)&ldlibrarypath; if (*lib == '/') { if (try_loadlib (core, lib, libaddr)) { return true; } } else { while (*libpath) { bool ret = false; char *s = r_str_newf ("%s/%s", *libpath, lib); if (try_loadlib (core, s, libaddr)) { ret = true; } free (s); if (ret) { return true; } libpath++; } } return false; } R_API int r_core_bin_load(RCore *r, const char *filenameuri, ut64 baddr) { const char *suppress_warning = r_config_get (r->config, "file.nowarn"); RCoreFile *cf = r_core_file_cur (r); RBinFile *binfile = NULL; RIODesc *desc = cf ? cf->desc : NULL; RBinPlugin *plugin = NULL; int is_io_load = desc && desc->plugin; if (cf) { if ((filenameuri == NULL || !*filenameuri)) { filenameuri = cf->desc->name; } else if (cf->desc->name && strcmp (filenameuri, cf->desc->name)) { // XXX - this needs to be handled appropriately // if the cf does not match the filenameuri then // either that RCoreFIle * needs to be loaded or a // new RCoreFile * should be opened. if (!strcmp (suppress_warning, "false")) { eprintf ("Error: The filenameuri '%s' is not the same as in RCoreFile: %s\n", filenameuri, cf->desc->name); } } } if (!filenameuri) { eprintf ("r_core_bin_load: no file specified\n"); return false; } r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr"); r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf"); if (is_io_load) { // TODO? necessary to restore the desc back? // RIODesc *oldesc = desc; // Fix to select pid before trying to load the binary if ( (desc->plugin && desc->plugin->isdbg) \ || r_config_get_i (r->config, "cfg.debug")) { r_core_file_do_load_for_debug (r, baddr, filenameuri); } else { ut64 laddr = r_config_get_i (r->config, "bin.laddr"); r_core_file_do_load_for_io_plugin (r, baddr, laddr); } // Restore original desc r_io_use_desc (r->io, desc); } if (cf && binfile && desc) binfile->fd = desc->fd; binfile = r_bin_cur (r->bin); if (r->bin->cur && r->bin->cur->curplugin && r->bin->cur->curplugin->strfilter) { char msg[2]; msg[0] = r->bin->cur->curplugin->strfilter; msg[1] = 0; r_config_set (r->config, "bin.strfilter", msg); } r_core_bin_set_env (r, binfile); plugin = r_bin_file_cur_plugin (binfile); if (plugin && plugin->name && !strncmp (plugin->name, "any", 3)) { // set use of raw strings //r_config_set (r->config, "bin.rawstr", "true"); r_config_set_i (r->config, "io.va", false); // get bin.minstr r->bin->minstrlen = r_config_get_i (r->config, "bin.minstr"); r->bin->maxstrbuf = r_config_get_i (r->config, "bin.maxstrbuf"); } else if (binfile) { RBinObject *obj = r_bin_get_object (r->bin); RBinInfo * info = obj ? obj->info : NULL; if (plugin && plugin->name && info) if (strcmp (plugin->name, "any")) { r_core_bin_set_arch_bits (r, binfile->file, info->arch, info->bits); } } if (plugin && plugin->name && !strcmp (plugin->name, "dex")) { r_core_cmd0 (r, "\"(fix-dex,wx `#sha1 $s-32 @32` @12 ;" " wx `#adler32 $s-12 @12` @8)\"\n"); } if (!r_config_get_i (r->config, "cfg.debug")) { /* load GP for mips */ ut64 gp = r_num_math (r->num, "loc._gp"); if (gp && gp != UT64_MAX) { r_config_set_i (r->config, "anal.gp", gp); } } if (r_config_get_i (r->config, "bin.libs")) { ut64 libaddr = (r->assembler->bits == 64) ? 0x00007fff00000000 : 0x7f000000; const char *lib; RListIter *iter; RList *libs = r_bin_get_libs (r->bin); r_list_foreach (libs, iter, lib) { eprintf ("Opening %s\n", lib); r_core_file_loadlib (r, lib, libaddr); libaddr += 0x2000000; } } return true; } R_API RIOMap *r_core_file_get_next_map (RCore *core, RCoreFile * fh, int mode, ut64 loadaddr) { const char *loadmethod = r_config_get (core->config, "file.loadmethod"); const char *suppress_warning = r_config_get (core->config, "file.nowarn"); ut64 load_align = r_config_get_i (core->config, "file.loadalign"); RIOMap *map = NULL; if (!strcmp (loadmethod, "overwrite")) map = r_io_map_new (core->io, fh->desc->fd, mode, 0, loadaddr, r_io_desc_size (core->io, fh->desc)); if (!strcmp (loadmethod, "fail")) map = r_io_map_add (core->io, fh->desc->fd, mode, 0, loadaddr, r_io_desc_size (core->io, fh->desc)); if (!strcmp (loadmethod, "append") && load_align) { map = r_io_map_add_next_available (core->io, fh->desc->fd, mode, 0, loadaddr, r_io_desc_size (core->io, fh->desc), load_align); } if (!strcmp (suppress_warning, "false")) { if (!map) eprintf ("r_core_file_get_next_map: Unable to load specified file to 0x%08"PFMT64x"\n", loadaddr); else { if (map->from != loadaddr) eprintf ("r_core_file_get_next_map: Unable to load specified file to 0x%08"PFMT64x",\n" "but loaded to 0x%08"PFMT64x"\n", loadaddr, map->from); } } r_io_sort_maps (core->io); //necessary ??? return map; } R_API RCoreFile *r_core_file_open_many(RCore *r, const char *file, int flags, ut64 loadaddr) { RIODesc *fd; RList *list_fds = NULL; const char *cp = NULL; char *loadmethod = NULL; RListIter *fd_iter, *iter2; RCoreFile *fh, *top_file = NULL; ut64 current_loadaddr = loadaddr; const char *suppress_warning = r_config_get (r->config, "file.nowarn"); int openmany = r_config_get_i (r->config, "file.openmany"), opened_count = 0; list_fds = r_io_open_many (r->io, file, flags, 0644); if (!list_fds || r_list_length (list_fds) == 0 ) { r_list_free (list_fds); return NULL; } cp = r_config_get (r->config, "file.loadmethod"); if (cp) loadmethod = strdup (cp); r_config_set (r->config, "file.loadmethod", "append"); r_list_foreach_safe (list_fds, fd_iter, iter2, fd) { opened_count++; if (opened_count > openmany) { // XXX - Open Many should limit the number of files // loaded in io plugin area this needs to be more premptive // like down in the io plugin layer. // start closing down descriptors r_list_delete (list_fds, fd_iter); continue; } fh = R_NEW0 (RCoreFile); if (!fh) { eprintf ("file.c:r_core_many failed to allocate new RCoreFile.\n"); break; } fh->alive = 1; fh->core = r; fh->desc = fd; r->file = fh; r->io->plugin = fd->plugin; // XXX - load addr should be at a set offset fh->map = r_core_file_get_next_map (r, fh, flags, current_loadaddr); if (!fh->map) { r_core_file_free (fh); if (!strcmp (suppress_warning, "false")) eprintf("Unable to load file due to failed mapping.\n"); continue; } current_loadaddr = fh->map->to; if (!top_file) { top_file = fh; // check load addr to make sure its still valid loadaddr = top_file->map->from; } r_bin_bind (r->bin, &(fh->binb)); r_list_append (r->files, fh); r_core_bin_load (r, fh->desc->name, fh->map->from); } if (!top_file) { free (loadmethod); return top_file; } cp = r_config_get (r->config, "cmd.open"); if (cp && *cp) r_core_cmd (r, cp, 0); r_config_set (r->config, "file.path", r_file_abspath (top_file->desc->name)); r_config_set_i (r->config, "zoom.to", top_file->map->from + r_io_desc_size (r->io, top_file->desc)); if (loadmethod) r_config_set (r->config, "file.loadmethod", loadmethod); free (loadmethod); return top_file; } R_API RCoreFile *r_core_file_open (RCore *r, const char *file, int flags, ut64 loadaddr) { ut64 prev = r_sys_now(); const char *suppress_warning = r_config_get (r->config, "file.nowarn"); const int openmany = r_config_get_i (r->config, "file.openmany"); const char *cp; RCoreFile *fh = NULL; RIODesc *fd; if (!file || !*file) { goto beach; } if (!strcmp (file, "-")) { file = "malloc://512"; flags = 4|2; } r->io->bits = r->assembler->bits; // TODO: we need an api for this fd = r_io_open_nomap (r->io, file, flags, 0644); if (fd == NULL && openmany > 2) { // XXX - make this an actual option somewhere? fh = r_core_file_open_many (r, file, flags, loadaddr); if (fh) goto beach; } if (fd == NULL) { if (flags & 2) { if (!r_io_create (r->io, file, 0644, 0)) { goto beach; } if (!(fd = r_io_open_nomap (r->io, file, flags, 0644))) { goto beach; } } else { goto beach; } } if (r_io_is_listener (r->io)) { r_core_serve (r, fd); goto beach; } fh = R_NEW0 (RCoreFile); if (!fh) { eprintf ("core/file.c: r_core_open failed to allocate RCoreFile.\n"); goto beach; } fh->alive = 1; fh->core = r; fh->desc = fd; cp = r_config_get (r->config, "cmd.open"); if (cp && *cp) r_core_cmd (r, cp, 0); { char *absfile = r_file_abspath (file); r_config_set (r->config, "file.path", absfile); free (absfile); } fh->map = r_core_file_get_next_map (r, fh, flags, loadaddr); if (!fh->map) { r_core_file_free (fh); fh = NULL; if (!strcmp (suppress_warning, "false")) eprintf("Unable to load file due to failed mapping.\n"); goto beach; } // check load addr to make sure its still valid r_bin_bind (r->bin, &(fh->binb)); r_list_append (r->files, fh); r_core_file_set_by_file (r, fh); r_config_set_i (r->config, "zoom.to", fh->map->from + r_io_desc_size (r->io, fh->desc)); if (r_config_get_i (r->config, "cfg.debug")) { bool swstep = true; if (r->dbg->h && r->dbg->h->canstep) swstep = false; r_config_set_i (r->config, "dbg.swstep", swstep); } beach: r->times->file_open_time = r_sys_now() - prev; return fh; } R_API int r_core_files_free(const RCore *core, RCoreFile *cf) { if (!core || !core->files || !cf) return false; return r_list_delete_data (core->files, cf); } R_API void r_core_file_free(RCoreFile *cf) { int res = 1; if (!cf || !cf->core) return; if (cf) { res = r_core_files_free (cf->core, cf); } //if (!res && cf && cf->alive) { if (res && cf && cf->alive) { // double free libr/io/io.c:70 performs free RIO *io = NULL; if (cf) { io = (RIO*)(cf->desc ? cf->desc->io : NULL); if (cf->map) { r_io_map_del (io, cf->map->fd); cf->map = NULL; } r_bin_file_deref_by_bind (&cf->binb); r_io_close ((RIO *) io, cf->desc); free (cf); } } cf = NULL; } R_API int r_core_file_close(RCore *r, RCoreFile *fh) { int ret; RIODesc *desc = fh && fh->desc? fh->desc : NULL; RCoreFile *prev_cf = r && r->file != fh ? r->file : NULL; // TODO: This is not correclty done. because map and iodesc are // still referenced // we need to fully clear all R_IO structs // related to a file as well as the ones needed for RBin. // // XXX -these checks are intended to *try* and catch // stale objects. Unfortunately, if the file handle // (fh) is stale and freed, and there is more than 1 // fh in the r->files list, we are hosed. (design flaw) // TODO maybe using sdb to keep track of the allocated and // deallocated files might be a good solutions if (!r || !desc || r_list_empty (r->files)) return false; if (fh == r->file) r->file = NULL; r_core_file_set_by_fd (r, fh->desc->fd); r_core_bin_set_by_fd (r, fh->desc->fd); /* delete filedescriptor from io descs here */ r_io_desc_del (r->io, fh->desc->fd); // AVOID DOUBLE FREE HERE r->files->free = NULL; ret = r_list_delete_data (r->files, fh); if (ret) { if (!prev_cf && r_list_length (r->files) > 0) prev_cf = (RCoreFile *) r_list_get_n (r->files, 0); if (prev_cf) { RIODesc *desc = prev_cf->desc; if (!desc) eprintf ("Error: RCoreFile's found with out a supporting RIODesc.\n"); ret = r_core_file_set_by_file (r, prev_cf); } } #if 0 { RListIter *iter; RIODesc *iod; RCoreFile *mcf; r_list_foreach (r->files, iter, mcf) { r_cons_printf ("[cf]--> %p %p %d\n", mcf, mcf->desc, mcf->desc->fd); } r_list_foreach (r->io->files, iter, iod) { r_cons_printf ("[io]--> %p %d\n", iod, iod->fd); } } #endif return ret; } R_API RCoreFile *r_core_file_get_by_fd(RCore *core, int fd) { RCoreFile *file; RListIter *iter; r_list_foreach (core->files, iter, file) { if (file->desc->fd == fd) return file; } return NULL; } R_API int r_core_file_list(RCore *core, int mode) { int overlapped, count = 0; RCoreFile *f; ut64 from; RListIter *iter; if (mode=='j') r_cons_printf ("["); r_list_foreach (core->files, iter, f) { if (f->map) { from = f->map->from; overlapped = r_io_map_overlaps (core->io, f->desc, f->map); } else { from = 0LL; overlapped = false; } switch (mode) { case 'j': r_cons_printf ("{\"raised\":%s,\"fd\":%d,\"uri\":\"%s\",\"from\":%" PFMT64d",\"writable\":%s,\"size\":%d,\"overlaps\":%s}%s", core->io->raised == f->desc->fd?"true":"false", (int)f->desc->fd, f->desc->uri, (ut64)from, f->desc->flags & R_IO_WRITE? "true": "false", (int)r_io_desc_size (core->io, f->desc), overlapped?"true":"false", iter->n? ",":""); break; case '*': case 'r': r_cons_printf ("o %s 0x%"PFMT64x"\n", f->desc->uri, (ut64)from); break; default: r_cons_printf ("%c %d %s @ 0x%"PFMT64x" ; %s size=%d %s\n", core->io->raised == f->desc->fd?'*':'-', (int)f->desc->fd, f->desc->uri, (ut64)from, f->desc->flags & R_IO_WRITE? "rw": "r", (ut32)r_io_desc_size (core->io, f->desc), overlapped?"overlaps":""); break; } count++; } if (mode=='j') r_cons_printf ("]\n"); return count; } // XXX - needs to account for binfile index and bin object index R_API int r_core_file_bin_raise (RCore *core, ut32 binfile_idx) { RBin *bin = core->bin; int v = binfile_idx > 1 ? binfile_idx : 1; RBinFile *bf = r_list_get_n (bin->binfiles, v); int res = false; if (bf) { res = r_bin_file_set_cur_binfile (bin, bf); if (res) r_io_raise (core->io, bf->fd); res = res ? r_core_file_set_by_fd (core, bf->fd) : res; if (res) core->switch_file_view = 1; } return res; } R_API int r_core_file_binlist(RCore *core) { int count = 0; RListIter *iter; RCoreFile *cur_cf = core->file, *cf = NULL; RBinFile *binfile = NULL; RBin *bin = core->bin; const RList *binfiles = bin ? bin->binfiles: NULL; if (!binfiles) return false; r_list_foreach (binfiles, iter, binfile) { int fd = binfile->fd; cf = r_core_file_get_by_fd (core, fd); if (cf && cf->map) { r_cons_printf ("%c %d %s @ 0x%"PFMT64x" ; %s\n", core->io->raised == cf->desc->fd?'*':'-', fd, cf->desc->uri, cf->map->from, cf->desc->flags & R_IO_WRITE? "rw": "r"); } } r_core_file_set_by_file (core, cur_cf); //r_core_bin_bind (core, cur_bf); return count; } R_API int r_core_file_close_fd(RCore *core, int fd) { RCoreFile *file; RListIter *iter; r_list_foreach (core->files, iter, file) { if (file->desc->fd == fd || fd == -1) { r_core_file_close (core, file); if (file == core->file) { core->file = NULL; // deref } #if 0 if (r_list_empty (core->files)) core->file = NULL; #endif return true; } } return false; } R_API int r_core_hash_load(RCore *r, const char *file) { const ut8 *md5, *sha1; char hash[128], *p; int i; int buf_len = 0; ut8 *buf = NULL; RHash *ctx; ut64 limit; RCoreFile *cf = r_core_file_cur (r); if (!file && cf && cf->desc) { file = cf->desc->name; } if (!file) { return false; } limit = r_config_get_i (r->config, "cfg.hashlimit"); if (r_io_desc_size (r->io, cf->desc) > limit) return false; buf = (ut8*)r_file_slurp (file, &buf_len); if (buf==NULL) return false; ctx = r_hash_new (true, R_HASH_MD5); md5 = r_hash_do_md5 (ctx, buf, buf_len); p = hash; for (i=0; iconfig, "file.md5", hash); r_hash_free (ctx); ctx = r_hash_new (true, R_HASH_SHA1); sha1 = r_hash_do_sha1 (ctx, buf, buf_len); p = hash; for (i=0; iconfig, "file.sha1", hash); r_hash_free (ctx); free (buf); return true; } R_API RCoreFile * r_core_file_find_by_fd (RCore *core, ut64 fd) { RListIter *iter; RCoreFile *cf = NULL; r_list_foreach (core->files, iter, cf) { if (cf && cf->desc && cf->desc->fd == fd) break; cf = NULL; } return cf; } R_API RCoreFile * r_core_file_find_by_name (RCore * core, const char * name) { RListIter *iter; RCoreFile *cf = NULL; r_list_foreach (core->files, iter, cf) { if (cf && cf->desc && !strcmp (cf->desc->name, name)) break; cf = NULL; } return cf; } R_API int r_core_file_set_by_fd (RCore * core, ut64 fd) { RCoreFile *cf = r_core_file_find_by_fd (core, fd); return r_core_file_set_by_file (core, cf); } R_API int r_core_file_set_by_name (RCore * core, const char * name) { RCoreFile *cf = r_core_file_find_by_name (core, name); return r_core_file_set_by_file (core, cf); } R_API int r_core_file_set_by_file (RCore * core, RCoreFile *cf) { if (cf) { RIODesc *desc = cf->desc; core->offset = cf && cf->map ? cf->map->from : 0LL; core->file = cf; if (desc) { r_io_use_desc (core->io, desc); r_core_bin_set_by_fd (core, desc->fd); } return true; } return false; } R_API ut32 r_core_file_cur_fd (RCore *core) { RIODesc *desc = core->file ? core->file->desc : NULL; if (desc) { return desc->fd; } return (ut32)-1; //WTF } R_API RCoreFile * r_core_file_cur (RCore *r) { // Add any locks here return r->file; }