R_API void r_debug_map_list(RDebug *dbg, ut64 addr, int rad) { RListIter *iter = r_list_iterator (dbg->maps); if (rad) { while (r_list_iter_next (iter)) { RDebugMap *map = r_list_iter_get (iter); dbg->printf ("f map.%s.%s 0x%08"PFMT64x" 0x%08"PFMT64x"\n", map->name, r_str_rwx_i (map->perm), map->addr_end - map->addr, map->addr); } iter = r_list_iterator (dbg->maps_user); while (r_list_iter_next (iter)) { RDebugMap *map = r_list_iter_get (iter); dbg->printf ("f map.%s.%s 0x%08"PFMT64x" 0x%08"PFMT64x"\n", map->name, r_str_rwx_i (map->perm), map->addr_end - map->addr, map->addr); } } else { while (r_list_iter_next (iter)) { RDebugMap *map = r_list_iter_get (iter); dbg->printf ("sys 0x%08"PFMT64x" %c 0x%08"PFMT64x" %c %s %s\n", map->addr, (addr>=map->addr && addr<=map->addr_end)?'*':'-', map->addr_end, map->user?'u':'s', r_str_rwx_i (map->perm), map->name); } iter = r_list_iterator (dbg->maps_user); while (r_list_iter_next (iter)) { RDebugMap *map = r_list_iter_get (iter); dbg->printf ("usr 0x%08"PFMT64x" - 0x%08"PFMT64x" %c %x %s\n", map->addr, map->addr_end, map->user?'u':'s', map->perm, map->name); } } }
bool test_r_str_rwx_i(void) { const char* rwx = r_str_rwx_i (7); const char* rw = r_str_rwx_i (6); const char* rx = r_str_rwx_i (5); const char* mx = r_str_rwx_i (17); const char* invalid_mode = r_str_rwx_i (898); mu_assert_streq (rwx, "-rwx", "rwx = 7 mode"); mu_assert_streq (rw, "-rw-", "rw = 6 mode"); mu_assert_streq (rx, "-r-x", "rx = 5 mode"); mu_assert_streq (mx, "m--x", "mx = 17 mode"); //XXX this test fails because the underlying behavior is wrong! mu_test_status = MU_TEST_BROKEN; // Only for this next assert. mu_assert_streq (invalid_mode, "----", "invalid permissions mode"); mu_end; }
/* Write a single memory map line to the console */ static void print_debug_map_line(RDebug *dbg, RDebugMap *map, ut64 addr, const char *input) { if (input[0] == 'q') { // "dmq" char buf[128]; char *name = (map->name && *map->name) ? r_str_newf ("%s.%s", map->name, r_str_rwx_i (map->perm)) : r_str_newf ("%08"PFMT64x".%s", map->addr, r_str_rwx_i (map->perm)); r_name_filter (name, 0); dbg->cb_printf ("0x%016"PFMT64x" - 0x%016"PFMT64x" %6s %5s %s\n", map->addr, map->addr_end, r_num_units (buf, map->addr_end - map->addr), r_str_rwx_i (map->perm), name); free (name); } else { char sizebuf[128]; const char *fmtstr = dbg->bits & R_SYS_BITS_64 ? "0x%016"PFMT64x" - 0x%016"PFMT64x" %c %s %6s %c %s %s %s%s%s\n" : "0x%08"PFMT64x" - 0x%08"PFMT64x" %c %s %6s %c %s %s %s%s%s\n"; const char *type = map->shared? "sys": "usr"; const char *flagname = dbg->corebind.getName ? dbg->corebind.getName (dbg->corebind.core, map->addr) : NULL; if (!flagname) { flagname = ""; } else if (map->name) { char *filtered_name = strdup (map->name); r_name_filter (filtered_name, 0); if (!strncmp (flagname, "map.", 4) && \ !strcmp (flagname + 4, filtered_name)) { flagname = ""; } free (filtered_name); } dbg->cb_printf (fmtstr, map->addr, map->addr_end, (addr>=map->addr && addr<map->addr_end)?'*':'-', type, r_num_units (sizebuf, map->size), map->user?'u':'s', r_str_rwx_i (map->perm), map->name?map->name:"?", map->file?map->file:"?", *flagname? " ; ": "", flagname); } }
/* Print out the JSON body for memory maps in the passed map region */ static void print_debug_map_json(RDebug *dbg, RDebugMap *map, bool prefix_comma) { dbg->cb_printf ("%s{", prefix_comma ? ",": ""); if (map->name && *map->name) { char *escaped_name = r_str_escape (map->name); dbg->cb_printf ("\"name\":\"%s\",", escaped_name); free (escaped_name); } if (map->file && *map->file) { char *escaped_path = r_str_escape (map->file); dbg->cb_printf ("\"file\":\"%s\",", escaped_path); free (escaped_path); } dbg->cb_printf ("\"addr\":%"PFMT64u",", map->addr); dbg->cb_printf ("\"addr_end\":%"PFMT64u",", map->addr_end); dbg->cb_printf ("\"type\":\"%c\",", map->user?'u':'s'); dbg->cb_printf ("\"perm\":\"%s\"", r_str_rwx_i (map->perm)); dbg->cb_printf ("}"); }
static int __system(RIO *io, RIODesc *fd, const char *cmd) { if (!strcmp (cmd, "pid")) { eprintf ("%d\n", fd->fd); }else if (!strcmp (cmd, "maps")) { int i; for (i =0; i<self_sections_count ;i++) { eprintf ("0x%08"PFMT64x" - 0x%08"PFMT64x" %s %s\n", self_sections[i].from, self_sections[i].to, r_str_rwx_i (self_sections[i].perm), self_sections[i].name); } } else { eprintf ("|Usage: \n"); eprintf ("| =!pid show getpid()\n"); eprintf ("| =!maps show map regions\n"); } return 0; }
bool test_r_str_rwx_i(void) { const char* rwx = r_str_rwx_i (7); const char* rw = r_str_rwx_i (6); const char* rx = r_str_rwx_i (5); const char* mx = r_str_rwx_i (17); const char* invalid_mode = r_str_rwx_i (898); const char* invalid_mode_neg = r_str_rwx_i (-10); mu_assert_streq (rwx, "-rwx", "rwx = 7 mode"); mu_assert_streq (rw, "-rw-", "rw = 6 mode"); mu_assert_streq (rx, "-r-x", "rx = 5 mode"); mu_assert_streq (mx, "m--x", "mx = 17 mode"); mu_assert_streq (invalid_mode, "----", "invalid permissions mode"); mu_assert_streq (invalid_mode_neg, "----", "invalid permissions mode (negative value)"); mu_end; }
R_API void r_debug_esil_watch_list(RDebug *dbg) { EsilBreak *ew; RListIter *iter; r_list_foreach (EWPS, iter, ew) { dbg->cb_printf ("de %s %c %s\n", r_str_rwx_i (ew->rwx), ew->dev, ew->expr); }
static RList *ios_dbg_maps(RDebug *dbg, int only_modules) { boolt contiguous = R_FALSE; ut32 oldprot = UT32_MAX; ut32 oldmaxprot = UT32_MAX; char buf[1024]; char module_name[MAXPATHLEN]; mach_vm_address_t address = MACH_VM_MIN_ADDRESS; mach_vm_size_t size = (mach_vm_size_t) 0; mach_vm_size_t osize = (mach_vm_size_t) 0; natural_t depth = 0; int tid = dbg->pid; task_t task = pid_to_task (tid); RDebugMap *mr = NULL; RList *list = NULL; int i = 0; if (only_modules) { return xnu_dbg_modules (dbg); } #if __arm64__ || __aarch64__ size = osize = 16384; // acording to frida #else size = osize = 4096; #endif #if 0 if (dbg->pid == 0) { vm_address_t base = get_kernel_base (task); eprintf ("Kernel Base Address: 0x%"PFMT64x"\n", (ut64)base); return NULL; } #endif kern_return_t kr; for (;;) { struct vm_region_submap_info_64 info; mach_msg_type_number_t info_count; info_count = VM_REGION_SUBMAP_INFO_COUNT_64; memset (&info, 0, sizeof (info)); kr = mach_vm_region_recurse (task, &address, &size, &depth, (vm_region_recurse_info_t) &info, &info_count); if (kr != KERN_SUCCESS) { //eprintf ("Cannot kern succ recurse\n"); break; } if (info.is_submap) { depth++; continue; } if (!list) { list = r_list_new (); //list->free = (RListFree*)r_debug_map_free; } { module_name[0] = 0; int ret = proc_regionfilename (tid, address, module_name, sizeof (module_name)); module_name[ret] = 0; } #if 0 oldprot = info.protection; oldmaxprot = info.max_protection; // contiguous pages seems to hide some map names if (mr) { if (address == mr->addr + mr->size) { if (oldmaxprot == info.max_protection) { contiguous = R_FALSE; } else if (oldprot != UT32_MAX && oldprot == info.protection) { /* expand region */ mr->size += size; contiguous = R_TRUE; } else { contiguous = R_FALSE; } } else { contiguous = R_FALSE; } } else contiguous = R_FALSE; //if (info.max_protection == oldprot && !contiguous) { #endif if (1) { #define xwr2rwx(x) ((x&1)<<2) | (x&2) | ((x&4)>>2) // XXX: if its shared, it cannot be read? snprintf (buf, sizeof (buf), "%s %02x %s%s%s%s%s %s depth=%d", r_str_rwx_i (xwr2rwx (info.max_protection)), i, unparse_inheritance (info.inheritance), info.user_tag? " user": "", info.is_submap? " sub": "", info.inheritance? " inherit": "", info.is_submap ? " submap": "", module_name, depth); //info.shared ? "shar" : "priv", //info.reserved ? "reserved" : "not-reserved", //""); //module_name); mr = r_debug_map_new (buf, address, address+size, xwr2rwx (info.protection), 0); if (mr == NULL) { eprintf ("Cannot create r_debug_map_new\n"); break; } mr->file = strdup (module_name); i++; r_list_append (list, mr); } if (size<1) { eprintf ("EFUCK\n"); size = osize; // f**k } address += size; size = 0; } return list; }
static void r_core_file_info (RCore *core, int mode) { const char *fn = NULL; int dbg = r_config_get_i (core->config, "cfg.debug"); RBinInfo *info = r_bin_get_info (core->bin); if (mode == R_CORE_BIN_JSON) r_cons_printf ("{"); if (mode == R_CORE_BIN_RADARE) return; if (info) { fn = info->file; switch (mode) { case R_CORE_BIN_JSON: r_cons_printf ("\"type\":\"%s\"," "\"os\":\"%s\"," "\"arch\":\"%s\"," "\"bits\":%d," "\"endian\":\"%s\"," , info->type , info->os , info->machine , info->bits , info->big_endian? "big": "little"); break; default: r_cons_printf ("type\t%s\n" "os\t%s\n" "arch\t%s\n" "bits\t%d\n" "endian\t%s\n" , info->type , info->os , info->machine , info->bits , info->big_endian? "big": "little"); break; } } else fn = core->file->filename; if (mode == R_CORE_BIN_JSON) { r_cons_printf ("\"file\":\"%s\"", fn); if (dbg) dbg = R_IO_WRITE | R_IO_EXEC; r_cons_printf (",\"fd\":%d", core->file->fd->fd); r_cons_printf (",\"size\":%d", core->file->size); r_cons_printf (",\"mode\":\"%s\"", r_str_rwx_i ( core->file->rwx | dbg)); r_cons_printf (",\"block\":%d", core->blocksize); r_cons_printf (",\"uri\":\"%s\"", core->file->uri); if (core->bin->curxtr) r_cons_printf (",\"packet\":\"%s\"", core->bin->curxtr->name); if (core->bin->curxtr) r_cons_printf (",\"format\":\"%s\"", core->bin->cur.curplugin->name); r_cons_printf ("}"); } else { //r_cons_printf ("# Core file info\n"); r_cons_printf ("file\t%s\n", fn); if (dbg) dbg = R_IO_WRITE | R_IO_EXEC; r_cons_printf ("fd\t%d\n", core->file->fd->fd); r_cons_printf ("size\t0x%x\n", core->file->size); r_cons_printf ("mode\t%s\n", r_str_rwx_i (core->file->rwx | dbg)); r_cons_printf ("block\t0x%x\n", core->blocksize); r_cons_printf ("uri\t%s\n", core->file->uri); if (core->bin->curxtr) r_cons_printf ("packet\t%s\n", core->bin->curxtr->name); if (core->bin->curxtr) r_cons_printf ("format\t%s\n", core->bin->cur.curplugin->name); } }
R_API void r_debug_map_list(RDebug *dbg, ut64 addr, const char *input) { int i; bool notfirst = false; RListIter *iter; RDebugMap *map; if (!dbg) { return; } switch (input[0]) { case 'j': // "dmj" add JSON opening array brace dbg->cb_printf ("["); break; case '*': // "dm*" dont print a header for r2 commands output break; default: // TODO: Find a way to only print headers if output isn't being grepped print_debug_map_line_header (dbg, input); } for (i = 0; i < 2; i++) { // Iterate over dbg::maps and dbg::maps_user RList *maps = (i == 0) ? dbg->maps : dbg->maps_user; r_list_foreach (maps, iter, map) { switch (input[0]) { case 'j': // "dmj" print_debug_map_json (dbg, map, notfirst); notfirst = true; break; case '*': // "dm*" { char *name = (map->name && *map->name) ? r_str_newf ("%s.%s", map->name, r_str_rwx_i (map->perm)) : r_str_newf ("%08"PFMT64x".%s", map->addr, r_str_rwx_i (map->perm)); r_name_filter (name, 0); dbg->cb_printf ("f map.%s 0x%08"PFMT64x" 0x%08"PFMT64x"\n", name, map->addr_end - map->addr + 1, map->addr); free (name); } break; case 'q': // "dmq" if (input[1] == '.') { // "dmq." if (addr >= map->addr && addr < map->addr_end) { print_debug_map_line (dbg, map, addr, input); } break; } print_debug_map_line (dbg, map, addr, input); break; case '.': if (addr >= map->addr && addr < map->addr_end) { print_debug_map_line (dbg, map, addr, input); } break; default: print_debug_map_line (dbg, map, addr, input); break; } } } if (input[0] == 'j') { // "dmj" add JSON closing array brace dbg->cb_printf ("]\n"); } }
static void print_debug_maps_ascii_art(RDebug *dbg, RList *maps, ut64 addr, int colors) { ut64 mul; // The amount of address space a single console column will represent in bar graph ut64 min = -1, max = 0; int width = r_cons_get_size (NULL) - 90; RListIter *iter; RDebugMap *map; if (width < 1) { width = 30; } r_list_sort (maps, cmp); mul = findMinMax (maps, &min, &max, 0, width); ut64 last = min; if (min != -1 && mul != 0) { const char *color_prefix = ""; // Color escape code prefixed to string (address coloring) const char *color_suffix = ""; // Color escape code appended to end of string const char *fmtstr; char size_buf[56]; // Holds the human formatted size string [124K] int skip = 0; // Number of maps to skip when re-calculating the minmax r_list_foreach (maps, iter, map) { r_num_units (size_buf, map->size); // Convert map size to human readable string if (colors) { color_suffix = Color_RESET; if (map->perm & 2) { // Writable maps are red color_prefix = Color_RED; } else if (map->perm & 1) { // Executable maps are green color_prefix = Color_GREEN; } else { color_prefix = ""; color_suffix = ""; } } else { color_prefix = ""; color_suffix = ""; } if ((map->addr - last) > UT32_MAX) { // TODO: Comment what this is for mul = findMinMax (maps, &min, &max, skip, width); // Recalculate minmax } skip++; fmtstr = dbg->bits & R_SYS_BITS_64 ? // Prefix formatting string (before bar) "map %4.8s %c %s0x%016"PFMT64x"%s |" : "map %4.8s %c %s0x%08"PFMT64x"%s |"; dbg->cb_printf (fmtstr, size_buf, (addr >= map->addr && \ addr < map->addr_end) ? '*' : '-', color_prefix, map->addr, color_suffix); // * indicates map is within our current seeked offset int col; for (col = 0; col < width; col++) { // Iterate over the available width/columns for bar graph ut64 pos = min + (col * mul); // Current address space to check ut64 npos = min + ((col + 1) * mul); // Next address space to check if (map->addr < npos && map->addr_end > pos) { dbg->cb_printf ("#"); // TODO: Comment what a # represents } else { dbg->cb_printf ("-"); } } fmtstr = dbg->bits & R_SYS_BITS_64 ? // Suffix formatting string (after bar) "| %s0x%016"PFMT64x"%s %s %s\n" : "| %s0x%08"PFMT64x"%s %s %s\n"; dbg->cb_printf (fmtstr, color_prefix, map->addr_end, color_suffix, r_str_rwx_i (map->perm), map->name); last = map->addr; } }