Add support for dm commands in core dump mode. (#5930)
* add support for relative path core dump --------- Co-authored-by: NOT XVilka <notxvilka@proton.me>
This commit is contained in:
parent
33d0dcbeb2
commit
21d4084af0
15 changed files with 940 additions and 172 deletions
|
|
@ -10,6 +10,55 @@
|
|||
static bool core_file_do_load_for_debug(RzCore *r, ut64 baseaddr, const char *filenameuri);
|
||||
static bool core_file_do_load_for_io_plugin(RzCore *r, ut64 baseaddr, ut64 loadaddr);
|
||||
|
||||
/**
|
||||
* \brief Check whether the current file is a core dump
|
||||
* \param core RzCore instance
|
||||
* \return true if the current file is a core dump, false otherwise
|
||||
*/
|
||||
RZ_IPI bool rz_core_is_core_dump(RzCore *core) {
|
||||
if (!core || !core->io || !core->bin) {
|
||||
return false;
|
||||
}
|
||||
int cur_fd = rz_io_fd_get_current(core->io);
|
||||
RzBinFile *bf = rz_bin_file_find_by_fd(core->bin, cur_fd);
|
||||
if (!bf) {
|
||||
// Fallback for cases where there is no binfile bound to the current fd.
|
||||
bf = rz_bin_cur(core->bin);
|
||||
}
|
||||
RzBinPlugin *plugin = bf ? rz_bin_file_cur_plugin(bf) : NULL;
|
||||
return plugin && plugin->file_type && plugin->file_type(bf) == RZ_BIN_TYPE_CORE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Strip `[fmv]map.` prefix of a given IOMap name
|
||||
* \param map RzIOMap instance
|
||||
* \return the name without the prefix or the same name if no prefix is found.
|
||||
* NULL if map or map->name is NULL.
|
||||
*/
|
||||
RZ_IPI const char *rz_core_io_map_strip_prefix(const RzIOMap *map) {
|
||||
if (!map || !map->name) {
|
||||
return NULL;
|
||||
}
|
||||
const char *name = map->name;
|
||||
if (rz_str_startswith(name, "fmap.") ||
|
||||
rz_str_startswith(name, "mmap.") ||
|
||||
rz_str_startswith(name, "vmap.")) {
|
||||
return name + 5;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RZ_IPI const char *rz_core_io_map_file_path(const RzIOMap *map) {
|
||||
const char *name = rz_core_io_map_strip_prefix(map);
|
||||
return (name && *name == '/') ? name : NULL;
|
||||
}
|
||||
|
||||
RZ_IPI const char *rz_core_io_map_file_path_or_relative(const RzIOMap *map) {
|
||||
const char *name = rz_core_io_map_strip_prefix(map);
|
||||
// Both "/abs/path" and "rel/path" contain a '/'; LOAD0, [stack] etc. do not.
|
||||
return (name && strchr(name, '/')) ? name : NULL;
|
||||
}
|
||||
|
||||
static RzCoreFile *core_file_new(RzCore *core, int fd) {
|
||||
RzCoreFile *r = RZ_NEW0(RzCoreFile);
|
||||
if (!r) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
#include <rz_core.h>
|
||||
#include <rz_debug.h>
|
||||
#include <sdb.h>
|
||||
#include <cmd_descs.h>
|
||||
|
||||
#define TN_KEY_LEN 32
|
||||
#define TN_KEY_FMT "%" PFMT64u
|
||||
|
||||
|
|
@ -515,64 +517,118 @@ static int dump_maps(RzCore *core, int perm, const char *filename) {
|
|||
RzListIter *iter;
|
||||
rz_debug_map_sync(core->dbg); // update process memory maps
|
||||
ut64 addr = core->offset;
|
||||
int do_dump = false;
|
||||
int ret = !rz_list_empty(core->dbg->maps);
|
||||
rz_list_foreach (core->dbg->maps, iter, map) {
|
||||
do_dump = false;
|
||||
if (perm == -1) {
|
||||
if (addr >= map->addr && addr < map->addr_end) {
|
||||
do_dump = true;
|
||||
if (addr < map->addr || addr >= map->addr_end) {
|
||||
continue;
|
||||
}
|
||||
} else if (perm == 0) {
|
||||
do_dump = true;
|
||||
} else if (perm == (map->perm & perm)) {
|
||||
do_dump = true;
|
||||
} else if (perm != 0 && perm != (map->perm & perm)) {
|
||||
continue;
|
||||
}
|
||||
if (do_dump) {
|
||||
ut8 *buf = malloc(map->size);
|
||||
// TODO: use mmap here. we need a portable implementation
|
||||
if (!buf) {
|
||||
RZ_LOG_ERROR("core: Cannot allocate 0x%08" PFMT64x " bytes\n", map->size);
|
||||
free(buf);
|
||||
/// XXX: TODO: read by blocks!!1
|
||||
continue;
|
||||
}
|
||||
if (map->size > MAX_MAP_SIZE) {
|
||||
RZ_LOG_ERROR("core: map size is too big to be dumped (0x%08" PFMT64x " > 0x%08x)\n", map->addr, MAX_MAP_SIZE);
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
rz_io_read_at_mapped(core->io, map->addr, buf, map->size);
|
||||
char *file = filename
|
||||
? rz_str_dup(filename)
|
||||
: rz_str_newf("0x%08" PFMT64x "-0x%08" PFMT64x "-%s.dmp",
|
||||
map->addr, map->addr_end, rz_str_rwx_i(map->perm));
|
||||
if (!rz_file_dump(file, buf, map->size, 0)) {
|
||||
RZ_LOG_ERROR("core: Cannot write '%s'\n", file);
|
||||
ret = 0;
|
||||
} else {
|
||||
RZ_LOG_WARN("core: Dumped %d byte(s) into %s\n", (int)map->size, file);
|
||||
}
|
||||
free(file);
|
||||
|
||||
ut8 *buf = RZ_NEWS(ut8, map->size);
|
||||
// TODO: use mmap here. we need a portable implementation
|
||||
if (!buf) {
|
||||
RZ_LOG_ERROR("core: Cannot allocate 0x%08" PFMT64x " bytes\n", map->size);
|
||||
free(buf);
|
||||
/// XXX: TODO: read by blocks!!1
|
||||
continue;
|
||||
}
|
||||
if (map->size > MAX_MAP_SIZE) {
|
||||
RZ_LOG_ERROR("core: map size is too big to be dumped (0x%08" PFMT64x " > 0x%08x)\n", map->addr, MAX_MAP_SIZE);
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
rz_io_read_at_mapped(core->io, map->addr, buf, map->size);
|
||||
char *file = filename
|
||||
? rz_str_dup(filename)
|
||||
: rz_str_newf("0x%08" PFMT64x "-0x%08" PFMT64x "-%s.dmp",
|
||||
map->addr, map->addr_end, rz_str_rwx_i(map->perm));
|
||||
if (!rz_file_dump(file, buf, map->size, 0)) {
|
||||
RZ_LOG_ERROR("core: Cannot write '%s'\n", file);
|
||||
ret = 0;
|
||||
} else {
|
||||
RZ_LOG_WARN("core: Dumped %d byte(s) into %s\n", (int)map->size, file);
|
||||
}
|
||||
free(file);
|
||||
free(buf);
|
||||
}
|
||||
// eprintf ("No debug region found here\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cmd_debug_current_modules(RzCore *core, RzOutputMode mode) { // "dmm"
|
||||
#define MAX_MAP_SIZE (1024 * 1024 * 512)
|
||||
static int dump_io_maps(RzCore *core, int perm, const char *filename) {
|
||||
RzPVector *maps = rz_io_maps(core->io);
|
||||
ut64 addr = core->offset;
|
||||
int ret = !rz_pvector_empty(maps);
|
||||
void **it;
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
ut64 map_addr = map->itv.addr;
|
||||
ut64 map_size = map->itv.size;
|
||||
ut64 map_end = map_addr + map_size;
|
||||
|
||||
if (perm == -1) {
|
||||
if (addr < map_addr || addr >= map_end) {
|
||||
continue;
|
||||
}
|
||||
} else if (perm != 0 && perm != (map->perm & perm)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ut8 *buf = RZ_NEWS(ut8, map_size);
|
||||
if (!buf) {
|
||||
RZ_LOG_ERROR("core: Cannot allocate 0x%08" PFMT64x " bytes\n", map_size);
|
||||
continue;
|
||||
}
|
||||
if (map_size > MAX_MAP_SIZE) {
|
||||
RZ_LOG_ERROR("core: map size is too big to be dumped (0x%08" PFMT64x " > 0x%08x)\n", map_addr, MAX_MAP_SIZE);
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
rz_io_read_at_mapped(core->io, map_addr, buf, map_size);
|
||||
char *file = filename
|
||||
? rz_str_dup(filename)
|
||||
: rz_str_newf("0x%08" PFMT64x "-0x%08" PFMT64x "-%s.dmp",
|
||||
map_addr, map_end, rz_str_rwx_i(map->perm));
|
||||
if (!rz_file_dump(file, buf, map_size, 0)) {
|
||||
RZ_LOG_ERROR("core: Cannot write '%s'\n", file);
|
||||
ret = 0;
|
||||
} else {
|
||||
RZ_LOG_WARN("core: Dumped %d byte(s) into %s\n", (int)map_size, file);
|
||||
}
|
||||
free(file);
|
||||
free(buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cmd_debug_current_modules(RzCore *core, RzCmdStateOutput *state) { // "dmm"
|
||||
ut64 addr = core->offset;
|
||||
RzDebugMap *map;
|
||||
RzList *list;
|
||||
RzListIter *iter;
|
||||
PJ *pj = state->d.pj;
|
||||
RzOutputMode mode = state->mode;
|
||||
rz_cmd_state_output_array_start(state);
|
||||
list = rz_debug_modules_list(core->dbg);
|
||||
rz_list_foreach (list, iter, map) {
|
||||
if (!(addr >= map->addr && addr < map->addr_end)) {
|
||||
continue;
|
||||
}
|
||||
rz_cons_printf("0x%08" PFMT64x " 0x%08" PFMT64x " %s\n", map->addr, map->addr_end, map->file);
|
||||
if (mode == RZ_OUTPUT_MODE_STANDARD) {
|
||||
rz_cons_printf("0x%08" PFMT64x " 0x%08" PFMT64x " %s\n", map->addr, map->addr_end, map->file);
|
||||
} else if (mode == RZ_OUTPUT_MODE_JSON) {
|
||||
pj_o(pj);
|
||||
pj_kn(pj, "addr", map->addr);
|
||||
pj_kn(pj, "addr_end", map->addr_end);
|
||||
pj_ks(pj, "file", map->file);
|
||||
pj_end(pj);
|
||||
}
|
||||
}
|
||||
rz_cmd_state_output_array_end(state);
|
||||
rz_list_free(list);
|
||||
}
|
||||
|
||||
|
|
@ -601,6 +657,91 @@ static void cmd_debug_modules(RzCore *core, RzCmdStateOutput *state) { // "dmm"
|
|||
rz_list_free(list);
|
||||
}
|
||||
|
||||
static RZ_OWN RzPVector /*<RzIOMap *>*/ *io_map_list(RzCore *core) { // "dmm"
|
||||
RzPVector *maps = rz_io_maps(core->io);
|
||||
RzPVector *ret = rz_pvector_new(NULL);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
char *lastname = NULL;
|
||||
void **it;
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (!file) {
|
||||
continue;
|
||||
}
|
||||
if (!RZ_STR_EQ(lastname, file)) {
|
||||
rz_pvector_push(ret, map);
|
||||
free(lastname);
|
||||
lastname = rz_str_dup(file);
|
||||
}
|
||||
}
|
||||
free(lastname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cmd_io_current_modules(RzCore *core, RzCmdStateOutput *state) { // "dmm"
|
||||
ut64 addr = core->offset;
|
||||
RzPVector *maps = io_map_list(core);
|
||||
void **it;
|
||||
PJ *pj = state->d.pj;
|
||||
RzOutputMode mode = state->mode;
|
||||
rz_cmd_state_output_array_start(state);
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
ut64 map_addr = map->itv.addr;
|
||||
ut64 map_end = map_addr + map->itv.size;
|
||||
if (!(addr >= map_addr && addr < map_end)) {
|
||||
continue;
|
||||
}
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (!file) {
|
||||
file = map->name;
|
||||
}
|
||||
if (mode == RZ_OUTPUT_MODE_STANDARD) {
|
||||
rz_cons_printf("0x%08" PFMT64x " 0x%08" PFMT64x " %s\n", map_addr, map_end, file);
|
||||
} else if (mode == RZ_OUTPUT_MODE_JSON) {
|
||||
pj_o(pj);
|
||||
pj_kn(pj, "addr", map_addr);
|
||||
pj_kn(pj, "addr_end", map_end);
|
||||
pj_ks(pj, "file", file);
|
||||
pj_end(pj);
|
||||
}
|
||||
}
|
||||
rz_cmd_state_output_array_end(state);
|
||||
rz_pvector_free(maps);
|
||||
}
|
||||
|
||||
static void cmd_io_modules(RzCore *core, RzCmdStateOutput *state) { // "dmm"
|
||||
RzPVector *maps;
|
||||
void **it;
|
||||
PJ *pj = state->d.pj;
|
||||
RzOutputMode mode = state->mode;
|
||||
rz_cmd_state_output_array_start(state);
|
||||
|
||||
maps = io_map_list(core);
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (!file) {
|
||||
file = map->name;
|
||||
}
|
||||
if (mode == RZ_OUTPUT_MODE_STANDARD) {
|
||||
rz_cons_printf("0x%08" PFMT64x " 0x%08" PFMT64x " %s\n", map->itv.addr, map->itv.addr + map->itv.size, file);
|
||||
} else if (mode == RZ_OUTPUT_MODE_JSON) {
|
||||
/* Escape backslashes (e.g. for Windows). */
|
||||
pj_o(pj);
|
||||
pj_kn(pj, "addr", map->itv.addr);
|
||||
pj_kn(pj, "addr_end", map->itv.addr + map->itv.size);
|
||||
pj_ks(pj, "name", file);
|
||||
pj_end(pj);
|
||||
}
|
||||
}
|
||||
rz_cmd_state_output_array_end(state);
|
||||
rz_pvector_free(maps);
|
||||
}
|
||||
|
||||
static ut64 addroflib(RzCore *core, const char *libname) {
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
|
|
@ -642,6 +783,42 @@ static RzDebugMap *get_closest_map(RzCore *core, ut64 addr) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static RzIOMap *get_io_map_from_lib_name(RzCore *core, const char *lib_name) {
|
||||
if (!core || !lib_name) {
|
||||
return NULL;
|
||||
}
|
||||
const char *basename = rz_file_basename(lib_name);
|
||||
if (!basename) {
|
||||
return NULL;
|
||||
}
|
||||
RzIOMap *result = NULL;
|
||||
RzPVector *maps = io_map_list(core);
|
||||
void **it;
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (file && strstr(rz_file_basename(file), basename)) {
|
||||
result = map;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rz_pvector_free(maps);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
// Fall back to all IO maps
|
||||
maps = rz_io_maps(core->io);
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (file && strstr(rz_file_basename(file), basename)) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
RZ_LOG_ERROR("Unknown library '%s' not found\n", lib_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Hacky way to get the binary information of a file.
|
||||
* It opens \p file into the current core->bin (backing up the previous pointer)
|
||||
|
|
@ -679,14 +856,22 @@ static bool get_bin_info(RzCore *core, const char *file, ut64 baseaddr,
|
|||
|
||||
// dm
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_list_maps_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
||||
// dm is oml when file is a core dump
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
return rz_open_maps_list_handler(core, argc, argv, state);
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
rz_debug_map_sync(core->dbg); // update process memory maps
|
||||
rz_core_debug_map_print(core, core->offset, state);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
// dma
|
||||
// dm+
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_allocate_maps_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RZ_LOG_ERROR("Cannot allocate maps in core dump mode\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
ut64 addr = core->offset;
|
||||
int size = (int)rz_num_math(core->num, argv[1]);
|
||||
|
|
@ -696,20 +881,32 @@ RZ_IPI RzCmdStatus rz_cmd_debug_allocate_maps_handler(RzCore *core, int argc, co
|
|||
|
||||
// dmm
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_modules_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
cmd_io_modules(core, state);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
cmd_debug_modules(core, state);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
// dmm.
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_current_modules_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode) {
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_current_modules_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
cmd_io_current_modules(core, state);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
cmd_debug_current_modules(core, mode);
|
||||
cmd_debug_current_modules(core, state);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
// dm-
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_deallocate_map_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RZ_LOG_ERROR("Cannot deallocate maps in core dump mode\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
|
|
@ -727,6 +924,10 @@ RZ_IPI RzCmdStatus rz_cmd_debug_deallocate_map_handler(RzCore *core, int argc, c
|
|||
|
||||
// dm=
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_list_maps_ascii_handler(RzCore *core, int argc, const char **argv) {
|
||||
// dm= is oml= when file is a core dump
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
return rz_open_maps_list_ascii_handler(core, argc, argv);
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
rz_debug_map_sync(core->dbg);
|
||||
rz_debug_map_list_visual(core->dbg, core->offset, argv[0] + 2,
|
||||
|
|
@ -735,21 +936,33 @@ RZ_IPI RzCmdStatus rz_cmd_debug_list_maps_ascii_handler(RzCore *core, int argc,
|
|||
}
|
||||
|
||||
// dm.
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_map_current_handler(RzCore *core, int argc, const char **argv) {
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_map_current_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
||||
// dm. is oml. when file is a core dump
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
return rz_open_maps_list_cur_handler(core, argc, argv, state);
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
ut64 addr = core->offset;
|
||||
// RZ_OUTPUT_MODE_LONG is workaround for '.'
|
||||
RzCmdStateOutput state = { 0 };
|
||||
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_LONG, core);
|
||||
rz_core_debug_map_print(core, addr, &state);
|
||||
rz_cmd_state_output_print(&state);
|
||||
rz_cmd_state_output_fini(&state);
|
||||
rz_cmd_state_output_init(state, RZ_OUTPUT_MODE_LONG, core);
|
||||
rz_core_debug_map_print(core, addr, state);
|
||||
rz_cmd_state_output_print(state);
|
||||
rz_cmd_state_output_fini(state);
|
||||
rz_cons_flush();
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
// dmd
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dump_maps_handler(RzCore *core, int argc, const char **argv) {
|
||||
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
if (argc == 2) {
|
||||
dump_io_maps(core, -1, argv[1]);
|
||||
} else if (argc == 1) {
|
||||
dump_io_maps(core, -1, NULL);
|
||||
}
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
if (argc == 2) {
|
||||
dump_maps(core, -1, argv[1]);
|
||||
|
|
@ -761,6 +974,10 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dump_maps_handler(RzCore *core, int argc, const
|
|||
|
||||
// dmda
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dump_maps_all_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
dump_io_maps(core, 0, NULL);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
dump_maps(core, 0, NULL);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
|
|
@ -768,6 +985,10 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dump_maps_all_handler(RzCore *core, int argc, co
|
|||
|
||||
// dmdw
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dump_maps_writable_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
dump_io_maps(core, RZ_PERM_RW, NULL);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
dump_maps(core, RZ_PERM_RW, NULL);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
|
|
@ -789,21 +1010,41 @@ static RzDebugMap *get_debug_map_from_lib_name(RzCore *core, const char *lib_nam
|
|||
}
|
||||
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dmi_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
|
||||
if (argc == 1) {
|
||||
// Effectively an alias for 'dmm'
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
cmd_io_modules(core, state);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
cmd_debug_modules(core, state);
|
||||
rz_cmd_state_output_print(state);
|
||||
rz_cons_flush();
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
const char *lib_name = argc >= 2 ? argv[1] : NULL;
|
||||
const char *sym_name = argc == 3 ? argv[2] : NULL;
|
||||
|
||||
RzCoreBinFilter filter = { .offset = UT64_MAX, .name = sym_name };
|
||||
int action = RZ_CORE_BIN_ACC_SYMBOLS;
|
||||
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RzIOMap *map = get_io_map_from_lib_name(core, lib_name);
|
||||
if (!map) {
|
||||
RZ_LOG_ERROR("Failed to get map from %s\n", lib_name);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (!file) {
|
||||
file = map->name;
|
||||
}
|
||||
if (!get_bin_info(core, file, map->itv.addr, state, action, &filter)) {
|
||||
RZ_LOG_ERROR("Failed to get binary information for map: '%s' in file: '%s'\n", map->name, file);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzDebugMap *map = get_debug_map_from_lib_name(core, lib_name);
|
||||
if (!map) {
|
||||
RZ_LOG_ERROR("Failed to get map from %s\n", lib_name);
|
||||
|
|
@ -818,22 +1059,48 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dmi_handler(RzCore *core, int argc, const char *
|
|||
}
|
||||
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dmi_all_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
if (argc == 1) {
|
||||
// Effectively an alias for 'dmm'
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
cmd_io_modules(core, state);
|
||||
rz_cmd_state_output_print(state);
|
||||
rz_cons_flush();
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
cmd_debug_modules(core, state);
|
||||
rz_cmd_state_output_print(state);
|
||||
rz_cons_flush();
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
const char *lib_name = argv[1];
|
||||
RzCoreBinFilter filter = { .offset = UT64_MAX, .name = NULL };
|
||||
int action = RZ_CORE_BIN_ACC_ALL & ~RZ_CORE_BIN_ACC_INFO;
|
||||
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RzIOMap *map = get_io_map_from_lib_name(core, lib_name);
|
||||
if (!map) {
|
||||
RZ_LOG_ERROR("Failed to get map from %s\n", lib_name);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (!file) {
|
||||
file = map->name;
|
||||
}
|
||||
if (!get_bin_info(core, file, map->itv.addr, state, action, &filter)) {
|
||||
RZ_LOG_ERROR("Failed to get binary information for map: '%s' in file: '%s'\n", map->name, file);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzDebugMap *map = get_debug_map_from_lib_name(core, lib_name);
|
||||
if (!map) {
|
||||
RZ_LOG_ERROR("Failed to get map from %s\n", lib_name);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
const char *file = map->file ? map->file : map->name;
|
||||
RzCoreBinFilter filter = { .offset = UT64_MAX, .name = NULL };
|
||||
int action = RZ_CORE_BIN_ACC_ALL & ~RZ_CORE_BIN_ACC_INFO;
|
||||
if (!get_bin_info(core, file, map->addr, state, action, &filter)) {
|
||||
RZ_LOG_ERROR("Failed to get binary information for map: '%s' in file: '%s'\n", map->name, file);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
|
|
@ -886,6 +1153,10 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dmi_closest_handler(RzCore *core, int argc, cons
|
|||
|
||||
// dmp
|
||||
RZ_IPI RzCmdStatus rz_debug_memory_permission_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RZ_LOG_ERROR("Cannot change memory permissions in core dump mode\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
|
|
@ -915,10 +1186,36 @@ RZ_IPI RzCmdStatus rz_debug_memory_permission_handler(RzCore *core, int argc, co
|
|||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
static void rz_cmd_debug_dmS_handler_printer(ut64 baddr, const char *file, const char *sectname, RzOutputMode mode) {
|
||||
char *res;
|
||||
char *name = rz_str_escape((char *)rz_file_basename(file));
|
||||
char *filesc = rz_str_escape(file);
|
||||
char *old_prefix = rz_sys_getenv("RZ_BIN_PREFIX");
|
||||
rz_sys_setenv("RZ_BIN_PREFIX", name);
|
||||
|
||||
const char *json_flag = (mode == RZ_OUTPUT_MODE_JSON) ? " -j" : "";
|
||||
|
||||
if (sectname && mode != RZ_OUTPUT_MODE_JSON) {
|
||||
char *sect = rz_str_escape(sectname);
|
||||
res = rz_sys_cmd_strf("rz-bin%s -B 0x%08" PFMT64x " -S \"%s\" | grep \"%s\"", json_flag, baddr, filesc, sect);
|
||||
free(sect);
|
||||
} else {
|
||||
res = rz_sys_cmd_strf("rz-bin%s -B 0x%08" PFMT64x " -S \"%s\"", json_flag, baddr, filesc);
|
||||
}
|
||||
if (res) {
|
||||
rz_str_remove_char(res, '\r');
|
||||
}
|
||||
rz_sys_setenv("RZ_BIN_PREFIX", old_prefix);
|
||||
free(old_prefix);
|
||||
free(filesc);
|
||||
if (res) {
|
||||
rz_cons_println(res);
|
||||
}
|
||||
free(name);
|
||||
free(res);
|
||||
}
|
||||
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dmS_handler(RzCore *core, int argc, const char **argv, RzOutputMode m) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
ut64 addr;
|
||||
const char *libname = NULL, *sectname = NULL;
|
||||
ut64 baddr = 0LL;
|
||||
|
|
@ -937,6 +1234,35 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dmS_handler(RzCore *core, int argc, const char *
|
|||
libname = argv[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RzPVector *maps = io_map_list(core);
|
||||
void **it;
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
ut64 map_addr = map->itv.addr;
|
||||
ut64 map_end = map_addr + map->itv.size;
|
||||
if ((!libname ||
|
||||
(addr != UT64_MAX && (addr >= map_addr && addr < map_end)) ||
|
||||
(libname != NULL && (strstr(map->name, libname))))) {
|
||||
baddr = map_addr;
|
||||
const char *file = rz_core_io_map_file_path_or_relative(map);
|
||||
if (!file) {
|
||||
file = map->name;
|
||||
}
|
||||
rz_cmd_debug_dmS_handler_printer(baddr, file, sectname, m);
|
||||
if (libname || addr != UT64_MAX) { // only single match requested
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rz_pvector_free(maps);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzDebugMap *map;
|
||||
RzListIter *iter;
|
||||
rz_debug_map_sync(core->dbg); // update process memory maps
|
||||
RzList *list = rz_debug_modules_list(core->dbg);
|
||||
rz_list_foreach (list, iter, map) {
|
||||
|
|
@ -944,22 +1270,8 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dmS_handler(RzCore *core, int argc, const char *
|
|||
(addr != UT64_MAX && (addr >= map->addr && addr < map->addr_end)) ||
|
||||
(libname != NULL && (strstr(map->name, libname))))) {
|
||||
baddr = map->addr;
|
||||
char *res;
|
||||
const char *file = map->file ? map->file : map->name;
|
||||
char *name = rz_str_escape((char *)rz_file_basename(file));
|
||||
char *filesc = rz_str_escape(file);
|
||||
/* TODO: do not spawn. use RzBin API */
|
||||
if (sectname) {
|
||||
char *sect = rz_str_escape(sectname);
|
||||
res = rz_sys_cmd_strf("env RZ_BIN_PREFIX=\"%s\" rz-bin -B 0x%08" PFMT64x " -S \"%s\" | grep \"%s\"", name, baddr, filesc, sect);
|
||||
free(sect);
|
||||
} else {
|
||||
res = rz_sys_cmd_strf("env RZ_BIN_PREFIX=\"%s\" rz-bin -B 0x%08" PFMT64x " -S \"%s\"", name, baddr, filesc);
|
||||
}
|
||||
free(filesc);
|
||||
rz_cons_println(res);
|
||||
free(name);
|
||||
free(res);
|
||||
rz_cmd_debug_dmS_handler_printer(baddr, file, sectname, m);
|
||||
if (libname || addr != UT64_MAX) { // only single match requested
|
||||
break;
|
||||
}
|
||||
|
|
@ -970,6 +1282,10 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dmS_handler(RzCore *core, int argc, const char *
|
|||
|
||||
// dml
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dml_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RZ_LOG_ERROR("Cannot load into memory in core dump mode\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
|
|
@ -1001,6 +1317,10 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dml_handler(RzCore *core, int argc, const char *
|
|||
|
||||
// dmL
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_dmL_handler(RzCore *core, int argc, const char **argv) {
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
RZ_LOG_ERROR("Cannot allocate maps in core dump mode\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
int size;
|
||||
ut64 addr;
|
||||
|
|
@ -1013,35 +1333,33 @@ RZ_IPI RzCmdStatus rz_cmd_debug_dmL_handler(RzCore *core, int argc, const char *
|
|||
// "dmxa"
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_heap_jemalloc_a_handler(RzCore *core, int argc, const char **argv) {
|
||||
bool has_specified_arena = argc > 1 && RZ_STR_ISNOTEMPTY(argv[1]);
|
||||
ut64 arena_addr = 0;
|
||||
|
||||
// Only check debug mode when no argument is provided (symbol resolution needed)
|
||||
// With address arguments we can still work in static mode
|
||||
if (!has_specified_arena) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
} else if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid arena address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
} else {
|
||||
arena_addr = rz_num_math(core->num, argv[1]);
|
||||
if (has_specified_arena) {
|
||||
if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid arena address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
ut64 arena_addr = rz_num_math(core->num, argv[1]);
|
||||
return rz_heap_jemalloc_cmd_a(core, has_specified_arena, arena_addr);
|
||||
}
|
||||
|
||||
return rz_heap_jemalloc_cmd_a(core, has_specified_arena, arena_addr);
|
||||
if (!rz_core_is_core_dump(core)) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
}
|
||||
return rz_heap_jemalloc_cmd_a(core, has_specified_arena, 0);
|
||||
}
|
||||
|
||||
// "dmxb"
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_heap_jemalloc_b_handler(RzCore *core, int argc, const char **argv) {
|
||||
bool has_specified_arena = argc > 1 && RZ_STR_ISNOTEMPTY(argv[1]);
|
||||
bool has_bin_info = argc > 2 && RZ_STR_ISNOTEMPTY(argv[2]);
|
||||
ut64 arena_addr = 0;
|
||||
ut64 bin_info_addr = 0;
|
||||
|
||||
if (!has_specified_arena) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
} else if (!has_bin_info) {
|
||||
RZ_LOG_ERROR("Usage: dmxb <arena_addr> <bin_info_addr>\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
} else {
|
||||
if (has_specified_arena) {
|
||||
ut64 arena_addr = 0;
|
||||
ut64 bin_info_addr = 0;
|
||||
if (!has_bin_info) {
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid arena address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
|
|
@ -1052,43 +1370,53 @@ RZ_IPI RzCmdStatus rz_cmd_debug_heap_jemalloc_b_handler(RzCore *core, int argc,
|
|||
}
|
||||
arena_addr = rz_num_math(core->num, argv[1]);
|
||||
bin_info_addr = rz_num_math(core->num, argv[2]);
|
||||
|
||||
return rz_heap_jemalloc_cmd_b(core, has_specified_arena, arena_addr, has_bin_info, bin_info_addr);
|
||||
}
|
||||
|
||||
return rz_heap_jemalloc_cmd_b(core, has_specified_arena, arena_addr, has_bin_info, bin_info_addr);
|
||||
if (!rz_core_is_core_dump(core)) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
}
|
||||
|
||||
return rz_heap_jemalloc_cmd_b(core, has_specified_arena, 0, has_bin_info, 0);
|
||||
}
|
||||
|
||||
// "dmxc"
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_heap_jemalloc_c_handler(RzCore *core, int argc, const char **argv) {
|
||||
bool has_specified_arena = argc > 1 && RZ_STR_ISNOTEMPTY(argv[1]);
|
||||
ut64 arena_addr = 0;
|
||||
|
||||
if (!has_specified_arena) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
} else if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid arena address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
} else {
|
||||
arena_addr = rz_num_math(core->num, argv[1]);
|
||||
if (has_specified_arena) {
|
||||
if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid arena address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
ut64 arena_addr = rz_num_math(core->num, argv[1]);
|
||||
return rz_heap_jemalloc_cmd_c(core, has_specified_arena, arena_addr);
|
||||
}
|
||||
|
||||
return rz_heap_jemalloc_cmd_c(core, has_specified_arena, arena_addr);
|
||||
if (!rz_core_is_core_dump(core)) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
}
|
||||
return rz_heap_jemalloc_cmd_c(core, has_specified_arena, 0);
|
||||
}
|
||||
|
||||
// "dmxe" - Find extent for malloc address
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_heap_jemalloc_e_handler(RzCore *core, int argc, const char **argv) {
|
||||
bool has_addr = argc > 1 && RZ_STR_ISNOTEMPTY(argv[1]);
|
||||
ut64 lookup_addr = 0;
|
||||
|
||||
if (!has_addr) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
} else if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
} else {
|
||||
lookup_addr = rz_num_math(core->num, argv[1]);
|
||||
if (has_addr) {
|
||||
if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
RZ_LOG_ERROR("Invalid address '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
ut64 lookup_addr = rz_num_math(core->num, argv[1]);
|
||||
return rz_heap_jemalloc_cmd_e(core, has_addr, lookup_addr);
|
||||
}
|
||||
|
||||
return rz_heap_jemalloc_cmd_e(core, has_addr, lookup_addr);
|
||||
if (!rz_core_is_core_dump(core)) {
|
||||
CMD_CHECK_DEBUG_DEAD(core);
|
||||
}
|
||||
return rz_heap_jemalloc_cmd_e(core, has_addr, 0);
|
||||
}
|
||||
|
||||
// "dmxei" - Display extent info
|
||||
|
|
@ -1097,7 +1425,6 @@ RZ_IPI RzCmdStatus rz_cmd_debug_heap_jemalloc_ei_handler(RzCore *core, int argc,
|
|||
ut64 extent_addr = 0;
|
||||
|
||||
if (!has_addr) {
|
||||
RZ_LOG_ERROR("Usage: dmxei <edata_addr>\n");
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
if (!rz_num_is_valid_input(core->num, argv[1])) {
|
||||
|
|
|
|||
|
|
@ -784,8 +784,11 @@ commands:
|
|||
args: []
|
||||
- name: dm.
|
||||
cname: cmd_debug_map_current
|
||||
type: RZ_CMD_DESC_TYPE_ARGV_STATE
|
||||
summary: Show map name of current address
|
||||
args: []
|
||||
modes:
|
||||
- RZ_OUTPUT_MODE_STANDARD
|
||||
- name: dmm
|
||||
summary: Module memory map commands
|
||||
subcommands:
|
||||
|
|
@ -799,8 +802,10 @@ commands:
|
|||
args: []
|
||||
- name: dmm.
|
||||
cname: cmd_debug_current_modules
|
||||
type: RZ_CMD_DESC_TYPE_ARGV_STATE
|
||||
modes:
|
||||
- RZ_OUTPUT_MODE_STANDARD
|
||||
- RZ_OUTPUT_MODE_JSON
|
||||
summary: List memory map of current module
|
||||
args: []
|
||||
- name: dm-
|
||||
|
|
@ -899,6 +904,7 @@ commands:
|
|||
cname: cmd_debug_dmS
|
||||
modes:
|
||||
- RZ_OUTPUT_MODE_STANDARD
|
||||
- RZ_OUTPUT_MODE_JSON
|
||||
args:
|
||||
- name: addr|libname
|
||||
type: RZ_CMD_ARG_TYPE_STRING
|
||||
|
|
|
|||
|
|
@ -23352,12 +23352,12 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
|
|||
RzCmdDesc *cmd_debug_list_maps_ascii_cd = rz_cmd_desc_argv_new(core->rcmd, dm_cd, "dm=", rz_cmd_debug_list_maps_ascii_handler, &cmd_debug_list_maps_ascii_help);
|
||||
rz_warn_if_fail(cmd_debug_list_maps_ascii_cd);
|
||||
|
||||
RzCmdDesc *cmd_debug_map_current_cd = rz_cmd_desc_argv_new(core->rcmd, dm_cd, "dm.", rz_cmd_debug_map_current_handler, &cmd_debug_map_current_help);
|
||||
RzCmdDesc *cmd_debug_map_current_cd = rz_cmd_desc_argv_state_new(core->rcmd, dm_cd, "dm.", RZ_OUTPUT_MODE_STANDARD, rz_cmd_debug_map_current_handler, &cmd_debug_map_current_help);
|
||||
rz_warn_if_fail(cmd_debug_map_current_cd);
|
||||
|
||||
RzCmdDesc *dmm_cd = rz_cmd_desc_group_state_new(core->rcmd, dm_cd, "dmm", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_debug_modules_handler, &cmd_debug_modules_help, &dmm_help);
|
||||
rz_warn_if_fail(dmm_cd);
|
||||
RzCmdDesc *cmd_debug_current_modules_cd = rz_cmd_desc_argv_modes_new(core->rcmd, dmm_cd, "dmm.", RZ_OUTPUT_MODE_STANDARD, rz_cmd_debug_current_modules_handler, &cmd_debug_current_modules_help);
|
||||
RzCmdDesc *cmd_debug_current_modules_cd = rz_cmd_desc_argv_state_new(core->rcmd, dmm_cd, "dmm.", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_debug_current_modules_handler, &cmd_debug_current_modules_help);
|
||||
rz_warn_if_fail(cmd_debug_current_modules_cd);
|
||||
|
||||
RzCmdDesc *cmd_debug_deallocate_map_cd = rz_cmd_desc_argv_new(core->rcmd, dm_cd, "dm-", rz_cmd_debug_deallocate_map_handler, &cmd_debug_deallocate_map_help);
|
||||
|
|
@ -23417,7 +23417,7 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
|
|||
RzCmdDesc *cmd_debug_dmL_cd = rz_cmd_desc_argv_new(core->rcmd, dm_cd, "dmL", rz_cmd_debug_dmL_handler, &cmd_debug_dmL_help);
|
||||
rz_warn_if_fail(cmd_debug_dmL_cd);
|
||||
|
||||
RzCmdDesc *cmd_debug_dmS_cd = rz_cmd_desc_argv_modes_new(core->rcmd, dm_cd, "dmS", RZ_OUTPUT_MODE_STANDARD, rz_cmd_debug_dmS_handler, &cmd_debug_dmS_help);
|
||||
RzCmdDesc *cmd_debug_dmS_cd = rz_cmd_desc_argv_modes_new(core->rcmd, dm_cd, "dmS", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_debug_dmS_handler, &cmd_debug_dmS_help);
|
||||
rz_warn_if_fail(cmd_debug_dmS_cd);
|
||||
|
||||
RzCmdDesc *dmw_cd = rz_cmd_desc_group_modes_new(core->rcmd, dm_cd, "dmw", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON, rz_cmd_debug_process_heaps_handler, &cmd_debug_process_heaps_help, &dmw_help);
|
||||
|
|
|
|||
|
|
@ -1312,11 +1312,11 @@ RZ_IPI RzCmdStatus rz_cmd_debug_allocate_maps_handler(RzCore *core, int argc, co
|
|||
// "dm="
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_list_maps_ascii_handler(RzCore *core, int argc, const char **argv);
|
||||
// "dm."
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_map_current_handler(RzCore *core, int argc, const char **argv);
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_map_current_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
// "dmm"
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_modules_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
// "dmm."
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_current_modules_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode);
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_current_modules_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
|
||||
// "dm-"
|
||||
RZ_IPI RzCmdStatus rz_cmd_debug_deallocate_map_handler(RzCore *core, int argc, const char **argv);
|
||||
// "dmd"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ RZ_DEPRECATE RZ_IPI const char *rz_core_get_parser(RzCore *core);
|
|||
RZ_IPI void rz_core_kuery_print(RzCore *core, const char *k);
|
||||
RZ_IPI int rz_output_mode_to_char(RzOutputMode mode);
|
||||
RZ_IPI void rz_core_print_warnings_after(RZ_NONNULL RzCore *core);
|
||||
RZ_IPI bool rz_core_is_core_dump(RzCore *core);
|
||||
RZ_IPI const char *rz_core_io_map_strip_prefix(const RzIOMap *map);
|
||||
RZ_IPI const char *rz_core_io_map_file_path(const RzIOMap *map);
|
||||
RZ_IPI const char *rz_core_io_map_file_path_or_relative(const RzIOMap *map);
|
||||
|
||||
RZ_IPI int bb_cmpaddr(const void *_a, const void *_b, void *user);
|
||||
RZ_IPI int fcn_cmpaddr(const void *_a, const void *_b, void *user);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "core_private.h"
|
||||
|
||||
void print_heap_chunk_simple(RzCore *core, ut64 chunk, const char *status, PJ *pj, const RzHeapConfig *config);
|
||||
static void rz_heap_get_brks(RzCore *core, ut64 *brk_start, ut64 *brk_end);
|
||||
static bool rz_heap_get_brks(RzCore *core, ut64 *brk_start, ut64 *brk_end);
|
||||
static inline bool init_glibc_config(RzCore *core, RzHeapConfig *config);
|
||||
static ut64 rz_heap_get_main_arena_with_symbol(RzCore *core, RzDebugMap *map);
|
||||
static bool rz_heap_is_arena(RzCore *core, ut64 m_arena, ut64 m_state, const RzHeapConfig *config);
|
||||
|
|
@ -150,6 +150,10 @@ static inline ut64 rz_heap_get_next_pointer(RzCore *core, ut64 pos, ut64 next, c
|
|||
: next;
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_heap_is_map_name_libc(const char *map_name) {
|
||||
return map_name && (strstr(map_name, "/libc-") || strstr(map_name, "/libc."));
|
||||
}
|
||||
|
||||
static ut64 rz_heap_get_main_arena_with_symbol(RzCore *core, RzDebugMap *map) {
|
||||
rz_return_val_if_fail(core && map, UT64_MAX);
|
||||
ut64 base_addr = map->addr;
|
||||
|
|
@ -206,6 +210,24 @@ beach:
|
|||
return main_arena;
|
||||
}
|
||||
|
||||
static ut64 rz_heap_get_main_arena_with_symbol_core_dump(RzCore *core, RzIOMap *map) {
|
||||
rz_return_val_if_fail(core && map, UT64_MAX);
|
||||
ut64 base_addr = map->itv.addr;
|
||||
rz_return_val_if_fail(base_addr != UT64_MAX, UT64_MAX);
|
||||
|
||||
ut64 main_arena = UT64_MAX;
|
||||
ut64 off = UT64_MAX;
|
||||
const char *path = rz_core_io_map_file_path_or_relative(map);
|
||||
if (path && rz_file_exists(path)) {
|
||||
off = rz_heap_get_va_symbol(core, path, "main_arena");
|
||||
if (off != UT64_MAX) {
|
||||
main_arena = base_addr + off;
|
||||
return main_arena;
|
||||
}
|
||||
}
|
||||
return UT64_MAX;
|
||||
}
|
||||
|
||||
static ut8 *get_glibc_banner(RzCore *core, const char *section_name,
|
||||
const char *libc_path) {
|
||||
RzPVector *sections = NULL;
|
||||
|
|
@ -507,7 +529,116 @@ bool rz_heap_update_main_arena_internal(RzCore *core, ut64 m_arena, MallocState
|
|||
return true;
|
||||
}
|
||||
|
||||
static void rz_heap_get_brks(RzCore *core, ut64 *brk_start, ut64 *brk_end) {
|
||||
/**
|
||||
* \brief Check if an IOMap corresponds to an anonymous LOAD segment.
|
||||
*
|
||||
* An anonymous LOAD segment is a memory mapping that is not backed by a
|
||||
* named file. It is identified by a name starting with "LOAD" followed only
|
||||
* by digits.
|
||||
*
|
||||
* \param map RzIOMap instance
|
||||
* \return true if the map is an anonymous LOAD segment, false otherwise
|
||||
*/
|
||||
static bool io_map_is_anonymous_load(const RzIOMap *map) {
|
||||
const char *name = rz_core_io_map_strip_prefix(map);
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
if (!rz_str_startswith(name, "LOAD")) {
|
||||
return false;
|
||||
}
|
||||
const char *p = name + 4;
|
||||
if (*p == '\0') {
|
||||
return false;
|
||||
}
|
||||
while (*p) {
|
||||
if (*p < '0' || *p > '9') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* In debug mode, we can locate the heap by the `[heap]` label:
|
||||
* [0xaaaaea80094c]> dm
|
||||
* 0x0000aaaaea800000 - 0x0000aaaaea801000 * usr 4K s r-x /rizin/test/bins/heap/segfault-heap-aarch64 /rizin/test/bins/heap/segfault-heap-aarch64 ; rizin_test_bins_heap_segfault_heap_aarch64.r_x
|
||||
* 0x0000aaaaea81f000 - 0x0000aaaaea820000 - usr 4K s r-- /rizin/test/bins/heap/segfault-heap-aarch64 /rizin/test/bins/heap/segfault-heap-aarch64 ; rizin_test_bins_heap_segfault_heap_aarch64.rw
|
||||
* 0x0000aaaaea820000 - 0x0000aaaaea821000 - usr 4K s rw- /rizin/test/bins/heap/segfault-heap-aarch64 /rizin/test/bins/heap/segfault-heap-aarch64 ; loc.__data_start
|
||||
* 0x0000aaab0f265000 - 0x0000aaab0f286000 - usr 132K s rw- [heap] [heap]
|
||||
* 0x0000ffff9ac40000 - 0x0000ffff9add9000 - usr 1.6M s r-x /usr/lib/aarch64-linux-gnu/libc.so.6 /usr/lib/aarch64-linux-gnu/libc.so.6
|
||||
* 0x0000ffff9add9000 - 0x0000ffff9aded000 - usr 80K s --- /usr/lib/aarch64-linux-gnu/libc.so.6 /usr/lib/aarch64-linux-gnu/libc.so.6
|
||||
* But in core dumps, the [heap] label doesn't exist:
|
||||
* [0x00000840]> dm
|
||||
* 1 fd: 4 +0x00000000 0xaaaae3c60000 - 0xaaaae3c60fff r-x mmap./run/host_virtiofs/Users/bubblepipe/repo/rizin/test/bins/heap/segfault-heap-aarch64
|
||||
* 2 fd: 3 +0x00002000 0xaaaae3c7f000 - 0xaaaae3c7ffff r-- fmap./run/host_virtiofs/Users/bubblepipe/repo/rizin/test/bins/heap/segfault-heap-aarch64
|
||||
* 3 fd: 3 +0x00003000 0xaaaae3c80000 - 0xaaaae3c80fff r-- fmap./run/host_virtiofs/Users/bubblepipe/repo/rizin/test/bins/heap/segfault-heap-aarch64
|
||||
* 4 fd: 3 +0x00004000 0xaaab126cd000 - 0xaaab126edfff r-- fmap.LOAD3
|
||||
* 5 fd: 5 +0x00000000 0xffff9a5d0000 - 0xffff9a768fff r-x mmap./usr/lib/aarch64-linux-gnu/libc.so.6
|
||||
* We identify the brk heap as the first anonymous LOAD segment after the main executable's last mapping.
|
||||
* This works because the kernel places the brk region right after the program's
|
||||
* data segment, while other regions are placed at a much higher address range.
|
||||
*
|
||||
* Source: https://man7.org/linux/man-pages/man2/brk.2.html
|
||||
* "brk() and sbrk() change the location of the program break, which
|
||||
* defines the end of the process's data segment (i.e., the program
|
||||
* break is the first location after the end of the uninitialized
|
||||
* data segment). Increasing the program break has the effect of
|
||||
* allocating memory to the process; decreasing the break deallocates
|
||||
* memory."
|
||||
*/
|
||||
static bool rz_heap_get_brks_core_dump(RzCore *core, ut64 *brk_start, ut64 *brk_end) {
|
||||
RzPVector *maps = rz_io_maps(core->io);
|
||||
if (!maps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// identify the main executable's file path:
|
||||
// the first file-backed mapping (low address) that
|
||||
// is not a special region like [stack], [vdso], etc.
|
||||
const char *exe_path = NULL;
|
||||
ut64 lowest_addr = UT64_MAX;
|
||||
void **it;
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
const char *path = rz_core_io_map_file_path_or_relative(map);
|
||||
if (path && map->itv.addr < lowest_addr) {
|
||||
lowest_addr = map->itv.addr;
|
||||
exe_path = path;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exe_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the end of all mappings belonging to the executable
|
||||
ut64 exe_end = 0;
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
const char *path = rz_core_io_map_file_path_or_relative(map);
|
||||
if (path && !strcmp(path, exe_path)) {
|
||||
ut64 end = map->itv.addr + map->itv.size;
|
||||
if (end > exe_end) {
|
||||
exe_end = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find the first anonymous LOAD segment after the executable
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
if (map->itv.addr > exe_end && io_map_is_anonymous_load(map)) {
|
||||
*brk_start = map->itv.addr;
|
||||
*brk_end = map->itv.addr + map->itv.size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rz_heap_get_brks(RzCore *core, ut64 *brk_start, ut64 *brk_end) {
|
||||
if (rz_config_get_b(core->config, "cfg.debug")) {
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
|
|
@ -517,7 +648,7 @@ static void rz_heap_get_brks(RzCore *core, ut64 *brk_start, ut64 *brk_end) {
|
|||
if (strstr(map->name, "[heap]")) {
|
||||
*brk_start = map->addr;
|
||||
*brk_end = map->addr_end;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -530,11 +661,13 @@ static void rz_heap_get_brks(RzCore *core, ut64 *brk_start, ut64 *brk_end) {
|
|||
if (strstr(map->name, "[heap]")) {
|
||||
*brk_start = map->itv.addr;
|
||||
*brk_end = map->itv.addr + map->itv.size;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rz_heap_get_brks_core_dump(core, brk_start, brk_end);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void print_arena_stats(RzCore *core, ut64 m_arena, MallocState *main_arena, ut64 global_max_fast, int format, const RzHeapConfig *config) {
|
||||
|
|
@ -661,10 +794,6 @@ static void print_arena_stats(RzCore *core, ut64 m_arena, MallocState *main_aren
|
|||
PRINT_GA("}\n\n");
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_heap_is_map_name_libc(const char *map_name) {
|
||||
return strstr(map_name, "/libc-") || strstr(map_name, "/libc.");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Store the base address of main arena at m_arena
|
||||
* \param core RzCore pointer
|
||||
|
|
@ -704,6 +833,31 @@ RZ_API bool rz_heap_resolve_main_arena(RzCore *core, ut64 *m_arena) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (rz_core_is_core_dump(core)) {
|
||||
void **it;
|
||||
RzPVector *maps = rz_io_maps(core->io);
|
||||
rz_pvector_foreach (maps, it) {
|
||||
RzIOMap *map = *it;
|
||||
if (map->name && strstr(map->name, "arena")) {
|
||||
libc_addr_sta = map->itv.addr;
|
||||
libc_addr_end = map->itv.addr + map->itv.size;
|
||||
break;
|
||||
}
|
||||
/* Try to find the main arena address using the glibc's symbols. */
|
||||
if (rz_heap_is_map_name_libc(map->name) && first_libc && main_arena_sym == UT64_MAX) {
|
||||
first_libc = false;
|
||||
main_arena_sym = rz_heap_get_main_arena_with_symbol_core_dump(core, map);
|
||||
}
|
||||
if (rz_heap_is_map_name_libc(map->name)) {
|
||||
if (map->itv.addr < libc_addr_sta) {
|
||||
libc_addr_sta = map->itv.addr;
|
||||
}
|
||||
ut64 end = map->itv.addr + map->itv.size;
|
||||
if (end > libc_addr_end) {
|
||||
libc_addr_end = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
void **it;
|
||||
RzPVector *maps = rz_io_maps(core->io);
|
||||
|
|
@ -717,7 +871,7 @@ RZ_API bool rz_heap_resolve_main_arena(RzCore *core, ut64 *m_arena) {
|
|||
}
|
||||
}
|
||||
|
||||
if (libc_addr_sta == UT64_MAX || libc_addr_end == UT64_MAX) {
|
||||
if (libc_addr_sta == UT64_MAX || libc_addr_end == 0) {
|
||||
if (rz_config_get_b(core->config, "cfg.debug")) {
|
||||
RZ_LOG_WARN("core: Can't find glibc mapped in memory (see dm)\n");
|
||||
} else {
|
||||
|
|
@ -726,8 +880,7 @@ RZ_API bool rz_heap_resolve_main_arena(RzCore *core, ut64 *m_arena) {
|
|||
return false;
|
||||
}
|
||||
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
if (brk_start == UT64_MAX || brk_end == UT64_MAX) {
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
RZ_LOG_ERROR("core: no heap section\n");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -894,7 +1047,7 @@ static void resolve_tcache_perthread(RZ_NONNULL RzCore *core, const RzHeapConfig
|
|||
RZ_API RZ_OWN bool resolve_heap_tcache(RZ_NONNULL RzCore *core, ut64 arena_base, const RzHeapConfig *config) {
|
||||
RzDebug *dbg = core->dbg;
|
||||
|
||||
if (dbg->threads) {
|
||||
if (rz_config_get_b(core->config, "cfg.debug") && dbg->threads) {
|
||||
resolve_tcache_perthread(core, config);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1233,8 +1386,7 @@ static int print_double_linked_list_bin(RzCore *core, MallocState *main_arena, u
|
|||
return -1;
|
||||
}
|
||||
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
if (brk_start == UT64_MAX || brk_end == UT64_MAX) {
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
RZ_LOG_ERROR("core: no heap section\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1333,10 +1485,9 @@ RzHeapBin *rz_heap_fastbin_content_internal(RzCore *core, MallocState *arena, in
|
|||
if (!next) {
|
||||
return heap_bin;
|
||||
}
|
||||
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
heap_bin->fd = next;
|
||||
if (brk_start == UT64_MAX || brk_end == UT64_MAX) {
|
||||
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
return heap_bin;
|
||||
}
|
||||
|
||||
|
|
@ -1486,8 +1637,7 @@ RzList /*<RzHeapBin *>*/ *rz_heap_tcache_content_internal(RzCore *core, ut64 are
|
|||
}
|
||||
|
||||
ut64 brk_start = UT64_MAX, brk_end = UT64_MAX;
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
if (brk_start == UT64_MAX || brk_end == UT64_MAX) {
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1713,8 +1863,7 @@ RzHeapBin *rz_heap_bin_content_internal(RzCore *core, MallocState *arena, int bi
|
|||
}
|
||||
|
||||
ut64 brk_start = UT64_MAX, brk_end = UT64_MAX, initial_brk = UT64_MAX;
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
if (brk_start == UT64_MAX || brk_end == UT64_MAX) {
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
return bin;
|
||||
}
|
||||
|
||||
|
|
@ -2052,12 +2201,12 @@ RzList /*<RzHeapChunkListItem *>*/ *rz_heap_chunks_list_internal(RzCore *core, M
|
|||
RzConsPrintablePalette *pal = &rz_cons_singleton()->context->pal;
|
||||
|
||||
if (m_arena == m_state) {
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
return chunks;
|
||||
}
|
||||
if (tcache) {
|
||||
initial_brk = ((brk_start >> 12) << 12) + config->chunk_hdr_size;
|
||||
if (rz_config_get_b(core->config, "cfg.debug")) {
|
||||
tcache_initial_brk = initial_brk;
|
||||
}
|
||||
tcache_initial_brk = initial_brk;
|
||||
initial_brk += config->tcache.struct_size;
|
||||
} else {
|
||||
initial_brk = (brk_start >> 12) << 12;
|
||||
|
|
@ -2112,8 +2261,8 @@ RzList /*<RzHeapChunkListItem *>*/ *rz_heap_chunks_list_internal(RzCore *core, M
|
|||
if (fastbin) {
|
||||
int i = (size_tmp / (ptr_size * 2)) - 2;
|
||||
ut64 idx = (ut64)main_arena->fastbinsY[i];
|
||||
if (!rz_glibc_read_chunk(core->io, idx, &cnk, config)) {
|
||||
continue;
|
||||
if (!idx || !rz_glibc_read_chunk(core->io, idx, &cnk, config)) {
|
||||
goto skip_fastbin;
|
||||
}
|
||||
ut64 next = rz_heap_get_next_pointer(core, idx, cnk.fd, config);
|
||||
if (prev_chunk == idx && idx && !next) {
|
||||
|
|
@ -2127,7 +2276,7 @@ RzList /*<RzHeapChunkListItem *>*/ *rz_heap_chunks_list_internal(RzCore *core, M
|
|||
break;
|
||||
}
|
||||
if (!rz_glibc_read_chunk(core->io, next, &cnk_next, config)) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
ut64 next_node = rz_heap_get_next_pointer(core, next, cnk_next.fd, config);
|
||||
// avoid triple while?
|
||||
|
|
@ -2137,7 +2286,7 @@ RzList /*<RzHeapChunkListItem *>*/ *rz_heap_chunks_list_internal(RzCore *core, M
|
|||
break;
|
||||
}
|
||||
if (!rz_glibc_read_chunk(core->io, next_node, &cnk_next, config)) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
next_node = rz_heap_get_next_pointer(core, next_node, cnk_next.fd, config);
|
||||
}
|
||||
|
|
@ -2146,10 +2295,11 @@ RzList /*<RzHeapChunkListItem *>*/ *rz_heap_chunks_list_internal(RzCore *core, M
|
|||
}
|
||||
}
|
||||
if (!rz_glibc_read_chunk(core->io, next, &cnk, config)) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
next = rz_heap_get_next_pointer(core, next, cnk.fd, config);
|
||||
}
|
||||
skip_fastbin:
|
||||
if (double_free) {
|
||||
PRINT_RA(" Double free in simple-linked list detected ");
|
||||
break;
|
||||
|
|
@ -2323,8 +2473,9 @@ RZ_IPI RzCmdStatus rz_cmd_heap_chunks_print_handler(RzCore *core, int argc, cons
|
|||
}
|
||||
ut64 brk_start = 0, brk_end = 0;
|
||||
if (m_arena == m_state) {
|
||||
rz_heap_get_brks(core, &brk_start, &brk_end);
|
||||
|
||||
if (!rz_heap_get_brks(core, &brk_start, &brk_end)) {
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
brk_start = ((m_state >> 16) << 16);
|
||||
brk_end = brk_start + main_arena->system_mem;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-FileCopyrightText: 2026 bubblepipe <bubblepipe42@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include "core/core_private.h"
|
||||
#include <rz_core.h>
|
||||
#include <rz_heap_jemalloc.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -49,9 +50,52 @@ static ut64 je_get_va_symbol(RzCore *core, const char *path, const char *sym_nam
|
|||
return vaddr;
|
||||
}
|
||||
|
||||
static bool resolve_jemalloc_core_dump(RzCore *core, const char *symname, ut64 *symbol) {
|
||||
void **it;
|
||||
RzPVector *io_maps = rz_io_maps(core->io);
|
||||
rz_pvector_foreach (io_maps, it) {
|
||||
RzIOMap *io_map = *it;
|
||||
const char *path = rz_core_io_map_file_path_or_relative(io_map);
|
||||
|
||||
if (!rz_file_exists(path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// find the lowest map address for this file, for base_addr
|
||||
bool already_processed = false;
|
||||
ut64 base_addr = io_map->itv.addr;
|
||||
void **it2;
|
||||
rz_pvector_foreach (io_maps, it2) {
|
||||
RzIOMap *m2 = *it2;
|
||||
const char *p2 = rz_core_io_map_file_path_or_relative(m2);
|
||||
if (!RZ_STR_EQ(p2, path)) {
|
||||
continue;
|
||||
}
|
||||
if (it2 < it) {
|
||||
already_processed = true;
|
||||
break;
|
||||
}
|
||||
if (m2->itv.addr < base_addr) {
|
||||
base_addr = m2->itv.addr;
|
||||
}
|
||||
}
|
||||
if (already_processed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_pie = false;
|
||||
ut64 vaddr = je_get_va_symbol(core, path, symname, &is_pie);
|
||||
if (vaddr != UT64_MAX) {
|
||||
*symbol = is_pie ? (base_addr + vaddr) : vaddr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rz_resolve_jemalloc(RzCore *core, const char *symname, ut64 *symbol) {
|
||||
RzListIter *iter;
|
||||
RzDebugMap *map;
|
||||
RzDebugMap *debug_map;
|
||||
const char *jemalloc_path = NULL;
|
||||
ut64 jemalloc_addr = UT64_MAX;
|
||||
const char *binary_path = NULL;
|
||||
|
|
@ -60,20 +104,25 @@ static bool rz_resolve_jemalloc(RzCore *core, const char *symname, ut64 *symbol)
|
|||
if (!core || !core->dbg || !core->dbg->maps) {
|
||||
return false;
|
||||
}
|
||||
rz_debug_map_sync(core->dbg);
|
||||
|
||||
rz_list_foreach (core->dbg->maps, iter, map) {
|
||||
if (strstr(map->name, "libjemalloc.")) {
|
||||
if (jemalloc_addr == UT64_MAX || map->addr < jemalloc_addr) {
|
||||
jemalloc_addr = map->addr;
|
||||
jemalloc_path = map->name;
|
||||
if (rz_core_is_core_dump(core)) {
|
||||
return resolve_jemalloc_core_dump(core, symname, symbol);
|
||||
}
|
||||
|
||||
// for debug mode
|
||||
rz_debug_map_sync(core->dbg);
|
||||
rz_list_foreach (core->dbg->maps, iter, debug_map) {
|
||||
if (strstr(debug_map->name, "libjemalloc.")) {
|
||||
if (jemalloc_addr == UT64_MAX || debug_map->addr < jemalloc_addr) {
|
||||
jemalloc_addr = debug_map->addr;
|
||||
jemalloc_path = debug_map->name;
|
||||
}
|
||||
}
|
||||
if (!strstr(map->name, ".so") && !strstr(map->name, "lib") &&
|
||||
!strstr(map->name, "[") && strlen(map->name) > 0) {
|
||||
if (binary_addr == UT64_MAX || map->addr < binary_addr) {
|
||||
binary_addr = map->addr;
|
||||
binary_path = map->name;
|
||||
if (!strstr(debug_map->name, ".so") && !strstr(debug_map->name, "lib") &&
|
||||
!strstr(debug_map->name, "[") && strlen(debug_map->name) > 0) {
|
||||
if (binary_addr == UT64_MAX || debug_map->addr < binary_addr) {
|
||||
binary_addr = debug_map->addr;
|
||||
binary_path = debug_map->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -312,7 +361,7 @@ static void jemalloc_print_narenas_450(RzCore *core, bool has_specified_addr, ut
|
|||
|
||||
if (!has_specified_addr) {
|
||||
if (rz_resolve_jemalloc(core, "narenas_total", &symaddr)) {
|
||||
if (!read_ptr_at(core->io, symaddr, &narenas, config->ptr_size)) {
|
||||
if (!read_ptr_at(core->io, symaddr, &narenas, 4)) {
|
||||
RZ_LOG_ERROR("Failed to read narenas_total\n");
|
||||
return;
|
||||
}
|
||||
|
|
@ -830,11 +879,15 @@ static void jemalloc_print_narenas_530(RzCore *core, bool has_specified_addr, ut
|
|||
|
||||
if (!has_specified_addr) { // no args, list all arenas
|
||||
if (rz_resolve_jemalloc(core, "narenas_total", &symaddr)) {
|
||||
if (!read_ptr_at(core->io, symaddr, &narenas, config->ptr_size)) {
|
||||
RZ_LOG_DEBUG("symaddr : %" PFMT64d "\n", symaddr);
|
||||
if (!read_ptr_at(core->io, symaddr, &narenas, 4)) {
|
||||
RZ_LOG_ERROR("Failed to read narenas_total\n");
|
||||
return;
|
||||
}
|
||||
PRINTF_GA("narenas : %" PFMT64d "\n", narenas);
|
||||
} else {
|
||||
RZ_LOG_ERROR("narena_total not resolved\n");
|
||||
return;
|
||||
}
|
||||
if (narenas == 0) {
|
||||
RZ_LOG_ERROR("No arenas allocated.\n");
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ EOF
|
|||
EXPECT=<<EOF
|
||||
1
|
||||
3
|
||||
2
|
||||
1
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -153,3 +153,36 @@ Extent @ 0x7fff96016500
|
|||
Allocated Address: 0x7fff95e00000
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=dmxa/dmxb/dmxe/dmxei with jemalloc 5.3.0 core dump (linux-amd64-4k_page)
|
||||
FILE=bins/heap/segfault-jemalloc5.3.0-amd64-core
|
||||
CMDS=<<EOF
|
||||
dmxa~narena
|
||||
dmxa~0x55ae211c05c0
|
||||
dmxb~0x7f4550214528
|
||||
dmxe~0x7f4550216500
|
||||
dmxei 0x7f4550216980~Size
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
narenas : 129
|
||||
arenas[129] @ 0x55ae211c05c0 {
|
||||
bin[0] @ 0x7f4550214528 {
|
||||
Extent @ 0x7f4550216500
|
||||
Size: 0x1000
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
||||
NAME=dmxa/dmxb/dmxc with jemalloc 4.5.0 core dump (linux-aarch64-4k_page)
|
||||
FILE=bins/heap/segfault-jemalloc4.5.0-aarch64-core
|
||||
CMDS=<<EOF
|
||||
dmxa~narena
|
||||
dmxb~0xffffa6e00140
|
||||
dmxc~Chunk
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
narenas : 32
|
||||
arenas[0]: @ 0xffffa6e00140 {
|
||||
Chunk - start: 0xffffa6c00000, end: 0xffffa6e00000, size: 0x00200000
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ EOF
|
|||
EXPECT=<<EOF
|
||||
1
|
||||
3
|
||||
2
|
||||
1
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ EOF
|
|||
EXPECT=<<EOF
|
||||
1
|
||||
3
|
||||
2
|
||||
1
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ EOF
|
|||
EXPECT=<<EOF
|
||||
1
|
||||
3
|
||||
2
|
||||
1
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -218,3 +218,21 @@ Extent @ 0x7fff96016500
|
|||
Allocated Address: 0x7fff95e00000
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=dmxa/dmxb/dmxe/dmxei with jemalloc 5.3.0 core dump (linux-amd64-4k_page)
|
||||
FILE=bins/heap/segfault-jemalloc5.3.0-amd64-core
|
||||
CMDS=<<EOF
|
||||
dmxa~narena
|
||||
dmxa~0x55ae211c05c0
|
||||
dmxb~0x7f4550214528
|
||||
dmxe~0x7f4550216500
|
||||
dmxei 0x7f4550216980~Size
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
narenas : 129
|
||||
arenas[129] @ 0x55ae211c05c0 {
|
||||
bin[0] @ 0x7f4550214528 {
|
||||
Extent @ 0x7f4550216500
|
||||
Size: 0x1000
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -116,11 +116,11 @@ CMDS=<<EOF
|
|||
oml
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
1 fd: 3 +0x00002000 0x56149dfaf000 - 0x56149dfaffff r-- fmap./home/florian/dev/crash/crash-linux-x86_64
|
||||
2 fd: 4 +0x00000000 0x56149dfb0000 - 0x56149dfb0fff r-x mmap./home/florian/dev/crash/crash-linux-x86_64
|
||||
3 fd: 5 +0x00000000 0x56149dfb1000 - 0x56149dfb1fff r-- mmap./home/florian/dev/crash/crash-linux-x86_64
|
||||
4 fd: 3 +0x00003000 0x56149dfb2000 - 0x56149dfb2fff r-- fmap./home/florian/dev/crash/crash-linux-x86_64
|
||||
5 fd: 3 +0x00004000 0x56149dfb3000 - 0x56149dfb3fff r-- fmap./home/florian/dev/crash/crash-linux-x86_64
|
||||
1 fd: 3 +0x00002000 0x56149dfaf000 - 0x56149dfaffff r-- fmap.bins/elf/core/crash-linux-x86_64
|
||||
2 fd: 4 +0x00000000 0x56149dfb0000 - 0x56149dfb0fff r-x mmap.bins/elf/core/crash-linux-x86_64
|
||||
3 fd: 5 +0x00000000 0x56149dfb1000 - 0x56149dfb1fff r-- mmap.bins/elf/core/crash-linux-x86_64
|
||||
4 fd: 3 +0x00003000 0x56149dfb2000 - 0x56149dfb2fff r-- fmap.bins/elf/core/crash-linux-x86_64
|
||||
5 fd: 3 +0x00004000 0x56149dfb3000 - 0x56149dfb3fff r-- fmap.bins/elf/core/crash-linux-x86_64
|
||||
6 fd: 3 +0x00005000 0x7f582fa2e000 - 0x7f582fa2ffff r-- fmap.LOAD5
|
||||
7 fd: 6 +0x00000000 0x7f582fa31000 - 0x7f582fa55fff r-- mmap./usr/lib/libc-2.33.so
|
||||
8 fd: 3 +0x00007000 0x7f582fa30000 - 0x7f582fa30fff r-- fmap./usr/lib/libc-2.33.so
|
||||
|
|
@ -174,9 +174,9 @@ CMDS=<<EOF
|
|||
oml
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
1 fd: 3 +0x00001000 0x558ce37000 - 0x558ce37fff r-x fmap./home/alarm/crash/crash-linux-arm64
|
||||
2 fd: 3 +0x00002000 0x558ce47000 - 0x558ce47fff r-- fmap./home/alarm/crash/crash-linux-arm64
|
||||
3 fd: 3 +0x00003000 0x558ce48000 - 0x558ce48fff r-- fmap./home/alarm/crash/crash-linux-arm64
|
||||
1 fd: 3 +0x00001000 0x558ce37000 - 0x558ce37fff r-x fmap.bins/elf/core/crash-linux-arm64
|
||||
2 fd: 3 +0x00002000 0x558ce47000 - 0x558ce47fff r-- fmap.bins/elf/core/crash-linux-arm64
|
||||
3 fd: 3 +0x00003000 0x558ce48000 - 0x558ce48fff r-- fmap.bins/elf/core/crash-linux-arm64
|
||||
4 fd: 4 +0x00000000 0x7f8bd61000 - 0x7f8bebafff r-x mmap./usr/lib/libc-2.32.so
|
||||
5 fd: 3 +0x00004000 0x7f8bd60000 - 0x7f8bd60fff r-x fmap./usr/lib/libc-2.32.so
|
||||
6 fd: 5 +0x00000000 0x7f8bebb000 - 0x7f8becafff r-- mmap./usr/lib/libc-2.32.so
|
||||
|
|
@ -601,3 +601,130 @@ cause = 0x0000000010800024
|
|||
t = 0x0000000000000000
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=dm commands on x86-64 core dump
|
||||
FILE=bins/elf/core/core-linux-x86_64
|
||||
CMDS=<<EOF
|
||||
dm~fmap?
|
||||
dm~mmap?
|
||||
dmj~{[0]}
|
||||
dm=~fmap?
|
||||
dm=~mmap?
|
||||
echo ----
|
||||
s 0x56149dfaf000
|
||||
dm.~0x56149dfaf000
|
||||
echo ----
|
||||
dmm~libc
|
||||
dmm.~bin
|
||||
dmmj~libc
|
||||
dmm.j~crash
|
||||
echo ----
|
||||
dmi bins/elf/core/crash-linux-x86_64~printf
|
||||
dmij~{[0]}
|
||||
dmia bins/elf/core/crash-linux-x86_64~MAGIC
|
||||
obf bins/elf/core/crash-linux-x86_64
|
||||
dmi.~end
|
||||
echo ----
|
||||
dmS~.rodata
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
15
|
||||
7
|
||||
{"map":1,"fd":3,"delta":8192,"from":94646549803008,"to":94646549807104,"perm":"r--","name":"fmap.bins/elf/core/crash-linux-x86_64"}
|
||||
15
|
||||
7
|
||||
----
|
||||
1 fd: 3 +0x00002000 0x56149dfaf000 - 0x56149dfaffff r-- fmap.bins/elf/core/crash-linux-x86_64
|
||||
----
|
||||
0x7f582fa31000 0x7f582fa56000 /usr/lib/libc-2.33.so
|
||||
0x56149dfaf000 0x56149dfb0000 bins/elf/core/crash-linux-x86_64
|
||||
[{"addr":94646549803008,"addr_end":94646549807104,"name":"bins/elf/core/crash-linux-x86_64"},{"addr":140016733065216,"addr_end":140016733216768,"name":"/usr/lib/libc-2.33.so"},{"addr":140016735272960,"addr_end":140016735277056,"name":"/usr/lib/ld-2.33.so"}]
|
||||
[{"addr":94646549803008,"addr_end":94646549807104,"file":"bins/elf/core/crash-linux-x86_64"}]
|
||||
----
|
||||
2 0x00001030 0x56149dfb0030 GLOBAL FUNC 16 imp.printf
|
||||
{"addr":94646549803008,"addr_end":94646549807104,"name":"bins/elf/core/crash-linux-x86_64"}
|
||||
0x00000000 MAGIC 0x00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
|
||||
34 ---------- 0x00004038 GLOBAL NOTYPE 0 _end
|
||||
----
|
||||
0x00002000 0x8 0x56149dfb1000 0x8 0x0 -r-- crash-linux-x86_64..rodata PROGBITS alloc
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=dm commands on arm64 core dump
|
||||
FILE=bins/elf/core/core-linux-arm64
|
||||
CMDS=<<EOF
|
||||
dm~fmap?
|
||||
dm~mmap?
|
||||
dm=~fmap?
|
||||
dm=~mmap?
|
||||
echo ----
|
||||
s 0x558ce37000
|
||||
dm.~0x558ce37000
|
||||
echo ----
|
||||
dmm~libc
|
||||
dmm.~bin
|
||||
dmmj~libc
|
||||
dmm.j~crash
|
||||
echo ----
|
||||
dmi bins/elf/core/crash-linux-arm64~printf
|
||||
dmia bins/elf/core/crash-linux-arm64~MAGIC
|
||||
obf bins/elf/core/crash-linux-arm64
|
||||
dmi.~end
|
||||
echo ----
|
||||
dmS~.rodata
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
14
|
||||
3
|
||||
14
|
||||
3
|
||||
----
|
||||
1 fd: 3 +0x00001000 0x558ce37000 - 0x558ce37fff r-x fmap.bins/elf/core/crash-linux-arm64
|
||||
----
|
||||
0x7f8bd61000 0x7f8bebb000 /usr/lib/libc-2.32.so
|
||||
0x558ce37000 0x558ce38000 bins/elf/core/crash-linux-arm64
|
||||
[{"addr":367435935744,"addr_end":367435939840,"name":"bins/elf/core/crash-linux-arm64"},{"addr":547806908416,"addr_end":547808325632,"name":"/usr/lib/libc-2.32.so"},{"addr":547808579584,"addr_end":547808714752,"name":"/usr/lib/ld-2.32.so"}]
|
||||
[{"addr":367435935744,"addr_end":367435939840,"file":"bins/elf/core/crash-linux-arm64"}]
|
||||
----
|
||||
9 0x00000620 0x558ce37620 GLOBAL FUNC 16 imp.printf
|
||||
0x00000000 MAGIC 0x00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
|
||||
83 ---------- 0x00011038 GLOBAL NOTYPE 0 _bss_end__
|
||||
----
|
||||
0x00000818 0xc 0x558ce37818 0xc 0x0 -r-- crash-linux-arm64..rodata PROGBITS alloc
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=dmh commands on arm64 core dump
|
||||
FILE=bins/heap/segfault-glibc-aarch64-core
|
||||
CMDS=<<EOF
|
||||
dmh~Arena
|
||||
dmha
|
||||
dmhb~Bin?
|
||||
dmhc @ 0xaaab126cd290~0xaaab126cd2a0
|
||||
echo ----
|
||||
dmhd~Empty
|
||||
dmhf~Arena
|
||||
echo ----
|
||||
dmhg~0x410?
|
||||
dmhm~malloc_state
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
Arena @ 0xffff9a780a50
|
||||
Main arena (addr=0xffff9a780a50, lastRemainder=0x0, top=0xaaab126cdae0, next=0xffff9a780a50)
|
||||
128
|
||||
0xaaab126cd2a0 0x6e75686320676942 0x617830207461206b Big chunk at 0xa
|
||||
----
|
||||
Fast_bin[01] [size: 0x20] Empty bin
|
||||
Fast_bin[02] [size: 0x30] Empty bin
|
||||
Fast_bin[03] [size: 0x40] Empty bin
|
||||
Fast_bin[04] [size: 0x50] Empty bin
|
||||
Fast_bin[05] [size: 0x60] Empty bin
|
||||
Fast_bin[06] [size: 0x70] Empty bin
|
||||
Fast_bin[07] [size: 0x80] Empty bin
|
||||
Fast bins in Arena @ 0xffff9a780a50
|
||||
----
|
||||
2
|
||||
malloc_state @ 0xffff9a780a50
|
||||
struct malloc_state main_arena {
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
Loading…
Reference in a new issue