From 88ead3a23454fad12d2bb9b82351de2ce2e738e1 Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 4 Feb 2025 17:51:09 +0100 Subject: [PATCH] Implement DBG_FIRST_SPECIAL dex debug opcode ##bin --- libr/bin/format/dex/dex.c | 44 ++---------------- libr/bin/p/bin_dex.c | 95 +++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 91 deletions(-) diff --git a/libr/bin/format/dex/dex.c b/libr/bin/format/dex/dex.c index 5c3fcad492c26..a001f34d0bfa4 100644 --- a/libr/bin/format/dex/dex.c +++ b/libr/bin/format/dex/dex.c @@ -225,13 +225,6 @@ static bool readAnnotationSet(RBinDexObj *dex, ut64 addr) { return r_buf_seek (dex->b, addr + (i * sizeof (ut32)), R_BUF_SET) >= 0; } -static void r_bin_dex_obj_free(RBinDexObj *dex) { - if (dex) { - r_buf_free (dex->b); - free (dex); - } -} - void r_bin_dex_free(RBinDexObj *dex) { if (!dex) { return; @@ -250,6 +243,8 @@ void r_bin_dex_free(RBinDexObj *dex) { free (dex->types); free (dex->fields); free (dex->protos); + r_buf_free (dex->b); + free (dex); } RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { @@ -313,7 +308,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { for (i = 0; i < dexhdr->strings_size; i++) { ut64 offset = dexhdr->strings_offset + i * sizeof (ut32); if (offset + 4 > dex->size) { - free (dex->strings); goto fail; } dex->strings[i] = r_read_le32 (&dex->strings[i]); @@ -334,8 +328,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { for (i = 0; i < dexhdr->class_size; i++) { ut64 offset = dexhdr->class_offset + i * DEX_CLASS_SIZE; if (offset + 32 > dex->size) { - free (dex->strings); - free (dex->classes); goto fail; } r_buf_seek (dex->b, offset, R_BUF_SET); @@ -363,9 +355,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { for (i = 0; i < dexhdr->method_size; i++) { ut64 offset = dexhdr->method_offset + i * sizeof (struct dex_method_t); if (offset + 8 > dex->size) { - free (dex->strings); - free (dex->classes); - free (dex->methods); goto fail; } r_buf_seek (dex->b, offset, R_BUF_SET); @@ -377,10 +366,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { /* types */ int types_size = dexhdr->types_size * sizeof (struct dex_type_t); if (types_size < 0) { - free (dex->strings); - free (dex->classes); - free (dex->methods); - free (dex->types); goto fail; } if (dexhdr->types_offset + types_size > dex->size) { @@ -390,18 +375,10 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { types_size = dex->size - dexhdr->types_offset; } if (types_size < 0) { - free (dex->strings); - free (dex->classes); - free (dex->methods); - free (dex->types); goto fail; } if (types_size > dex->size) { R_LOG_DEBUG ("oom prevented in huge types section %d / %d", types_size, dex->size); - free (dex->strings); - free (dex->classes); - free (dex->methods); - free (dex->types); goto fail; } dexhdr->types_size = types_size / sizeof (struct dex_type_t); @@ -410,10 +387,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { for (i = 0; i < dexhdr->types_size; i++) { ut64 offset = dexhdr->types_offset + i * sizeof (struct dex_type_t); if (offset + 4 > dex->size) { - free (dex->strings); - free (dex->classes); - free (dex->methods); - free (dex->types); goto fail; } dex->types[i].descriptor_id = r_buf_read_le32_at (dex->b, offset); @@ -433,11 +406,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { for (i = 0; i < dexhdr->fields_size; i++) { ut64 offset = dexhdr->fields_offset + i * sizeof (struct dex_field_t); if (offset + 8 > dex->size) { - free (dex->strings); - free (dex->classes); - free (dex->methods); - free (dex->types); - free (dex->fields); goto fail; } r_buf_seek (dex->b, offset, R_BUF_SET); @@ -460,12 +428,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { for (i = 0; i < dexhdr->prototypes_size; i++) { ut64 offset = dexhdr->prototypes_offset + i * sizeof (struct dex_proto_t); if (offset + 12 > dex->size) { - free (dex->strings); - free (dex->classes); - free (dex->methods); - free (dex->types); - free (dex->fields); - free (dex->protos); goto fail; } r_buf_seek (dex->b, offset, R_BUF_SET); @@ -569,6 +531,6 @@ RBinDexObj *r_bin_dex_new_buf(RBuffer *buf, bool verbose) { return dex; fail: - r_bin_dex_obj_free (dex); + r_bin_dex_free (dex); return NULL; } diff --git a/libr/bin/p/bin_dex.c b/libr/bin/p/bin_dex.c index 537330d79b105..632ae04711432 100644 --- a/libr/bin/p/bin_dex.c +++ b/libr/bin/p/bin_dex.c @@ -1,4 +1,4 @@ -/* radare - LGPL - Copyright 2011-2024 - pancake, h4ng3r */ +/* radare - LGPL - Copyright 2011-2025 - pancake, h4ng3r */ #include #include "../i/private.h" @@ -7,6 +7,21 @@ #define r_hash_adler32 __adler32 #include "../../crypto/hash/adler32.c" +#define DBG_END_SEQUENCE 0x00 +#define DBG_ADVANCE_PC 0x01 +#define DBG_ADVANCE_LINE 0x02 +#define DBG_START_LOCAL 0x03 +#define DBG_START_LOCAL_EXTENDED 0x04 +#define DBG_END_LOCAL 0x05 +#define DBG_RESTART_LOCAL 0x06 +#define DBG_SET_PROLOGUE_END 0x07 +#define DBG_SET_EPILOGUE_BEGIN 0x08 +#define DBG_SET_FILE 0x09 +#define DBG_FIRST_SPECIAL 0x0A + +#define DBG_LINE_BASE -4 +#define DBG_LINE_RANGE 15 + extern struct r_bin_dbginfo_t r_bin_dbginfo_dex; static ut64 get_method_attr(ut64 MA) { @@ -431,24 +446,24 @@ static void dex_parse_debug_item(RBinFile *bf, RBinDexClass *c, int MI, int MA, } while (keep) { switch (opcode) { - case 0x00: // DBG_END_SEQUENCE + case DBG_END_SEQUENCE: keep = false; break; - case 0x01: // DBG_ADVANCE_PC + case DBG_ADVANCE_PC: { ut64 addr_diff; r_buf_uleb128 (bf->buf, &addr_diff); address += addr_diff; } break; - case 0x02: // DBG_ADVANCE_LINE + case DBG_ADVANCE_LINE: { st64 line_diff; r_buf_sleb128 (bf->buf, &line_diff); line += line_diff; } break; - case 0x03: // DBG_START_LOCAL + case DBG_START_LOCAL: { ut64 register_num, name_idx, type_idx; r_buf_uleb128 (bf->buf, ®ister_num); @@ -485,7 +500,7 @@ static void dex_parse_debug_item(RBinFile *bf, RBinDexClass *c, int MI, int MA, //eprintf("DBG_START_LOCAL %x %x %x\n", register_num, name_idx, type_idx); } break; - case 0x04: // DBG_START_LOCAL_EXTENDED + case DBG_START_LOCAL_EXTENDED: { ut64 register_num, name_idx, type_idx, sig_idx; r_buf_uleb128 (bf->buf, ®ister_num); @@ -524,7 +539,7 @@ static void dex_parse_debug_item(RBinFile *bf, RBinDexClass *c, int MI, int MA, debug_locals[register_num].live = true; } break; - case 0x05: // DBG_END_LOCAL + case DBG_END_LOCAL: { ut64 register_num; r_buf_uleb128 (bf->buf, ®ister_num); @@ -551,7 +566,7 @@ static void dex_parse_debug_item(RBinFile *bf, RBinDexClass *c, int MI, int MA, debug_locals[register_num].live = false; } break; - case 0x06: // DBG_RESTART_LOCAL + case DBG_RESTART_LOCAL: { ut64 register_num; r_buf_uleb128 (bf->buf, ®ister_num); @@ -564,53 +579,34 @@ static void dex_parse_debug_item(RBinFile *bf, RBinDexClass *c, int MI, int MA, } } break; - case 0x07: // DBG_SET_PROLOGUE_END + case DBG_SET_PROLOGUE_END: + // ignored break; - case 0x08: // DBG_SET_PROLOGUE_BEGIN + case DBG_SET_EPILOGUE_BEGIN: + // ignored break; - case 0x09: // DBG_SET_FILE + case DBG_SET_FILE: { - ut64 res; - r_buf_uleb128 (bf->buf, &res); - source_file_idx = res - 1; + ut64 res; + r_buf_uleb128 (bf->buf, &res); + source_file_idx = res - 1; } break; - case 0x0a: // DBG_SET_FIRST_SPECIAL - { - // TODO - R_LOG_TODO ("DBG_SET_FIRST_SPECIAL"); - } - break; -#if 0 - case -4: // DBG_LINE_BASE - { - // TODO - } - break; -#endif -#if 0 - default: - // we parse trash or we dont support undocumented opcodes. but this must improve - R_LOG_WARN ("Unhandled dex debug opcode 0x%02x", opcode); - break; -#else default: -#endif - case 0x0f: // DBG_LINE_RANGE - { - int adjusted_opcode = opcode - 10; - address += (adjusted_opcode / 15); - line += -4 + (adjusted_opcode % 15); - struct dex_debug_position_t *position = - R_NEW0 (struct dex_debug_position_t); - if (!position) { - keep = false; - break; - } - position->source_file_idx = source_file_idx; - position->address = address; - position->line = line; - r_list_append (debug_positions, position); + if (opcode >= DBG_FIRST_SPECIAL) { + int adjusted_opcode = opcode - DBG_FIRST_SPECIAL; + int addr_delta = adjusted_opcode / DBG_LINE_RANGE; + int line_delta = DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE); + address += addr_delta; + line += line_delta; + struct dex_debug_position_t *position = + R_NEW0 (struct dex_debug_position_t); + position->source_file_idx = source_file_idx; + position->address = address; + position->line = line; + r_list_append (debug_positions, position); + } else { + R_LOG_ERROR ("unknown dex debug opcode: 0x%02x", opcode); } break; } @@ -1131,7 +1127,6 @@ static void parse_dex_class_fields(RBinFile *bf, RBinDexClass *c, RBinClass *cls } // TODO: refactor this method -// XXX it needs a lot of love!!! static void parse_dex_class_method(RBinFile *bf, RBinDexClass *c, RBinClass *cls, int *sym_count, ut64 DM, int *methods, bool is_direct) { PrintfCallback cb_printf = bf->rbin->cb_printf; RBinDexObj *dex = bf->bo->bin_obj;