DWARF .debug_info parsing fix and improvement (#17007)

* Get .debug_info working for DWARF 2, 3
* Fill up missing information in abbrev string table
* Add 64bit dwarf option into debug_info
* Add DWARF4 and DWARF5 forms
* Add unit tests
* added basic test

Co-authored-by: Riccardo Schirone <sirmy15@gmail.com>
This commit is contained in:
HoundThe 2020-06-19 13:25:59 +02:00 committed by GitHub
parent 2f78b9f5df
commit 914624a921
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1923 additions and 1097 deletions

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -896,11 +896,13 @@ static int bin_dwarf(RCore *core, int mode) {
// TODO: complete and speed-up support for dwarf
RBinDwarfDebugAbbrev *da = NULL;
da = r_bin_dwarf_parse_abbrev (core->bin, mode);
r_bin_dwarf_parse_info (da, core->bin, mode);
RBinDwarfDebugInfo *info = r_bin_dwarf_parse_info (da, core->bin, mode);
// dig types out of into and then free
r_bin_dwarf_free_debug_info (info);
r_bin_dwarf_parse_aranges (core->bin, mode);
list = ownlist = r_bin_dwarf_parse_line (core->bin, mode);
r_bin_dwarf_free_debug_abbrev (da);
free (da);
}
if (!list) {
return false;

File diff suppressed because it is too large Load Diff

View File

@ -431,7 +431,7 @@ pd 1
EOF
EXPECT=<<EOF
.blah:
31ed xor ebp, ebp ; /builddir/glibc-2.19/csu/../sysdeps/x86_64//start.S:67
31ed xor ebp, ebp ; start.S:67
EOF
RUN

View File

@ -4081,6 +4081,7 @@ EXPECT=<<EOF
[Source file]
/home/landley/work/ab7/build/temp-armv6l/gcc-core/gcc/config/arm/ieee754-df.S
/home/landley/work/ab7/build/temp-armv6l/gcc-core/gcc/config/arm/lib1funcs.asm
/home/landley/work/ab7/build/temp-armv6l/build-gcc/gcc
EOF
RUN

View File

@ -10,7 +10,7 @@ EXPECT=<<EOF
; DATA XREF from entry0 @ 0x40045d
/ 44: int main (int argc, char **argv, char **envp);
| ; var int64_t var_4h @ rbp-0x4
| 0x0040052d 55 push rbp ; /tmp/r2-regressions/.//dwarftest.c:4
| 0x0040052d 55 push rbp ; dwarftest.c:4
EOF
RUN
@ -20,7 +20,7 @@ CMDS=<<EOF
CL 0x0000a24e
EOF
EXPECT=<<EOF
file: TestRTTI/TestRTTI.cpp
file: /Users/ftamagni/src/TestRTTI/TestRTTI//TestRTTI.cpp
line: 18
EOF
RUN

View File

@ -8,22 +8,22 @@ s 0x00402c43
pd 30
EOF
EXPECT=<<EOF
0x00402c43 lea rax, [rbp - 0xa0] ; .//ezpz.cpp:265
0x00402c43 lea rax, [rbp - 0xa0] ; ezpz.cpp:265
0x00402c4a mov rdi, rax
0x00402c4d call sym MD5_Init(MD5_CTX*)
0x00402c52 mov eax, dword [rbp - 0xb4] ; .//ezpz.cpp:266
0x00402c52 mov eax, dword [rbp - 0xb4] ; ezpz.cpp:266
0x00402c58 add eax, 1
0x00402c5b movsxd rdx, eax
0x00402c5e lea rax, [rbp - 0xa0]
0x00402c65 mov esi, obj.Password
0x00402c6a mov rdi, rax
0x00402c6d call sym MD5_Update(MD5_CTX*, void const*, unsigned long)
0x00402c72 lea rdx, [rbp - 0xa0] ; .//ezpz.cpp:267
0x00402c72 lea rdx, [rbp - 0xa0] ; ezpz.cpp:267
0x00402c79 lea rax, [rbp - 0xb0]
0x00402c80 mov rsi, rdx
0x00402c83 mov rdi, rax
0x00402c86 call sym MD5_Final(unsigned char*, MD5_CTX*)
0x00402c8b mov eax, dword [rbp - 0xb4] ; .//ezpz.cpp:269
0x00402c8b mov eax, dword [rbp - 0xb4] ; ezpz.cpp:269
0x00402c91 cdqe
0x00402c93 shl rax, 4
0x00402c97 lea rcx, [rax + obj.GoodHashes]
@ -34,9 +34,9 @@ EXPECT=<<EOF
0x00402cb0 call sym.imp.memcmp
0x00402cb5 test eax, eax
0x00402cb7 je 0x402cc2
0x00402cb9 mov byte [obj.DrawGoodWork], 0 ; .//ezpz.cpp:270
0x00402cb9 mov byte [obj.DrawGoodWork], 0 ; ezpz.cpp:270
0x00402cc0 jmp 0x402cdd
0x00402cc2 add dword [rbp - 0xb4], 1 ; .//ezpz.cpp:263
0x00402cc2 add dword [rbp - 0xb4], 1 ; ezpz.cpp:263
0x00402cc9 cmp dword [rbp - 0xb4], 0x14
EOF
RUN

View File

@ -80,7 +80,7 @@ NAME=C++ demangle relocs
FILE=bins/elf/libstdc++.so.6
CMDS=pd 1 @0x00091004
EXPECT=<<EOF
0x00091004 488b159d880f. mov rdx, qword [reloc.vtable_for_std::bad_alloc] ; /build/gcc/src/gcc/libstdc++-v3/libsupc++/new:57 ; [0x1898a8:8]=0
0x00091004 488b159d880f. mov rdx, qword [reloc.vtable_for_std::bad_alloc] ; new:57 ; [0x1898a8:8]=0
EOF
RUN

View File

@ -20,6 +20,7 @@ if get_option('enable_tests')
'debruijn',
'diff',
'dwarf',
'dwarf_info',
'esil_dfg_filter',
'event',
'flags',

View File

@ -12,17 +12,17 @@
#define check_abbrev_tag(expected_tag) \
mu_assert_eq (da->decls[i].tag, expected_tag, "Incorrect abbreviation tag")
#define check_abbrev_length(expected_length) \
mu_assert_eq (da->decls[i].length, expected_length, "Incorrect abbreviation length")
#define check_abbrev_count(expected_count) \
mu_assert_eq (da->decls[i].count, expected_count, "Incorrect abbreviation count")
#define check_abbrev_children(expected_children) \
mu_assert_eq (da->decls[i].has_children, expected_children, "Incorrect children flag")
#define check_abbrev_attr_name(expected_name) \
mu_assert_eq (da->decls[i].specs[j].attr_name, expected_name, "Incorrect children flag");
mu_assert_eq (da->decls[i].defs[j].attr_name, expected_name, "Incorrect children flag");
#define check_abbrev_attr_form(expected_form) \
mu_assert_eq (da->decls[i].specs[j].attr_form, expected_form, "Incorrect children flag");
mu_assert_eq (da->decls[i].defs[j].attr_form, expected_form, "Incorrect children flag");
/**
* @brief Comparator to sort list of line statements by address(collection of DwarfRows)
@ -57,7 +57,7 @@ bool test_dwarf3_c_basic(void) { // this should work for dwarf2 aswell
// static void dump_r_bin_dwarf_debug_abbrev(FILE *f, RBinDwarfDebugAbbrev *da)
// which prints out all the abbreviation
da = r_bin_dwarf_parse_abbrev (bin, MODE);
mu_assert_eq (da->length, 7, "Incorrect number of abbreviation");
mu_assert_eq (da->count, 7, "Incorrect number of abbreviation");
// order matters
// I nest scopes to make it more readable, (hopefully)
@ -65,7 +65,7 @@ bool test_dwarf3_c_basic(void) { // this should work for dwarf2 aswell
check_abbrev_tag (DW_TAG_compile_unit);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
{
int j = 0;
check_abbrev_attr_name (DW_AT_producer);
@ -93,45 +93,43 @@ bool test_dwarf3_c_basic(void) { // this should work for dwarf2 aswell
i++;
check_abbrev_tag (DW_TAG_variable);
{
check_abbrev_length (8);
check_abbrev_count (8);
check_abbrev_children (false);
}
i++;
check_abbrev_tag (DW_TAG_base_type);
{
check_abbrev_length (4);
check_abbrev_count (4);
check_abbrev_children (false);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_length (12);
check_abbrev_count (12);
check_abbrev_children (true);
}
i++;
check_abbrev_tag (DW_TAG_variable);
{
check_abbrev_length (7);
check_abbrev_count (7);
check_abbrev_children (false);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_length (10);
check_abbrev_count (10);
check_abbrev_children (true);
}
i++;
check_abbrev_tag (DW_TAG_variable);
{
check_abbrev_length (6);
check_abbrev_count (6);
check_abbrev_children (false);
}
i++;
RList *line_list = NULL;
line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (line_list->length, 8, "Amount of line information parse doesn't match");
RList *line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (r_list_length (line_list), 8, "Amount of line information parse doesn't match");
RBinDwarfRow *row;
RListIter *iter;
@ -155,6 +153,9 @@ bool test_dwarf3_c_basic(void) { // this should work for dwarf2 aswell
mu_assert_eq (row->address, test_addresses[i++], "Line number statement address doesn't match");
}
r_list_free (line_list);
r_bin_dwarf_free_debug_abbrev (da);
r_bin_free (bin);
r_io_free (io);
mu_end;
}
@ -183,7 +184,7 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
// static void dump_r_bin_dwarf_debug_abbrev(FILE *f, RBinDwarfDebugAbbrev *da)
// which prints out all the abbreviation
da = r_bin_dwarf_parse_abbrev (bin, MODE);
mu_assert ("Incorrect number of abbreviation", da->length == 32);
mu_assert ("Incorrect number of abbreviation", da->count == 32);
// order matters
// I nest scopes to make it more readable, (hopefully)
@ -191,7 +192,7 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
check_abbrev_tag (DW_TAG_compile_unit);
{
check_abbrev_children (true);
check_abbrev_length (9);
check_abbrev_count (9);
{
/**
* Everything commented out is something that is missing from being printed by `id` Radare
@ -229,7 +230,7 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
check_abbrev_tag (DW_TAG_structure_type);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
{
/**
* Everything commented out is something that is missing from being printed by `id` Radare
@ -264,31 +265,31 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
}
i++;
check_abbrev_tag (DW_TAG_formal_parameter);
{
check_abbrev_children (false);
check_abbrev_length (3);
check_abbrev_count (3);
}
i++;
check_abbrev_tag (DW_TAG_formal_parameter);
{
check_abbrev_children (false);
check_abbrev_length (2);
check_abbrev_count (2);
}
i++;
check_abbrev_tag (DW_TAG_member);
{
check_abbrev_children (false);
check_abbrev_length (5);
check_abbrev_count (5);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (10);
check_abbrev_count (10);
}
i++;
@ -296,7 +297,7 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (12);
check_abbrev_count (12);
{
int j = 0;
check_abbrev_attr_name (DW_AT_external);
@ -337,155 +338,153 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (13);
check_abbrev_count (13);
}
i++;
check_abbrev_tag (DW_TAG_const_type);
{
check_abbrev_children (false);
check_abbrev_length (2);
check_abbrev_count (2);
}
i++;
check_abbrev_tag (DW_TAG_pointer_type);
{
check_abbrev_children (false);
check_abbrev_length (3);
check_abbrev_count (3);
}
i++;
check_abbrev_tag (DW_TAG_reference_type);
{
check_abbrev_children (false);
check_abbrev_length (3);
check_abbrev_count (3);
}
i++;
check_abbrev_tag (DW_TAG_subroutine_type);
{
check_abbrev_children (true);
check_abbrev_length (3);
check_abbrev_count (3);
}
i++;
check_abbrev_tag (DW_TAG_unspecified_parameters);
{
check_abbrev_children (false);
check_abbrev_length (1);
check_abbrev_count (1);
}
i++;
check_abbrev_tag (DW_TAG_base_type);
{
check_abbrev_children (false);
check_abbrev_length (4);
check_abbrev_count (4);
}
i++;
check_abbrev_tag (DW_TAG_pointer_type);
{
check_abbrev_children (false);
check_abbrev_length (4);
check_abbrev_count (4);
}
i++;
check_abbrev_tag (DW_TAG_structure_type);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
}
i++;
check_abbrev_tag (DW_TAG_inheritance);
{
check_abbrev_children (false);
check_abbrev_length (3);
check_abbrev_count (3);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (10);
check_abbrev_count (10);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (13);
check_abbrev_count (13);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (12);
check_abbrev_count (12);
}
i++;
check_abbrev_tag (DW_TAG_variable);
{
check_abbrev_children (false);
check_abbrev_length (7);
check_abbrev_count (7);
}
i++;
check_abbrev_tag (DW_TAG_variable);
{
check_abbrev_children (false);
check_abbrev_length (7);
check_abbrev_count (7);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
}
i++;
check_abbrev_tag (DW_TAG_formal_parameter);
{
check_abbrev_children (false);
check_abbrev_length (5);
check_abbrev_count (5);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (5);
check_abbrev_count (5);
}
i++;
check_abbrev_tag (DW_TAG_formal_parameter);
{
check_abbrev_children (false);
check_abbrev_length (4);
check_abbrev_count (4);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (9);
check_abbrev_count (9);
}
i++;
check_abbrev_tag (DW_TAG_formal_parameter);
{
check_abbrev_children (false);
check_abbrev_length (3);
check_abbrev_count (3);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (9);
check_abbrev_count (9);
}
i++;
check_abbrev_tag (DW_TAG_subprogram);
{
check_abbrev_children (true);
check_abbrev_length (8);
check_abbrev_count (8);
}
// r_bin_dwarf_parse_info (da, core->bin, mode); Information not stored anywhere, not testable now?
// r_bin_dwarf_parse_aranges (core->bin, MODE); Information not stored anywhere, not testable now?
RList *line_list = NULL;
line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (line_list->length, 60, "Amount of line information parse doesn't match");
RList *line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (r_list_length (line_list), 60, "Amount of line information parse doesn't match");
RBinDwarfRow *row;
RListIter *iter;
@ -563,6 +562,9 @@ bool test_dwarf3_cpp_basic(void) { // this should work for dwarf2 aswell
mu_assert_eq (row->address, test_addresses[i++], "Line number statement address doesn't match");
}
r_list_free (line_list);
r_bin_dwarf_free_debug_abbrev (da);
r_bin_free (bin);
r_io_free (io);
mu_end;
}
@ -580,23 +582,21 @@ bool test_dwarf3_cpp_many_comp_units(void) {
// static void dump_r_bin_dwarf_debug_abbrev(FILE *f, RBinDwarfDebugAbbrev *da)
// which prints out all the abbreviation
da = r_bin_dwarf_parse_abbrev (bin, MODE);
mu_assert_eq (da->length, 58, "Incorrect number of abbreviation");
mu_assert_eq (da->count, 58, "Incorrect number of abbreviation");
int i = 18;
check_abbrev_tag (DW_TAG_formal_parameter);
check_abbrev_length (5);
check_abbrev_count (5);
check_abbrev_children (false);
check_abbrev_code (19);
i = 41;
check_abbrev_tag (DW_TAG_inheritance);
check_abbrev_length (3);
check_abbrev_count (3);
check_abbrev_children (false);
check_abbrev_code (18);
RList *line_list = NULL;
line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (line_list->length, 64, "Amount of line information parse doesn't match");
RList *line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (r_list_length (line_list), 64, "Amount of line information parse doesn't match");
RBinDwarfRow *row;
RListIter *iter;
@ -678,6 +678,9 @@ bool test_dwarf3_cpp_many_comp_units(void) {
mu_assert_eq (row->address, test_addresses[i++], "Line number statement address doesn't match");
}
r_list_free (line_list);
r_bin_dwarf_free_debug_abbrev (da);
r_bin_free (bin);
r_io_free (io);
mu_end;
}
@ -697,12 +700,10 @@ bool test_dwarf_cpp_empty_line_info(void) { // this should work for dwarf2 aswel
// which prints out all the abbreviation
da = r_bin_dwarf_parse_abbrev (bin, MODE);
// not ignoring null entries -> 755 abbrevs
mu_assert_eq (da->length, 731, "Incorrect number of abbreviation");
mu_assert_eq (da->count, 731, "Incorrect number of abbreviation");
RList *line_list = NULL;
line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (line_list->length, 771, "Amount of line information parse doesn't match");
RList *line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (r_list_length (line_list), 771, "Amount of line information parse doesn't match");
RBinDwarfRow *row;
RListIter *iter;
@ -744,6 +745,8 @@ bool test_dwarf_cpp_empty_line_info(void) { // this should work for dwarf2 aswel
break;
}
r_list_free (line_list);
r_bin_dwarf_free_debug_abbrev (da);
r_io_free (io);
mu_end;
}
@ -762,24 +765,22 @@ bool test_dwarf2_cpp_many_comp_units(void) {
// static void dump_r_bin_dwarf_debug_abbrev(FILE *f, RBinDwarfDebugAbbrev *da)
// which prints out all the abbreviation
da = r_bin_dwarf_parse_abbrev (bin, MODE);
mu_assert_eq (da->length, 58, "Incorrect number of abbreviation");
mu_assert_eq (da->count, 58, "Incorrect number of abbreviation");
int i = 18;
check_abbrev_tag (DW_TAG_formal_parameter);
check_abbrev_length (5);
check_abbrev_count (5);
check_abbrev_children (false);
check_abbrev_code (19);
i = 41;
check_abbrev_tag (DW_TAG_inheritance);
check_abbrev_length (4);
check_abbrev_count (4);
check_abbrev_children (false);
check_abbrev_code (18);
RList *line_list = NULL;
line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (line_list->length, 64, "Amount of line information parse doesn't match");
RList *line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (r_list_length (line_list), 64, "Amount of line information parse doesn't match");
RBinDwarfRow *row;
RListIter *iter;
@ -859,6 +860,9 @@ bool test_dwarf2_cpp_many_comp_units(void) {
}
// add line information check
r_list_free (line_list);
r_bin_dwarf_free_debug_abbrev (da);
r_bin_free (bin);
r_io_free (io);
mu_end;
}
@ -872,13 +876,10 @@ bool test_dwarf4_cpp_many_comp_units(void) {
bool res = r_bin_open (bin, "bins/elf/dwarf4_many_comp_units.elf", &opt);
mu_assert ("couldn't open file", res);
RBinDwarfDebugAbbrev *da = NULL;
// TODO add abbrev checks
RList *line_list = NULL;
line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (line_list->length, 75, "Amount of line information parse doesn't match");
RList *line_list = r_bin_dwarf_parse_line (bin, MODE);
mu_assert_eq (r_list_length (line_list), 75, "Amount of line information parse doesn't match");
RBinDwarfRow *row;
RListIter *iter;
@ -968,6 +969,8 @@ bool test_dwarf4_cpp_many_comp_units(void) {
mu_assert_eq (row->address, test_addresses[i++], "Line number statement address doesn't match");
}
r_list_free (line_list);
r_bin_free (bin);
r_io_free (io);
mu_end;
}

335
test/unit/test_dwarf_info.c Normal file
View File

@ -0,0 +1,335 @@
#include <r_util.h>
#include "minunit.h"
#include <r_bin.h>
#include <r_bin_dwarf.h>
#define MODE 2
#define check_attr_string(attr_idx, expect_string) \
mu_assert_streq (cu.dies[i].attr_values[attr_idx].string.content, expect_string, "Wrong string attribute information")
#define check_attr_name(attr_idx, expect_name) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].attr_name, expect_name, "Wrong attribute name")
#define check_attr_address(attr_idx, expect_addr) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].address, expect_addr, "Wrong attribute name")
#define check_attr_form(attr_idx, expect_form) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].attr_form, expect_form, "Wrong attribute name")
#define check_attr_data(attr_idx, expect_data) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].data, expect_data, "Wrong attribute data")
#define check_attr_block_length(attr_idx, expect_len) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].block.length, expect_len, "Wrong attribute block length")
#define check_attr_block_data(attr_idx, data_idx, expect_data) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].block.data[data_idx], expect_data, "Wrong attribute block data")
#define check_attr_reference(attr_idx, expect_ref) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].reference, expect_ref, "Wrong attribute reference")
#define check_attr_flag(attr_idx, expect_flag) \
mu_assert_eq (cu.dies[i].attr_values[attr_idx].flag, expect_flag, "Wrong attribute flag")
#define check_die_abbr_code(expect_code) \
mu_assert_eq (cu.dies[i].abbrev_code, expect_code, "Wrong abbrev code")
#define check_die_length(len) \
mu_assert_eq (cu.dies[i].count, len, "Wrong DIE length information")
#define check_die_tag(tg) \
mu_assert_eq (cu.dies[i].tag, tg, "Wrong DIE tag")
#define check_basic_unit_header(vers, len, is64bit, addr_size, abbr_offset) \
do { \
mu_assert_eq (hdr.version, vers, "Wrong header version information"); \
mu_assert_eq (hdr.length, len, "Wrong header length information"); \
mu_assert_eq (hdr.is_64bit, is64bit, "Wrong header is_64bit information"); \
mu_assert_eq (hdr.address_size, addr_size, "Wrong header address_size information"); \
mu_assert_eq (hdr.abbrev_offset, abbr_offset, "Wrong header abbrev_offset information"); \
} while (0)
bool test_dwarf3_c(void) {
RBin *bin = r_bin_new ();
RIO *io = r_io_new ();
r_io_bind (io, &bin->iob);
RBinOptions opt = { 0 };
bool res = r_bin_open (bin, "bins/elf/dwarf3_c.elf", &opt);
mu_assert ("dwarf3_c.elf binary could not be opened", res);
RBinDwarfDebugAbbrev *da = r_bin_dwarf_parse_abbrev (bin, MODE);
mu_assert_eq (da->count, 7, "Incorrect number of abbreviation");
RBinDwarfDebugInfo *info = r_bin_dwarf_parse_info (da, bin, MODE);
mu_assert_eq (info->count, 1, "Incorrect number of info compilation units");
// check header
RBinDwarfCompUnit cu = info->comp_units[0];
RBinDwarfCompUnitHdr hdr = cu.hdr;
check_basic_unit_header (3, 0xa9, false, 8, 0x0);
mu_assert_eq (cu.count, 11, "Wrong attribute information");
mu_assert_eq (cu.offset, 0x0, "Wrong attribute information");
// check some of the attributes
int i = 0;
check_die_abbr_code (1);
check_die_length (7);
check_die_tag (DW_TAG_compile_unit);
check_attr_name (0, DW_AT_producer);
check_attr_string (2, "main.c");
i++;
check_die_abbr_code (2);
i++;
check_die_abbr_code (3);
i++;
check_die_abbr_code (4);
i++;
check_die_abbr_code (5);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (6);
i++;
check_die_abbr_code (7);
check_attr_string (0, "b");
check_attr_data (3, 15);
i++;
check_die_abbr_code (7);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (0);
r_bin_dwarf_free_debug_info (info);
r_bin_dwarf_free_debug_abbrev (da);
r_bin_free (bin);
r_io_free (io);
mu_end;
}
bool test_dwarf4_cpp_multiple_modules(void) {
RBin *bin = r_bin_new ();
RIO *io = r_io_new ();
r_io_bind (io, &bin->iob);
RBinOptions opt = { 0 };
bool res = r_bin_open (bin, "bins/elf/dwarf4_many_comp_units.elf", &opt);
mu_assert ("dwarf4_many_comp_units.elf binary could not be opened", res);
RBinDwarfDebugAbbrev *da = r_bin_dwarf_parse_abbrev (bin, MODE);
mu_assert_eq (da->count, 37, "Incorrect number of abbreviation");
RBinDwarfDebugInfo *info = r_bin_dwarf_parse_info (da, bin, MODE);
mu_assert_notnull (info, "Failed parsing of debug_info");
mu_assert_eq (info->count, 2, "Incorrect number of info compilation units");
// check header
RBinDwarfCompUnit cu = info->comp_units[0];
RBinDwarfCompUnitHdr hdr = cu.hdr;
check_basic_unit_header (4, 0x2c0, false, 8, 0x0);
// check some of the attributes
mu_assert_eq (cu.count, 73, "Wrong attribute information");
mu_assert_eq (cu.offset, 0x0, "Wrong attribute information");
int i = 0;
check_die_abbr_code (1);
check_die_length (7);
check_die_tag (DW_TAG_compile_unit);
check_attr_name (0, DW_AT_producer);
check_attr_string (2, "../main.cpp");
check_attr_name (6, DW_AT_ranges);
check_attr_reference (6, 0x0);
i++;
check_die_abbr_code (2);
i++;
check_die_abbr_code (3);
i++;
check_die_abbr_code (3);
i++;
check_die_abbr_code (3);
i++;
check_die_abbr_code (0);
i++;
// i == 6
check_die_abbr_code (4);
check_attr_reference (0, 0x6e);
check_attr_data (1, 4);
check_attr_string (2, "Bird");
check_attr_data (3, 8);
check_attr_data (4, 1);
check_attr_data (5, 9);
i++;
check_die_abbr_code (5);
check_die_tag (DW_TAG_member);
check_attr_string (0, "_vptr$Bird");
check_attr_reference (1, 0xc5);
check_attr_data (2, 0);
check_attr_data (3, true);
i++;
check_die_abbr_code (6);
i++;
check_die_abbr_code (7);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (8);
i++;
check_die_abbr_code (7);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (9);
check_die_tag (DW_TAG_subprogram);
check_die_length (10);
check_attr_string (0, "_ZN4Bird3flyEv");
check_attr_string (1, "fly");
check_attr_data (2, 1);
check_attr_data (3, 12);
check_attr_reference (4, 0xd8);
check_attr_name (6, DW_AT_vtable_elem_location);
check_attr_form (7, DW_FORM_flag_present);
check_attr_flag (7, true);
check_attr_name (8, DW_AT_external);
check_attr_flag (8, true);
check_attr_name (9, DW_AT_containing_type);
check_attr_reference (9, 0x6e);
i++;
check_die_abbr_code (7);
mu_assert_eq (cu.dies[i].abbrev_code, 7, "Wrong attribute information");
i++;
check_die_abbr_code (0);
mu_assert_eq (cu.dies[i].abbrev_code, 0, "Wrong attribute information");
i++;
check_die_abbr_code (0);
mu_assert_eq (cu.dies[i].abbrev_code, 0, "Wrong attribute information");
i++;
check_die_abbr_code (10);
mu_assert_eq (cu.dies[i].abbrev_code, 10, "Wrong attribute information");
i++;
check_die_abbr_code (11);
mu_assert_eq (cu.dies[i].abbrev_code, 11, "Wrong attribute information");
i++;
check_die_abbr_code (12);
mu_assert_eq (cu.dies[i].abbrev_code, 12, "Wrong attribute information");
i++;
check_die_abbr_code (13);
check_die_tag (DW_TAG_base_type);
check_die_length (3);
i++;
check_die_abbr_code (10);
i++;
check_die_abbr_code (14);
i++;
check_die_abbr_code (15);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (4);
i = 66;
check_die_abbr_code (18);
check_die_length (5);
check_attr_reference (3, 0x2a7);
i++;
check_die_abbr_code (15);
check_die_length (4);
check_attr_block_length (0, 2);
check_attr_block_data (0, 0, 0x91);
check_attr_block_data (0, 1, 0x78);
check_attr_string (1, "this");
check_attr_reference (2, 0x2be);
check_attr_flag (3, true);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (10);
i++;
check_die_abbr_code (10);
check_die_tag (DW_TAG_pointer_type);
i++;
check_die_abbr_code (10);
i++;
check_die_abbr_code (0);
i++;
cu = info->comp_units[1];
hdr = cu.hdr;
check_basic_unit_header (4, 0x192, false, 8, 0xfd);
// check some of the attributes
mu_assert_eq (cu.count, 42, "Wrong attribute information");
mu_assert_eq (cu.offset, 0x2c4, "Wrong attribute information");
i = 0;
check_die_abbr_code (1);
check_die_length (7);
check_die_tag (DW_TAG_compile_unit);
check_attr_name (0, DW_AT_producer);
check_attr_string (0, "clang version 10.0.0-4ubuntu1 ");
check_attr_data (1, 33);
check_attr_string (2, "../mammal.cpp");
check_attr_address (5, 0x0);
check_attr_form (5, DW_FORM_addr);
check_attr_name (6, DW_AT_ranges);
check_attr_reference (6, 0xb0);
i++;
check_die_abbr_code (2);
i++;
check_die_abbr_code (3);
i++;
check_die_abbr_code (4);
i++;
check_die_abbr_code (5);
i++;
check_die_abbr_code (0);
i++;
check_die_abbr_code (6);
i++;
check_die_abbr_code (5);
i++;
check_die_abbr_code (0);
i = 35;
check_die_abbr_code (8);
check_die_tag (DW_TAG_pointer_type);
check_die_length (1);
check_attr_form (0, DW_FORM_ref4);
check_attr_reference (0, 0x407);
i++;
check_die_abbr_code (19);
check_die_tag (DW_TAG_subprogram);
check_die_length (5);
check_attr_name (2, DW_AT_frame_base);
check_attr_block_length (2, 1);
check_attr_block_data (2, 0, 0x56);
check_attr_reference (3, 0x442);
check_attr_reference (4, 0x410);
i=40;
check_die_abbr_code (8);
i++;
check_die_abbr_code (0);
r_bin_dwarf_free_debug_info (info);
r_bin_dwarf_free_debug_abbrev (da);
r_bin_free (bin);
r_io_free (io);
mu_end;
}
bool all_tests() {
mu_run_test (test_dwarf3_c);
mu_run_test (test_dwarf4_cpp_multiple_modules);
return tests_passed != tests_run;
}
int main(int argc, char **argv) {
return all_tests ();
}