Add debug info support for Dalvik (#6570)

This commit is contained in:
Marc 2017-01-24 18:51:27 +01:00 committed by radare
parent a0c7ae8131
commit 459fc39f5b
7 changed files with 81 additions and 38 deletions

View File

@ -72,7 +72,7 @@ R_API char *r_bin_addr2text(RBin *bin, ut64 addr, int origin) {
// TODO: this is slow. must use a cached pool of mmaped files and line:off entries
out = r_file_slurp_line (file, line, 0);
if (!out) {
return 0;
return r_str_newf ("%s:%d", file, line);
}
out2 = malloc ((strlen (file) + 64 + strlen (out)) * sizeof (char));
if (origin > 1) {

View File

@ -367,7 +367,7 @@ beach:
static inline void add_sdb_addrline(Sdb *s, ut64 addr, const char *file, ut64 line, FILE *f, int mode) {
const char *p;
char fileline[128];
char *fileline;
char offset[64];
char *offset_ptr;
@ -398,16 +398,10 @@ static inline void add_sdb_addrline(Sdb *s, ut64 addr, const char *file, ut64 li
#else
p = file;
#endif
snprintf (fileline, sizeof (fileline) - 1, "%s|%"PFMT64d, p, line);
fileline = r_str_newf ("%s|%"PFMT64d, p, line);
offset_ptr = sdb_itoa (addr, offset, 16);
if (!sdb_add (s, offset_ptr, fileline, 0)) {
sdb_set (s, offset_ptr, fileline, 0);
}
if (!sdb_add (s, fileline, offset_ptr, 0)) {
sdb_set (s, fileline, offset_ptr, 0);
}
sdb_add (s, offset_ptr, fileline, 0);
sdb_add (s, fileline, offset_ptr, 0);
}
static const ut8* r_bin_dwarf_parse_ext_opcode(const RBin *a, const ut8 *obuf,

View File

@ -118,6 +118,7 @@ struct dex_encoded_catch_handler_t {
};
struct dex_debug_position_t {
ut32 source_file_idx;
ut64 address;
ut64 line;
};

View File

@ -0,0 +1,26 @@
/* radare - LGPL - Copyright 2009-2016 - nibble, montekki, pancake */
#include <r_types.h>
#include <r_bin.h>
static int get_line(RBinFile *arch, ut64 addr, char *file, int len, int *line) {
if (arch->sdb_addrinfo) {
char offset[64];
char *offset_ptr = sdb_itoa (addr, offset, 16);
char *ret = sdb_get (arch->sdb_addrinfo, offset_ptr, 0);
if (ret) {
char *p = strchr (ret, '|');
if (p) {
*p = '\0';
strncpy (file, ret, len);
*line = atoi (p + 1);
return true;
}
}
}
return false;
}
struct r_bin_dbginfo_t r_bin_dbginfo_dex = {
.get_line = &get_line,
};

View File

@ -5,16 +5,16 @@
// TODO: use proper dwarf api here.. or deprecate
static int get_line(RBinFile *arch, ut64 addr, char *file, int len, int *line) {
char *ret, *p, *offset_ptr, offset[64];
if (arch->sdb_addrinfo) {
offset_ptr = sdb_itoa (addr, offset, 16);
ret = sdb_get (arch->sdb_addrinfo, offset_ptr, 0);
char offset[64];
char *offset_ptr = sdb_itoa (addr, offset, 16);
char *ret = sdb_get (arch->sdb_addrinfo, offset_ptr, 0);
if (ret) {
p = strchr (ret, '|');
char *p = strchr (ret, '|');
if (p) {
*p = '\0';
strncpy(file, ret, len);
*line = atoi(p + 1);
strncpy (file, ret, len);
*line = atoi (p + 1);
return true;
}
}

View File

@ -9,6 +9,8 @@
#define r_hash_adler32 __adler32
#include "../../hash/adler32.c"
extern struct r_bin_dbginfo_t r_bin_dbginfo_dex;
#define DEBUG_PRINTF 0
#if DEBUG_PRINTF
@ -26,7 +28,7 @@ static char *getstr(RBinDexObj *bin, int idx) {
ut64 len;
int uleblen;
if (!bin || idx < 0 || idx >= bin->header.strings_size ||
!bin->strings) {
!bin->strings) {
return NULL;
}
if (bin->strings[idx] >= bin->size) {
@ -57,7 +59,7 @@ static char *getstr(RBinDexObj *bin, int idx) {
char *str = calloc (1, len + 1);
if (str) {
r_buf_read_at (bin->b, (bin->strings[idx]) + uleblen,
(ut8 *)str, len);
(ut8 *)str, len);
str[len] = 0;
return str;
}
@ -294,7 +296,7 @@ out_error:
// https://github.com/android/platform_dalvik/blob/0641c2b4836fae3ee8daf6c0af45c316c84d5aeb/libdex/DexDebugInfo.cpp#L312
// https://github.com/android/platform_dalvik/blob/0641c2b4836fae3ee8daf6c0af45c316c84d5aeb/libdex/DexDebugInfo.cpp#L141
static void dex_parse_debug_item(RBinFile *binfile, RBinDexObj *bin,
RBinDexClass *c, int MI, int MA, int ins_size,
RBinDexClass *c, int MI, int MA, int paddr, int ins_size,
int insns_size, char *class_name, int regsz,
int debug_info_off) {
struct r_bin_t *rbin = binfile->rbin;
@ -304,6 +306,7 @@ static void dex_parse_debug_item(RBinFile *binfile, RBinDexObj *bin,
ut64 parameters_size;
ut64 param_type_idx;
ut16 argReg = regsz - ins_size;
ut32 source_file_idx = c->source_file;
RList *params, *debug_positions, *emitted_debug_locals = NULL;
bool keep = true;
if (argReg >= regsz) {
@ -519,9 +522,8 @@ static void dex_parse_debug_item(RBinFile *binfile, RBinDexObj *bin,
break;
case 0x9:
{
ut64 name_idx;
p4 = r_uleb128 (p4, p4_end - p4, &name_idx);
name_idx -= 1;
p4 = r_uleb128 (p4, p4_end - p4, &source_file_idx);
--source_file_idx;
}
break;
default:
@ -535,6 +537,7 @@ static void dex_parse_debug_item(RBinFile *binfile, RBinDexObj *bin,
keep = false;
break;
}
position->source_file_idx = source_file_idx;
position->address = address;
position->line = line;
r_list_append (debug_positions, position);
@ -543,6 +546,24 @@ static void dex_parse_debug_item(RBinFile *binfile, RBinDexObj *bin,
}
opcode = *(p4++) & 0xff;
}
if (!binfile->sdb_addrinfo) {
binfile->sdb_addrinfo = sdb_new0 ();
}
char *fileline;
char offset[64];
char *offset_ptr;
RListIter *iter1;
struct dex_debug_position_t *pos;
r_list_foreach (debug_positions, iter1, pos) {
fileline = r_str_newf ("%s|%"PFMT64d, getstr (bin, pos->source_file_idx), pos->line);
offset_ptr = sdb_itoa (pos->address + paddr, offset, 16);
sdb_set (binfile->sdb_addrinfo, offset_ptr, fileline, 0);
sdb_set (binfile->sdb_addrinfo, fileline, offset_ptr, 0);
}
if (!dexdump) {
r_list_free (debug_positions);
r_list_free (emitted_debug_locals);
@ -907,7 +928,7 @@ static const ut8 *parse_dex_class_fields(RBinFile *binfile, RBinDexObj *bin,
break;
}
if (r_buf_read_at (binfile->buf, total, ff,
sizeof (DexField)) != sizeof (DexField)) {
sizeof (DexField)) != sizeof (DexField)) {
break;
}
field.class_id = r_read_le16 (ff);
@ -1157,17 +1178,6 @@ static const ut8 *parse_dex_class_method(RBinFile *binfile, RBinDexObj *bin,
}
}
if (MC > 0 && debug_info_off > 0 && bin->header.data_offset < debug_info_off &&
debug_info_off < bin->header.data_offset + bin->header.data_size) {
dex_parse_debug_item (binfile, bin, c, MI, MA, ins_size,
insns_size, cls->name, regsz, debug_info_off);
} else if (MC > 0) {
if (dexdump) {
rbin->cb_printf (" positions :\n");
rbin->cb_printf (" locals :\n");
}
}
if (*flag_name) {
RBinSymbol *sym = R_NEW0 (RBinSymbol);
sym->name = flag_name;
@ -1181,7 +1191,7 @@ static const ut8 *parse_dex_class_method(RBinFile *binfile, RBinDexObj *bin,
sym->vaddr = MC;// + 0x10;
sym->ordinal = (*sym_count)++;
if (MC > 0) {
// TODO: parse debug info
if (r_buf_read_at (binfile->buf, binfile->buf->base + MC, ff2, 16) < 1) {
R_FREE (sym);
R_FREE (signature);
@ -1236,6 +1246,17 @@ static const ut8 *parse_dex_class_method(RBinFile *binfile, RBinDexObj *bin,
// XXX memleak sym
R_FREE (sym);
}
if (MC > 0 && debug_info_off > 0 && bin->header.data_offset < debug_info_off &&
debug_info_off < bin->header.data_offset + bin->header.data_size) {
dex_parse_debug_item (binfile, bin, c, MI, MA, sym->paddr, ins_size,
insns_size, cls->name, regsz, debug_info_off);
} else if (MC > 0) {
if (dexdump) {
rbin->cb_printf (" positions :\n");
rbin->cb_printf (" locals :\n");
}
}
} else {
R_FREE (flag_name);
}
@ -1791,7 +1812,8 @@ RBinPlugin r_bin_plugin_dex = {
.header = &header,
.size = &size,
.get_offset = &getoffset,
.get_name = &getname
.get_name = &getname,
.dbginfo = &r_bin_dbginfo_dex,
};
#ifndef CORELIB

View File

@ -1,4 +1,4 @@
OBJ_DEX=bin_dex.o ../format/dex/dex.o
OBJ_DEX=bin_dex.o bin_dbginfo_dex.o ../format/dex/dex.o
STATIC_OBJ+=${OBJ_DEX}
TARGET_DEX=bin_dex.${EXT_SO}