mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-17 04:39:36 +00:00
Linux debug plugin, page promotion feature ##debug
* Linux debug plugin, page promotion feature proposal. Providing new 'dmL' debugger sub command. This is the only system having THP feature, others are more into direct huge tlb equivalent ... The system ought to be set in madvise mode and disabled on Android, would not do any good in this environment if this is ever supported. Once the syscall succeed, the address range ought to get the little 'hg' VmFlags. * interface changes
This commit is contained in:
parent
674c4a0668
commit
0626013ac7
@ -226,6 +226,7 @@ static const char *help_msg_dm[] = {
|
||||
"dms-", " <id> <mapaddr>", "Restore memory snapshot",
|
||||
"dmS", " [addr|libname] [sectname]", "List sections of target lib",
|
||||
"dmS*", " [addr|libname] [sectname]", "List sections of target lib in radare commands",
|
||||
"dmL", " address size", "Allocate <size> bytes at <address> and promote to huge page",
|
||||
//"dm, " rw- esp 9K", "set 9KB of the stack as read+write (no exec)",
|
||||
"TODO:", "", "map files in process memory. (dmf file @ [addr])",
|
||||
NULL
|
||||
@ -1826,7 +1827,7 @@ static int cmd_debug_map(RCore *core, const char *input) {
|
||||
*p++ = 0;
|
||||
addr = r_num_math (core->num, input + 1);
|
||||
size = r_num_math (core->num, p);
|
||||
r_debug_map_alloc (core->dbg, addr, size);
|
||||
r_debug_map_alloc (core->dbg, addr, size, false);
|
||||
} else {
|
||||
eprintf ("Usage: dm addr size\n");
|
||||
return false;
|
||||
@ -1848,6 +1849,21 @@ static int cmd_debug_map(RCore *core, const char *input) {
|
||||
}
|
||||
eprintf ("The address doesn't match with any map.\n");
|
||||
break;
|
||||
case 'L': // "dmL"
|
||||
{
|
||||
int size;
|
||||
char *p = strchr (input + 2, ' ');
|
||||
if (p) {
|
||||
*p++ = 0;
|
||||
addr = r_num_math (core->num, input + 1);
|
||||
size = r_num_math (core->num, p);
|
||||
r_debug_map_alloc (core->dbg, addr, size, true);
|
||||
} else {
|
||||
eprintf ("Usage: dmL addr size\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\0': // "dm"
|
||||
case '*': // "dm*"
|
||||
case 'j': // "dmj"
|
||||
|
@ -313,10 +313,10 @@ R_API int r_debug_map_sync(RDebug *dbg) {
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
R_API RDebugMap* r_debug_map_alloc(RDebug *dbg, ut64 addr, int size) {
|
||||
R_API RDebugMap* r_debug_map_alloc(RDebug *dbg, ut64 addr, int size, bool thp) {
|
||||
RDebugMap *map = NULL;
|
||||
if (dbg && dbg->h && dbg->h->map_alloc) {
|
||||
map = dbg->h->map_alloc (dbg, addr, size);
|
||||
map = dbg->h->map_alloc (dbg, addr, size, thp);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -1062,7 +1062,67 @@ static int io_perms_to_prot (int io_perms) {
|
||||
return prot_perms;
|
||||
}
|
||||
|
||||
static RDebugMap* linux_map_alloc (RDebug *dbg, ut64 addr, int size) {
|
||||
|
||||
static int linux_map_thp (RDebug *dbg, ut64 addr, int size) {
|
||||
#ifndef __ANDROID__
|
||||
RBuffer *buf = NULL;
|
||||
char code[1024];
|
||||
int ret = true;
|
||||
char *asm_list[] = {
|
||||
"x86", "x86.as",
|
||||
"x64", "x86.as",
|
||||
NULL
|
||||
};
|
||||
// In architectures where radare is supported, arm and x86, it is 2MB
|
||||
const size_t thpsize = 1<<21;
|
||||
|
||||
if ((size%thpsize)) {
|
||||
eprintf ("size not a power of huge pages size\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// In always mode, is more into mmap syscall level
|
||||
// even though the address might not have the 'hg'
|
||||
// vmflags
|
||||
if (r_sys_thp_mode() != 1) {
|
||||
eprintf ("transparent huge page mode is not in madvise mode\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int num = r_syscall_get_num (dbg->anal->syscall, "madvise");
|
||||
|
||||
snprintf (code, sizeof (code),
|
||||
"sc_madvise@syscall(%d);\n"
|
||||
"main@naked(0) { .rarg0 = sc_madvise(0x%08" PFMT64x ",%d, %d);break;\n"
|
||||
"}\n",
|
||||
num, addr, size, MADV_HUGEPAGE);
|
||||
r_egg_reset (dbg->egg);
|
||||
r_egg_setup (dbg->egg, dbg->arch, 8 * dbg->bits, 0, 0);
|
||||
r_egg_load (dbg->egg, code, 0);
|
||||
if (!r_egg_compile (dbg->egg)) {
|
||||
eprintf ("Cannot compile.\n");
|
||||
goto err_linux_map_thp;
|
||||
}
|
||||
if (!r_egg_assemble_asm (dbg->egg, asm_list)) {
|
||||
eprintf ("r_egg_assemble: invalid assembly\n");
|
||||
goto err_linux_map_thp;
|
||||
}
|
||||
buf = r_egg_get_bin (dbg->egg);
|
||||
if (buf) {
|
||||
r_reg_arena_push (dbg->reg);
|
||||
ut64 tmpsz;
|
||||
const ut8 *tmp = r_buf_data (buf, &tmpsz);
|
||||
ret = r_debug_execute (dbg, tmp, tmpsz, 1) == 0;
|
||||
r_reg_arena_pop (dbg->reg);
|
||||
}
|
||||
err_linux_map_thp:
|
||||
return ret;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static RDebugMap* linux_map_alloc (RDebug *dbg, ut64 addr, int size, bool thp) {
|
||||
RBuffer *buf = NULL;
|
||||
RDebugMap* map = NULL;
|
||||
char code[1024], *sc_name;
|
||||
@ -1111,6 +1171,12 @@ static RDebugMap* linux_map_alloc (RDebug *dbg, ut64 addr, int size) {
|
||||
map_addr = r_debug_execute (dbg, tmp, tmpsz, 1);
|
||||
r_reg_arena_pop (dbg->reg);
|
||||
if (map_addr != (ut64)-1) {
|
||||
if (thp) {
|
||||
if (!linux_map_thp (dbg, map_addr, size)) {
|
||||
// Not overly dramatic
|
||||
eprintf ("map promotion to huge page failed\n");
|
||||
}
|
||||
}
|
||||
r_debug_map_sync (dbg);
|
||||
map = r_debug_map_get (dbg, map_addr);
|
||||
}
|
||||
@ -1159,13 +1225,15 @@ err_linux_map_dealloc:
|
||||
}
|
||||
#endif
|
||||
|
||||
static RDebugMap* r_debug_native_map_alloc (RDebug *dbg, ut64 addr, int size) {
|
||||
static RDebugMap* r_debug_native_map_alloc (RDebug *dbg, ut64 addr, int size, bool thp) {
|
||||
#if __APPLE__
|
||||
(void)thp;
|
||||
return xnu_map_alloc (dbg, addr, size);
|
||||
#elif __WINDOWS__
|
||||
(void)thp;
|
||||
return w32_map_alloc (dbg, addr, size);
|
||||
#elif __linux__
|
||||
return linux_map_alloc (dbg, addr, size);
|
||||
return linux_map_alloc (dbg, addr, size, thp);
|
||||
#else
|
||||
// malloc not implemented for this platform
|
||||
return NULL;
|
||||
|
@ -392,7 +392,7 @@ typedef struct r_debug_plugin_t {
|
||||
/* memory */
|
||||
RList *(*map_get)(RDebug *dbg);
|
||||
RList *(*modules_get)(RDebug *dbg);
|
||||
RDebugMap* (*map_alloc)(RDebug *dbg, ut64 addr, int size);
|
||||
RDebugMap* (*map_alloc)(RDebug *dbg, ut64 addr, int size, bool thp);
|
||||
int (*map_dealloc)(RDebug *dbg, ut64 addr, int size);
|
||||
int (*map_protect)(RDebug *dbg, ut64 addr, int size, int perms);
|
||||
int (*init)(RDebug *dbg);
|
||||
@ -491,7 +491,7 @@ R_API bool r_debug_plugin_add(RDebug *dbg, RDebugPlugin *foo);
|
||||
|
||||
/* memory */
|
||||
R_API RList *r_debug_modules_list(RDebug*);
|
||||
R_API RDebugMap *r_debug_map_alloc(RDebug *dbg, ut64 addr, int size);
|
||||
R_API RDebugMap *r_debug_map_alloc(RDebug *dbg, ut64 addr, int size, bool thp);
|
||||
R_API int r_debug_map_dealloc(RDebug *dbg, RDebugMap *map);
|
||||
R_API RList *r_debug_map_list_new(void);
|
||||
R_API RDebugMap *r_debug_map_get(RDebug *dbg, ut64 addr);
|
||||
|
@ -65,6 +65,7 @@ R_API char *r_sys_whoami(char *buf);
|
||||
R_API char *r_sys_getdir(void);
|
||||
R_API int r_sys_chdir(const char *s);
|
||||
R_API bool r_sys_aslr(int val);
|
||||
R_API int r_sys_thp_mode(void);
|
||||
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr);
|
||||
#if __WINDOWS__
|
||||
#if UNICODE
|
||||
|
@ -523,6 +523,25 @@ R_API bool r_sys_aslr(int val) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_sys_thp_mode(void) {
|
||||
#if __linux__
|
||||
const char *thp = "/sys/kernel/mm/transparent_hugepage/enabled";
|
||||
int sz;
|
||||
int ret = 0;
|
||||
char *val = r_file_slurp (thp, &sz);
|
||||
if (val) {
|
||||
if (strstr (val, "[madvise]")) {
|
||||
ret = 1;
|
||||
} else if (strstr (val, "[always]")) {
|
||||
ret = 2;
|
||||
}
|
||||
free (val);
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __UNIX__
|
||||
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) {
|
||||
char *mysterr = NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user