Skip to content

Commit

Permalink
Implement DBG_FIRST_SPECIAL dex debug opcode ##bin
Browse files Browse the repository at this point in the history
  • Loading branch information
radare authored and trufae committed Feb 4, 2025
1 parent 46c725d commit 88ead3a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 91 deletions.
44 changes: 3 additions & 41 deletions libr/bin/format/dex/dex.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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]);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
95 changes: 45 additions & 50 deletions libr/bin/p/bin_dex.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2011-2024 - pancake, h4ng3r */
/* radare - LGPL - Copyright 2011-2025 - pancake, h4ng3r */

#include <r_bin.h>
#include "../i/private.h"
Expand All @@ -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) {
Expand Down Expand Up @@ -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, &register_num);
Expand Down Expand Up @@ -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, &register_num);
Expand Down Expand Up @@ -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, &register_num);
Expand All @@ -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, &register_num);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 88ead3a

Please sign in to comment.