mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 13:19:54 +00:00
Fix reading and parsing /proc/pid/maps from remote gdb on android ##debug
* Tested on Android12 / arm64
This commit is contained in:
parent
44c411d5ed
commit
e56c1ee7fe
@ -1,8 +1,6 @@
|
||||
/* radare - LGPL - Copyright 2009-2023 - pancake, defragger */
|
||||
|
||||
#include <r_core.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_debug.h>
|
||||
#include <libgdbr.h>
|
||||
#include <gdbclient/commands.h>
|
||||
|
||||
@ -14,14 +12,15 @@ typedef struct {
|
||||
#define UNSUPPORTED 0
|
||||
#define SUPPORTED 1
|
||||
|
||||
static RIOGdb ** origriogdb = NULL;
|
||||
static libgdbr_t *desc = NULL;
|
||||
static ut8* reg_buf = NULL;
|
||||
static int buf_size = 0;
|
||||
static int support_sw_bp = UNKNOWN;
|
||||
static int support_hw_bp = UNKNOWN;
|
||||
static R_TH_LOCAL RIOGdb ** origriogdb = NULL;
|
||||
static R_TH_LOCAL libgdbr_t *desc = NULL;
|
||||
static R_TH_LOCAL ut8* reg_buf = NULL;
|
||||
static R_TH_LOCAL int buf_size = 0;
|
||||
static R_TH_LOCAL int support_sw_bp = UNKNOWN;
|
||||
static R_TH_LOCAL int support_hw_bp = UNKNOWN;
|
||||
|
||||
static bool r_debug_gdb_attach(RDebug *dbg, int pid);
|
||||
|
||||
static void check_connection(RDebug *dbg) {
|
||||
if (!desc) {
|
||||
r_debug_gdb_attach (dbg, -1);
|
||||
@ -97,7 +96,37 @@ static bool gdb_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static RList *r_debug_gdb_map_get(RDebug* dbg) { //TODO
|
||||
#ifdef _MSC_VER
|
||||
#define GDB_FILE_OPEN_MODE (_S_IREAD | _S_IWRITE)
|
||||
#else
|
||||
#define GDB_FILE_OPEN_MODE (S_IRUSR | S_IWUSR | S_IXUSR)
|
||||
#endif
|
||||
|
||||
static char *read_remote_maps(ut64 *buflen) {
|
||||
*buflen = 0;
|
||||
char *fn = r_str_newf ("/proc/%d/maps", desc->pid);
|
||||
if (gdbr_open_file (desc, fn, O_RDONLY, GDB_FILE_OPEN_MODE) < 0) {
|
||||
free (fn);
|
||||
return NULL;
|
||||
}
|
||||
free (fn);
|
||||
int blen = 1024 * 512;
|
||||
char *buf = malloc (blen);
|
||||
if (buf) {
|
||||
int ret = gdbr_read_file (desc, (ut8*)buf, blen);
|
||||
if (ret < 1) {
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
*buflen = ret;
|
||||
buf = realloc (buf, ret + 1);
|
||||
buf[ret] = 0;
|
||||
}
|
||||
gdbr_close_file (desc);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static RList *r_debug_gdb_map_get(RDebug* dbg) { // TODO
|
||||
check_connection (dbg);
|
||||
if (!desc || desc->pid <= 0) {
|
||||
return NULL;
|
||||
@ -120,52 +149,26 @@ static RList *r_debug_gdb_map_get(RDebug* dbg) { //TODO
|
||||
}
|
||||
}
|
||||
|
||||
// Get file from GDB
|
||||
char path[128];
|
||||
ut8 *buf;
|
||||
int ret;
|
||||
// TODO don't hardcode buffer size, get from remote target
|
||||
// (I think gdb doesn't do that, it just keeps reading till EOF)
|
||||
// fstat info can get file size, but it doesn't work for /proc/pid/maps
|
||||
ut64 buflen = 16384;
|
||||
// If /proc/%d/maps is not valid for gdbserver, we return NULL, as of now
|
||||
snprintf (path, sizeof (path) - 1, "/proc/%d/maps", desc->pid);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define GDB_FILE_OPEN_MODE (_S_IREAD | _S_IWRITE)
|
||||
#else
|
||||
#define GDB_FILE_OPEN_MODE (S_IRUSR | S_IWUSR | S_IXUSR)
|
||||
#endif
|
||||
|
||||
if (gdbr_open_file (desc, path, O_RDONLY, GDB_FILE_OPEN_MODE) < 0) {
|
||||
ut64 buflen = 0;
|
||||
ut8 *buf = (ut8*) read_remote_maps (&buflen);
|
||||
if (!buf) {
|
||||
R_LOG_ERROR ("Cannot read /proc/pid/maps");
|
||||
return NULL;
|
||||
}
|
||||
if (!(buf = malloc (buflen))) {
|
||||
gdbr_close_file (desc);
|
||||
return NULL;
|
||||
}
|
||||
if ((ret = gdbr_read_file (desc, buf, buflen - 1)) <= 0) {
|
||||
gdbr_close_file (desc);
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
buf[ret] = '\0';
|
||||
|
||||
// Get map list
|
||||
int unk = 0, perm, i;
|
||||
char *ptr, *pos_1;
|
||||
size_t line_len;
|
||||
char name[1024], region1[100], region2[100], perms[5];
|
||||
char name[1024], region1[256], region2[100], perms[5];
|
||||
region1[0] = region2[0] = '0';
|
||||
region1[1] = region2[1] = 'x';
|
||||
char *save_ptr = NULL;
|
||||
if (!(ptr = r_str_tok_r ((char*) buf, "\n", &save_ptr))) {
|
||||
gdbr_close_file (desc);
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
if (!(retlist = r_list_new ())) {
|
||||
gdbr_close_file (desc);
|
||||
free (buf);
|
||||
return NULL;
|
||||
}
|
||||
@ -177,15 +180,40 @@ static RList *r_debug_gdb_map_get(RDebug* dbg) { //TODO
|
||||
if (line_len == 0) {
|
||||
break;
|
||||
}
|
||||
#if 1
|
||||
char *wordstr = strdup (ptr);
|
||||
r_str_replace_char (wordstr, '\t', ' ');
|
||||
RList *words = r_str_split_list (wordstr, " ", 6);
|
||||
int ret = r_list_length (words);
|
||||
perms[0] = 0;
|
||||
region1[2] = 0;
|
||||
region2[2] = 0;
|
||||
if (ret > 2) {
|
||||
offset = r_num_get (NULL, r_list_get_n (words, 2));
|
||||
r_str_ncpy (perms, r_list_get_n (words, 1), sizeof (perms));
|
||||
r_str_ncpy (region1 + 2, r_list_get_n (words, 0), sizeof (region1) - 2);
|
||||
}
|
||||
if (ret > 6) {
|
||||
const char *s = r_str_trim_head_ro (r_list_get_n (words, 6));
|
||||
r_str_ncpy (name, s, sizeof (name));
|
||||
} else {
|
||||
*name = 0;
|
||||
}
|
||||
r_list_free (words);
|
||||
free (wordstr);
|
||||
#else
|
||||
// We assume Linux target, for now, so -
|
||||
// 7ffff7dda000-7ffff7dfd000 r-xp 00000000 08:05 265428 /usr/lib/ld-2.25.so
|
||||
// Android
|
||||
// "12c00000-12c40000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)]";
|
||||
ret = sscanf (ptr, "%s %s %"PFMT64x" %*s %*s %[^\n]", ®ion1[2],
|
||||
perms, &offset, name);
|
||||
#endif
|
||||
// eprintf ("RET = %d (%s)\n", ret, ptr);
|
||||
if (ret == 3) {
|
||||
name[0] = '\0';
|
||||
} else if (ret < 3) {
|
||||
R_LOG_WARN ("Cannot parse \"%s\" with content: %s", path, buf);
|
||||
gdbr_close_file (desc);
|
||||
R_LOG_WARN ("Cannot parse proc/pid/maps line: %s", buf);
|
||||
free (buf);
|
||||
r_list_free (retlist);
|
||||
return NULL;
|
||||
@ -222,12 +250,11 @@ static RList *r_debug_gdb_map_get(RDebug* dbg) { //TODO
|
||||
map->file = strdup (name);
|
||||
r_list_append (retlist, map);
|
||||
} else {
|
||||
R_LOG_WARN ("Cannot create map 0x%08"PFMT64x" - 0x%08"PFMT64x" (%s)", map_start, map_end, perm);
|
||||
R_LOG_WARN ("Cannot create map 0x%08"PFMT64x" - 0x%08"PFMT64x" (%s)", map_start, map_end, perms);
|
||||
break;
|
||||
}
|
||||
ptr = r_str_tok_r (NULL, "\n", &save_ptr);
|
||||
}
|
||||
gdbr_close_file (desc);
|
||||
free (buf);
|
||||
return retlist;
|
||||
}
|
||||
@ -569,3 +596,4 @@ R_API RLibStruct radare_plugin = {
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -1453,25 +1453,24 @@ end:
|
||||
|
||||
int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode) {
|
||||
int ret = -1;
|
||||
char *buf;
|
||||
size_t buf_len;
|
||||
|
||||
if (!g || !filename || !*filename) {
|
||||
if (!g || R_STR_ISEMPTY (filename)) {
|
||||
return -1;
|
||||
}
|
||||
if (g->remote_file_fd >= 0) {
|
||||
R_LOG_ERROR ("%s: Remote file already open", __func__);
|
||||
return -1;
|
||||
}
|
||||
buf_len = (strlen (filename) * 2) + strlen ("vFile:open:") + 30;
|
||||
if (!(buf = calloc (buf_len, sizeof (char)))) {
|
||||
size_t buf_len = (strlen (filename) * 2) + strlen ("vFile:open:") + 30;
|
||||
char *buf = calloc (buf_len, sizeof (char));
|
||||
if (!buf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!gdbr_lock_enter (g)) {
|
||||
goto end;
|
||||
}
|
||||
strcpy (buf, "vFile:open:");
|
||||
r_str_ncpy (buf, "vFile:open:", buf_len);
|
||||
pack_hex (filename, strlen (filename), buf + strlen (buf));
|
||||
snprintf (buf + strlen (buf), buf_len - strlen (buf) - 1, ",%x,%x", flags, mode);
|
||||
if ((ret = send_msg (g, buf)) < 0) {
|
||||
@ -1484,21 +1483,17 @@ int gdbr_open_file(libgdbr_t *g, const char *filename, int flags, int mode) {
|
||||
|
||||
ret = 0;
|
||||
end:
|
||||
if (buf) {
|
||||
free (buf);
|
||||
}
|
||||
free (buf);
|
||||
gdbr_lock_leave (g);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
|
||||
r_return_val_if_fail (g && buf && max_len, -1);
|
||||
int ret, ret1;
|
||||
char command[64];
|
||||
ut64 data_sz;
|
||||
ret = 0;
|
||||
if (!g || !buf || !max_len) {
|
||||
return -1;
|
||||
}
|
||||
if (max_len >= INT32_MAX) {
|
||||
R_LOG_ERROR ("%s: Too big a file read requested: %"PFMT64d, __func__, max_len);
|
||||
return -1;
|
||||
@ -1538,8 +1533,7 @@ int gdbr_read_file(libgdbr_t *g, ut8 *buf, ut64 max_len) {
|
||||
goto end;
|
||||
}
|
||||
ret += ret1;
|
||||
}
|
||||
|
||||
}
|
||||
end:
|
||||
gdbr_lock_leave (g);
|
||||
return ret;
|
||||
|
@ -1,11 +1,9 @@
|
||||
/* libgdbr - LGPL - Copyright 2014 - defragger */
|
||||
/* libgdbr - LGPL - Copyright 2014-2023 - defragger */
|
||||
|
||||
#include "libgdbr.h"
|
||||
#include "arch.h"
|
||||
#include <r_util.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int gdbr_init(libgdbr_t *g, bool is_server) {
|
||||
if (!g) {
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user