diff --git a/librz/bin/dwarf/abbrev.c b/librz/bin/dwarf/abbrev.c index 61a9a66c9de..e95c1dd55c6 100644 --- a/librz/bin/dwarf/abbrev.c +++ b/librz/bin/dwarf/abbrev.c @@ -201,6 +201,9 @@ RZ_API size_t rz_bin_dwarf_abbrev_count(RZ_BORROW RZ_NONNULL const RzBinDwarfAbb */ RZ_API RZ_BORROW RzBinDwarfAbbrevDecl *rz_bin_dwarf_abbrev_get(RZ_BORROW RZ_NONNULL const RzBinDwarfAbbrevTable *tbl, size_t idx) { rz_return_val_if_fail(tbl, NULL); + if (idx > rz_vector_len(&tbl->abbrevs)) { + return NULL; + } return rz_vector_index_ptr(&tbl->abbrevs, idx - 1); } diff --git a/librz/bin/dwarf/dwarf.c b/librz/bin/dwarf/dwarf.c index 1ae7d79b6ee..9c8920880ed 100644 --- a/librz/bin/dwarf/dwarf.c +++ b/librz/bin/dwarf/dwarf.c @@ -15,6 +15,27 @@ RZ_IPI bool RzBinDwarfEncoding_from_file(RzBinDwarfEncoding *encoding, RzBinFile return true; } +/** + * \brief Load DWARF from split DWARF file + * \param bin The RzBin instance + * \param opt The RzBinDWARFOption reference + * \param filepath The file path + * \return RzBinDWARF pointer or NULL if failed + */ +RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_dwo_from_file( + RZ_BORROW RZ_NONNULL RzBin *bin, + RZ_BORROW RZ_NONNULL const char *filepath) { + rz_return_val_if_fail(bin && filepath, NULL); + RzBinOptions bopt = { 0 }; + rz_bin_options_init(&bopt, 0, 0, 0, false); + RzBinFile *prev = rz_bin_cur(bin); + RzBinFile *bf = rz_bin_open(bin, filepath, &bopt); + RET_NULL_IF_FAIL(bf); + RzBinDWARF *dwo = rz_bin_dwarf_from_file(bf); + AND_DO(prev, rz_bin_file_set_cur_binfile(bin, prev)); + return dwo; +} + RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_from_file( RZ_BORROW RZ_NONNULL RzBinFile *bf) { rz_return_val_if_fail(bf, NULL); diff --git a/librz/bin/dwarf/unit.c b/librz/bin/dwarf/unit.c index 9faf6beb207..13fddf5f13d 100644 --- a/librz/bin/dwarf/unit.c +++ b/librz/bin/dwarf/unit.c @@ -349,6 +349,26 @@ RZ_API RZ_OWN RzBinDwarfInfo *rz_bin_dwarf_info_from_buf( RzBinDwarfCompUnit *unit = NULL; rz_vector_foreach(&info->units, unit) { ht_up_insert(info->unit_by_offset, unit->offset, unit); + switch (unit->hdr.ut) { + case DW_UT_skeleton: { + RzBinDwarfDie *die = rz_vector_head(&unit->dies); + if (!die) { + RZ_LOG_ERROR("Invalid DW_UT_skeleton [0x%" PFMT64x "]\n", unit->offset); + break; + } + + break; + } + case DW_UT_compile: + case DW_UT_type: + case DW_UT_partial: + case DW_UT_split_compile: + case DW_UT_split_type: + case DW_UT_lo_user: + case DW_UT_hi_user: + default: break; + } + RzBinDwarfDie *die = NULL; rz_vector_foreach(&unit->dies, die) { ht_up_insert(info->die_by_offset, die->offset, die); // optimization for further processing diff --git a/librz/core/cbin.c b/librz/core/cbin.c index a23d2e5b85a..85788bb1d2c 100644 --- a/librz/core/cbin.c +++ b/librz/core/cbin.c @@ -626,13 +626,26 @@ RZ_API bool rz_core_bin_apply_main(RzCore *r, RzBinFile *binfile, bool va) { return true; } +RZ_API RzBinDWARF *rz_core_bin_dwarf(RzCore *core, RzBinFile *binfile) { + RzBinDWARF *dw = rz_bin_dwarf_from_file(binfile); + if (!dw) { + const char *filepath = rz_config_get(core->config, "bin.dbginfo.filepath"); + if (!filepath) { + return NULL; + } + dw = rz_bin_dwarf_dwo_from_file(core->bin, filepath); + } + + return dw; +} + RZ_API bool rz_core_bin_apply_dwarf(RzCore *core, RzBinFile *binfile) { rz_return_val_if_fail(core && binfile, false); if (!rz_config_get_i(core->config, "bin.dbginfo") || !binfile->o) { return false; } - RzBinDWARF *dw = rz_bin_dwarf_from_file(binfile); + RzBinDWARF *dw = rz_core_bin_dwarf(core, binfile); if (!dw) { return false; } @@ -1702,8 +1715,9 @@ static bool bin_dwarf(RzCore *core, RzBinFile *binfile, RzCmdStateOutput *state) return false; } - RzBinDWARF *dw = core->analysis->debug_info->dw; - dw = dw ? dw : rz_bin_dwarf_from_file(binfile); + RzBinDWARF *dw = core->analysis && core->analysis->debug_info + ? core->analysis->debug_info->dw + : rz_bin_dwarf_from_file(binfile); if (!dw) { return false; } diff --git a/librz/core/cconfig.c b/librz/core/cconfig.c index 4414264a96d..ca427f93a3f 100644 --- a/librz/core/cconfig.c +++ b/librz/core/cconfig.c @@ -3230,6 +3230,7 @@ RZ_API int rz_core_config_init(RzCore *core) { SETI("bin.baddr", -1, "Base address of the binary"); SETI("bin.laddr", 0, "Base address for loading library ('*.so')"); SETCB("bin.dbginfo", "true", &cb_bindbginfo, "Load debug information at startup if available"); + SETCB("bin.dbginfo.filepath", "", NULL, "Load split debug information (DWARF) file if available"); SETBPREF("bin.relocs", "true", "Load relocs information at startup if available"); SETICB("bin.minstr", 0, &cb_binminstr, "Minimum string length for strings in bin plugins"); SETICB("bin.maxstr", 0, &cb_binmaxstr, "Maximum string length for strings in bin plugins"); diff --git a/librz/core/cdwarf.c b/librz/core/cdwarf.c index 20566449f3a..9af085de024 100644 --- a/librz/core/cdwarf.c +++ b/librz/core/cdwarf.c @@ -192,7 +192,8 @@ RZ_API RZ_OWN char *rz_core_bin_dwarf_debug_info_to_string( RzBinDwarfDie *die = NULL; rz_vector_foreach(&unit->dies, die) { - rz_strbuf_appendf(sb, "<0x%" PFMT64x ">: Abbrev Number: %-4" PFMT64u " ", die->offset, die->abbrev_code); + rz_strbuf_appendf(sb, "<0x%" PFMT64x ">: Abbrev Number: %-4" PFMT64u " ", + die->offset, die->abbrev_code); const char *tag_name = rz_bin_dwarf_tag(die->tag); if (tag_name) { diff --git a/librz/include/rz_bin_dwarf.h b/librz/include/rz_bin_dwarf.h index 0d59ecd960a..cbbebda438b 100644 --- a/librz/include/rz_bin_dwarf.h +++ b/librz/include/rz_bin_dwarf.h @@ -1042,9 +1042,13 @@ typedef struct { // A 4-byte unsigned offset into the .debug_abbrev section. ut64 abbrev_offset; DW_UT ut; // DWARF 5 addition - ut8 dwo_id; // DWARF 5 addition - ut64 type_sig; // DWARF 5 addition - ut64 type_offset; // DWARF 5 addition + union { + ut64 dwo_id; // DWARF 5 addition + struct { + ut64 type_sig; // DWARF 5 addition + ut64 type_offset; // DWARF 5 addition + }; + }; ut64 header_size; // excluding length field RzBinDwarfEncoding encoding; } RzBinDwarfCompUnitHdr; @@ -1498,6 +1502,10 @@ RZ_API void rz_bin_dwarf_line_op_fini(RZ_OWN RZ_NULLABLE RzBinDwarfLineOp *op); RZ_API void rz_bin_dwarf_line_free(RZ_OWN RZ_NULLABLE RzBinDwarfLine *li); RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_from_file(RZ_BORROW RZ_NONNULL RzBinFile *bf); +RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_dwo_from_file( + RZ_BORROW RZ_NONNULL RzBin *bin, + RZ_BORROW RZ_NONNULL const char *filepath); + RZ_API void rz_bin_dwarf_free(RZ_OWN RZ_NULLABLE RzBinDWARF *dw); // Assuming ValueType is an enum defined elsewhere