From 444000416cc929d4ce67116a46eaeee1d8a5b4fd Mon Sep 17 00:00:00 2001 From: billow Date: Mon, 6 Nov 2023 23:41:42 +0800 Subject: [PATCH] Add debuginfod support (#3954) * Add DEBUGINFOD_URLS support * Add rz_bin_dwarf_from_debuginfod * Fix rz_bin_dwarf_attr_addr * Add test for debuginfod * Filter empty RzBinDWARF --- .github/workflows/ci.yml | 34 ++++---- .github/workflows/tcc.yml | 2 +- librz/analysis/dwarf_process.c | 9 +- librz/bin/dwarf/addr.c | 12 +-- librz/bin/dwarf/attr.c | 14 ++-- librz/bin/dwarf/dwarf.c | 35 +++++++- librz/bin/dwarf/dwarf_private.h | 7 -- librz/bin/dwarf/loclists.c | 8 +- librz/bin/dwarf/rnglists.c | 8 +- librz/core/cbin.c | 18 ++++ librz/core/cconfig.c | 4 + librz/include/rz_bin_dwarf.h | 40 ++++++++- test/db/archos/linux-x64/debuginfod | 125 ++++++++++++++++++++++++++++ 13 files changed, 265 insertions(+), 51 deletions(-) create mode 100644 test/db/archos/linux-x64/debuginfod diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78a89b33f20..95eb046f59c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -200,7 +200,7 @@ jobs: if: matrix.run_tests && matrix.enabled && matrix.os != 'macos-12' run: | sudo apt-get update - sudo apt-get --assume-yes install libc6 libc6-i386 libc6-dev + sudo apt-get --assume-yes install libc6 libc6-i386 libc6-dev debuginfod - name: Install gdbserver dependency if: matrix.run_tests && matrix.enabled && matrix.os == 'ubuntu-22.04' run: sudo apt-get --assume-yes install gdbserver @@ -451,7 +451,7 @@ jobs: - name: Install test dependencies run: | sudo pip3 install 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' - sudo apt-get install --yes tzdata + sudo apt-get install --yes tzdata debuginfod - name: Checkout rizin run: | git clone https://github.com/${{ github.repository }} @@ -520,7 +520,7 @@ jobs: - name: Run debug tests run: | cd test - rz-test -L -o results.json db/archos/linux-x64 + rz-test -L -e db/archos/linux-x64/debuginfod -e db/archos/linux-x64/dbg_dmh -o results.json db/archos/linux-x64 working-directory: rizin build-static: @@ -608,7 +608,7 @@ jobs: name: Test source tarball if: contains(github.head_ref, 'dist') || contains(github.head_ref, 'extras') || contains(github.ref, 'release-') || github.ref == 'refs/heads/stable' runs-on: ubuntu-22.04 - needs: [create-tarball] + needs: [ create-tarball ] steps: - name: Install python and other dependencies run: sudo apt-get --assume-yes install python3-wheel python3-setuptools python3-pip @@ -646,7 +646,7 @@ jobs: name: Build OSX package runs-on: macos-12 if: contains(github.head_ref, 'dist') || contains(github.head_ref, 'osx') || contains(github.head_ref, 'mac') || ((contains(github.ref, 'release-') || github.ref == 'refs/heads/stable') && github.event_name == 'push') || github.event_name == 'schedule' - needs: [build-and-test] + needs: [ build-and-test ] steps: - uses: actions/checkout@v3 - name: Install pkg-config with Homebrew @@ -669,11 +669,11 @@ jobs: name: Build Windows zip/installer ${{ matrix.name }} runs-on: windows-latest if: contains(github.head_ref, 'dist') || contains(github.head_ref, 'windows') || (github.event_name == 'push' && (contains(github.ref, 'release-') || github.ref == 'refs/heads/stable')) - needs: [build-and-test] + needs: [ build-and-test ] strategy: fail-fast: false matrix: - name: [vs2019_static, clang_cl, clang_cl_x86] + name: [ vs2019_static, clang_cl, clang_cl_x86 ] include: - name: vs2019_static compiler: cl @@ -714,11 +714,11 @@ jobs: name: Build Android ${{ matrix.name }} package runs-on: ubuntu-22.04 if: contains(github.head_ref, 'dist') || contains(github.head_ref, 'android') || ((contains(github.ref, 'release-') || github.ref == 'refs/heads/stable') && github.event_name == 'push') || github.event_name == 'schedule' - needs: [build-and-test] + needs: [ build-and-test ] strategy: fail-fast: false matrix: - name: [x86_64, arm, aarch64] + name: [ x86_64, arm, aarch64 ] steps: - uses: actions/checkout@v3 - name: Install dependencies @@ -743,7 +743,7 @@ jobs: name: Include Rizin headers from C++ program (Linux) runs-on: ubuntu-22.04 if: contains(github.head_ref, 'dist') || contains(github.head_ref, 'cpp') || ((contains(github.ref, 'release-') || github.ref == 'refs/heads/stable') && github.event_name == 'push') || github.event_name == 'schedule' - needs: [build-and-test] + needs: [ build-and-test ] steps: - uses: actions/checkout@v3 - name: Install dependencies @@ -769,7 +769,7 @@ jobs: name: Test EXTRA_PREFIX works well runs-on: ubuntu-22.04 if: contains(github.head_ref, 'dist') || ((contains(github.ref, 'release-') || github.ref == 'refs/heads/stable') && github.event_name == 'push') || github.event_name == 'schedule' - needs: [build-and-test] + needs: [ build-and-test ] steps: - uses: actions/checkout@v3 - name: Install dependencies @@ -792,7 +792,7 @@ jobs: build-rzpipe: name: Build rizin rzpipe if: contains(github.head_ref, 'dist') || contains(github.ref, 'release-') || github.ref == 'refs/heads/stable' || github.event_name == 'schedule' - needs: [test-tarball] + needs: [ test-tarball ] runs-on: ubuntu-22.04 env: RZPIPE_TESTS: "rz-pipe-py rz-pipe-go" @@ -821,7 +821,7 @@ jobs: build-bindgen: name: Build rz-bindgen if: contains(github.head_ref, 'dist') || contains(github.ref, 'release-') || github.ref == 'refs/heads/stable' || github.event_name == 'schedule' - needs: [test-tarball] + needs: [ test-tarball ] runs-on: ubuntu-22.04 steps: - uses: actions/download-artifact@v3 @@ -867,7 +867,7 @@ jobs: system: - macos-12 runs-on: ${{ matrix.system }} - needs: [build-osx-pkg] + needs: [ build-osx-pkg ] steps: - name: Install pkg-config with Homebrew run: brew install pkg-config @@ -888,10 +888,10 @@ jobs: test-windows-clang_cl: name: Test Windows installer built with ${{ matrix.name }} runs-on: windows-latest - needs: [build-windows] + needs: [ build-windows ] strategy: matrix: - name: [clang_cl, clang_cl_x86] + name: [ clang_cl, clang_cl_x86 ] include: - name: clang_cl bits: 64 @@ -1000,7 +1000,7 @@ jobs: publish-docker-image: name: Publish Docker image on Docker Hub - needs: [build-and-test] + needs: [ build-and-test ] runs-on: ubuntu-22.04 if: github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.head_ref, 'container')) steps: diff --git a/.github/workflows/tcc.yml b/.github/workflows/tcc.yml index a1330b572f4..f49692750c6 100644 --- a/.github/workflows/tcc.yml +++ b/.github/workflows/tcc.yml @@ -92,7 +92,7 @@ jobs: run: | python3 -m pip install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' sudo apt-get update - sudo apt-get --assume-yes install libc6 libc6-i386 + sudo apt-get --assume-yes install libc6 libc6-i386 debuginfod - name: Run tests env: diff --git a/librz/analysis/dwarf_process.c b/librz/analysis/dwarf_process.c index 8bd6a4a62cd..4aee17e50b2 100644 --- a/librz/analysis/dwarf_process.c +++ b/librz/analysis/dwarf_process.c @@ -1527,13 +1527,16 @@ static bool function_from_die( fcn->link_name = attr_string(attr, ctx); break; case DW_AT_low_pc: - fcn->low_pc = rz_bin_dwarf_attr_udata(attr); + fcn->low_pc = rz_bin_dwarf_attr_addr( + attr, ctx->dw, ctx->unit->hdr.encoding.address_size, ctx->unit->addr_base); break; case DW_AT_high_pc: - fcn->high_pc = rz_bin_dwarf_attr_udata(attr); + fcn->high_pc = rz_bin_dwarf_attr_addr( + attr, ctx->dw, ctx->unit->hdr.encoding.address_size, ctx->unit->addr_base); break; case DW_AT_entry_pc: - fcn->entry_pc = rz_bin_dwarf_attr_udata(attr); + fcn->entry_pc = rz_bin_dwarf_attr_addr( + attr, ctx->dw, ctx->unit->hdr.encoding.address_size, ctx->unit->addr_base); break; case DW_AT_specification: /* u64 to declaration DIE with more info */ { diff --git a/librz/bin/dwarf/addr.c b/librz/bin/dwarf/addr.c index f2a8e0c7f7b..88b5c38d39d 100644 --- a/librz/bin/dwarf/addr.c +++ b/librz/bin/dwarf/addr.c @@ -4,7 +4,9 @@ #include #include "dwarf_private.h" -RZ_IPI bool DebugAddr_get_address(const RzBinDwarfAddr *self, ut64 *address, +RZ_API bool rz_bin_dwarf_addr_get( + RZ_BORROW RZ_NONNULL const RzBinDwarfAddr *self, + RZ_BORROW RZ_NONNULL ut64 *address, ut8 address_size, ut64 base, ut64 index) { rz_return_val_if_fail(self && self->reader && address, false); RzBinEndianReader *reader = self->reader; @@ -14,7 +16,7 @@ RZ_IPI bool DebugAddr_get_address(const RzBinDwarfAddr *self, ut64 *address, return true; } -RZ_IPI void DebugAddr_free(RzBinDwarfAddr *self) { +RZ_API void rz_bin_dwarf_addr_free(RzBinDwarfAddr *self) { if (!self) { return; } @@ -22,7 +24,7 @@ RZ_IPI void DebugAddr_free(RzBinDwarfAddr *self) { free(self); } -RZ_IPI RzBinDwarfAddr *DebugAddr_new(RzBinEndianReader *reader) { +RZ_API RZ_OWN RzBinDwarfAddr *rz_bin_dwarf_addr_new(RZ_OWN RZ_NONNULL RzBinEndianReader *reader) { rz_return_val_if_fail(reader, NULL); RzBinDwarfAddr *self = RZ_NEW0(RzBinDwarfAddr); RET_NULL_IF_FAIL(self); @@ -30,9 +32,9 @@ RZ_IPI RzBinDwarfAddr *DebugAddr_new(RzBinEndianReader *reader) { return self; } -RZ_IPI RzBinDwarfAddr *DebugAddr_from_file(RzBinFile *bf) { +RZ_API RZ_OWN RzBinDwarfAddr *rz_bin_dwarf_addr_from_file(RZ_BORROW RZ_NONNULL RzBinFile *bf) { rz_return_val_if_fail(bf, NULL); RzBinEndianReader *r = RzBinEndianReader_from_file(bf, ".debug_addr", false); RET_NULL_IF_FAIL(r); - return DebugAddr_new(r); + return rz_bin_dwarf_addr_new(r); } diff --git a/librz/bin/dwarf/attr.c b/librz/bin/dwarf/attr.c index bcd53d3104d..63c4a85e695 100644 --- a/librz/bin/dwarf/attr.c +++ b/librz/bin/dwarf/attr.c @@ -20,7 +20,7 @@ RZ_IPI bool RzBinDwarfAttr_parse( // http://www.dwarfstd.org/doc/DWARF4.pdf#page=161&zoom=100,0,560 switch (attr->form) { case DW_FORM_addr: - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_Addr; RET_FALSE_IF_FAIL(read_address(reader, &value->u64, address_size)); break; case DW_FORM_data1: @@ -166,25 +166,25 @@ RZ_IPI bool RzBinDwarfAttr_parse( DW_AT_addr_base attribute of the associated compilation unit. index into an array of addresses in the .debug_addr section.*/ case DW_FORM_addrx: - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_AddrIndex; ULE128_OR_RET_FALSE(value->u64); break; case DW_FORM_addrx1: - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_AddrIndex; U8_OR_RET_FALSE(value->u64); break; case DW_FORM_addrx2: - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_AddrIndex; U_OR_RET_FALSE(16, value->u64); break; case DW_FORM_addrx3: // TODO: .DW_FORM_addrx3 - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_AddrIndex; rz_buf_seek(reader->buffer, 3, RZ_BUF_CUR); RZ_LOG_ERROR("TODO: DW_FORM_addrx3\n"); break; case DW_FORM_addrx4: - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_AddrIndex; U_OR_RET_FALSE(32, value->u64); break; case DW_FORM_line_ptr: // offset in a section .debug_line_str @@ -211,7 +211,7 @@ RZ_IPI bool RzBinDwarfAttr_parse( break; // An index into the .debug_rnglists case DW_FORM_rnglistx: - value->kind = RzBinDwarfAttr_Address; + value->kind = RzBinDwarfAttr_RangelistPtr; ULE128_OR_RET_FALSE(value->u64); break; default: diff --git a/librz/bin/dwarf/dwarf.c b/librz/bin/dwarf/dwarf.c index 3bfa697bd82..7850b8fecaa 100644 --- a/librz/bin/dwarf/dwarf.c +++ b/librz/bin/dwarf/dwarf.c @@ -22,7 +22,7 @@ static inline RZ_OWN RzBinDWARF *dwarf_from_file( RzBinDWARF *dw = RZ_NEW0(RzBinDWARF); RET_NULL_IF_FAIL(dw); - dw->addr = DebugAddr_from_file(bf); + dw->addr = rz_bin_dwarf_addr_from_file(bf); dw->line_str = rz_bin_dwarf_line_str_from_file(bf); dw->aranges = rz_bin_dwarf_aranges_from_file(bf); @@ -38,6 +38,10 @@ static inline RZ_OWN RzBinDWARF *dwarf_from_file( if (dw->info) { dw->line = rz_bin_dwarf_line_from_file(bf, dw, is_dwo); } + if (!(dw->addr || dw->line_str || dw->aranges || dw->str || dw->str_offsets || dw->loclists || dw->rnglists || dw->abbrev)) { + rz_bin_dwarf_free(dw); + return NULL; + } return dw; } @@ -185,6 +189,33 @@ RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_search_debug_file_directory( return NULL; } +RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_from_debuginfod( + RZ_BORROW RZ_NONNULL RzBinFile *bf, + RZ_BORROW RZ_NONNULL RzList /**/ *debuginfod_urls) { + rz_return_val_if_fail(bf && debuginfod_urls, NULL); + + RzBinDWARF *dw = NULL; + char *build_id = read_build_id(bf); + if (!build_id) { + return NULL; + } + RzListIter *it = NULL; + const char *debuginfod_url = NULL; + rz_list_foreach (debuginfod_urls, it, debuginfod_url) { + char *url = rz_str_newf("%s/buildid/%s/debuginfo", debuginfod_url, build_id); + if (!url) { + break; + } + dw = rz_bin_dwarf_from_path(url, false); + free(url); + if (dw) { + break; + } + } + free(build_id); + return dw; +} + /** * \brief Load DWARF from split DWARF file * \param filepath The file path @@ -225,7 +256,7 @@ RZ_API void rz_bin_dwarf_free(RZ_OWN RZ_NULLABLE RzBinDWARF *dw) { rz_bin_dwarf_free(dw->parent); DebugRngLists_free(dw->rnglists); - DebugAddr_free(dw->addr); + rz_bin_dwarf_addr_free(dw->addr); rz_bin_dwarf_str_free(dw->str); rz_bin_dwarf_str_offsets_free(dw->str_offsets); diff --git a/librz/bin/dwarf/dwarf_private.h b/librz/bin/dwarf/dwarf_private.h index a60e162317a..77a83e46db1 100644 --- a/librz/bin/dwarf/dwarf_private.h +++ b/librz/bin/dwarf/dwarf_private.h @@ -52,13 +52,6 @@ static inline bool bf_bigendian(RzBinFile *bf) { } RZ_IPI bool RzBinDwarfEncoding_from_file(RzBinDwarfEncoding *encoding, RzBinFile *bf); -/// addr - -RZ_IPI bool DebugAddr_get_address(const RzBinDwarfAddr *self, ut64 *address, - ut8 address_size, ut64 base, ut64 index); -RZ_IPI void DebugAddr_free(RzBinDwarfAddr *self); -RZ_IPI RzBinDwarfAddr *DebugAddr_new(RzBinEndianReader *reader); -RZ_IPI RzBinDwarfAddr *DebugAddr_from_file(RzBinFile *bf); /// range diff --git a/librz/bin/dwarf/loclists.c b/librz/bin/dwarf/loclists.c index 36f41fef224..bada6326247 100644 --- a/librz/bin/dwarf/loclists.c +++ b/librz/bin/dwarf/loclists.c @@ -165,7 +165,7 @@ static bool convert_raw( *entry = NULL; return true; case DW_LLE_base_addressx: - ERR_IF_FAIL(DebugAddr_get_address( + ERR_IF_FAIL(rz_bin_dwarf_addr_get( addr, &self->base_address, encoding->address_size, cu->addr_base, raw->base_addressx.addr)); return true; @@ -175,17 +175,17 @@ static bool convert_raw( case DW_LLE_startx_endx: range = RZ_NEW0(RzBinDwarfRange); ERR_IF_FAIL(range); - ERR_IF_FAIL(DebugAddr_get_address( + ERR_IF_FAIL(rz_bin_dwarf_addr_get( addr, &range->begin, encoding->address_size, cu->addr_base, raw->startx_endx.begin)); - ERR_IF_FAIL(DebugAddr_get_address( + ERR_IF_FAIL(rz_bin_dwarf_addr_get( addr, &range->end, encoding->address_size, cu->addr_base, raw->startx_endx.end)); break; case DW_LLE_startx_length: range = RZ_NEW0(RzBinDwarfRange); ERR_IF_FAIL(range); - ERR_IF_FAIL(DebugAddr_get_address( + ERR_IF_FAIL(rz_bin_dwarf_addr_get( addr, &range->begin, encoding->address_size, cu->addr_base, raw->startx_length.begin)); range->end = (raw->startx_length.length + raw->startx_length.begin) & mask; diff --git a/librz/bin/dwarf/rnglists.c b/librz/bin/dwarf/rnglists.c index 6ff77bdca16..76dc50c0d13 100644 --- a/librz/bin/dwarf/rnglists.c +++ b/librz/bin/dwarf/rnglists.c @@ -154,22 +154,22 @@ static bool convert_raw( *out = NULL; return true; case DW_RLE_base_addressx: - RET_FALSE_IF_FAIL(DebugAddr_get_address(addr, &self->base_address, + RET_FALSE_IF_FAIL(rz_bin_dwarf_addr_get(addr, &self->base_address, cu->hdr.encoding.address_size, cu->addr_base, raw->base_addressx.addr)); *out = NULL; return true; case DW_RLE_startx_endx: range = RZ_NEW0(RzBinDwarfRange); RET_FALSE_IF_FAIL(range); - RET_FALSE_IF_FAIL(DebugAddr_get_address(addr, &range->begin, + RET_FALSE_IF_FAIL(rz_bin_dwarf_addr_get(addr, &range->begin, cu->hdr.encoding.address_size, cu->addr_base, raw->startx_endx.begin)); - RET_FALSE_IF_FAIL(DebugAddr_get_address(addr, &range->end, + RET_FALSE_IF_FAIL(rz_bin_dwarf_addr_get(addr, &range->end, cu->hdr.encoding.address_size, cu->addr_base, raw->startx_endx.end)); break; case DW_RLE_startx_length: range = RZ_NEW0(RzBinDwarfRange); RET_FALSE_IF_FAIL(range); - RET_FALSE_IF_FAIL(DebugAddr_get_address(addr, &range->begin, + RET_FALSE_IF_FAIL(rz_bin_dwarf_addr_get(addr, &range->begin, cu->hdr.encoding.address_size, cu->addr_base, raw->startx_length.begin)); range->end = (raw->startx_length.length + raw->startx_length.begin) & mask; break; diff --git a/librz/core/cbin.c b/librz/core/cbin.c index 6246c7d29ee..efeefb5daa2 100644 --- a/librz/core/cbin.c +++ b/librz/core/cbin.c @@ -652,6 +652,24 @@ static inline RzBinDWARF *load_dwarf(RzCore *core, RzBinFile *binfile) { } } } + + if (rz_config_get_b(core->config, "bin.dbginfo.debuginfod")) { + char *debuginfod_urls = (char *)rz_config_get(core->config, "bin.dbginfo.debuginfod_urls"); + if (RZ_STR_ISNOTEMPTY(debuginfod_urls)) { + debuginfod_urls = rz_str_new(debuginfod_urls); + } else { + debuginfod_urls = rz_sys_getenv("DEBUGINFOD_URLS"); + } + RzList *urls = RZ_STR_ISNOTEMPTY(debuginfod_urls) ? rz_str_split_duplist(debuginfod_urls, " ", true) : NULL; + if (urls) { + RzBinDWARF *sep_dw = rz_bin_dwarf_from_debuginfod(binfile, urls); + rz_list_free(urls); + if (sep_dw) { + sep_dw->parent = dw; + return sep_dw; + } + } + } return dw; } diff --git a/librz/core/cconfig.c b/librz/core/cconfig.c index abd37c7e48a..c2f6dce940f 100644 --- a/librz/core/cconfig.c +++ b/librz/core/cconfig.c @@ -3248,6 +3248,10 @@ RZ_API int rz_core_config_init(RzCore *core) { SETCB("bin.dbginfo.dwo_path", "", NULL, "Load separate debug information (DWARF) file if available"); SETCB("bin.dbginfo.debug_file_directory", "/usr/lib/debug", NULL, "Set the directories which searches for separate debugging information files to directory"); + SETCB("bin.dbginfo.debuginfod", "false", NULL, + "Load debug file from bin.dbginfo.debuginfod_urls or DEBUGINFOD_URLS environment variable"); + SETCB("bin.dbginfo.debuginfod_urls", "http://debuginfod.elfutils.org/", NULL, + "Looks for debug symbols on the debuginfod servers, the value is a string of a space separated URLs"); 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/include/rz_bin_dwarf.h b/librz/include/rz_bin_dwarf.h index 7a2e5758bc8..4b68827bf51 100644 --- a/librz/include/rz_bin_dwarf.h +++ b/librz/include/rz_bin_dwarf.h @@ -993,7 +993,9 @@ typedef struct { // http://www.dwarfstd.org/doc/DWARF4.pdf#page=29&zoom=100,0,0 typedef enum { - RzBinDwarfAttr_Address, + RzBinDwarfAttr_Addr, + RzBinDwarfAttr_AddrBase, /// An offset to a set of addresses in the `.debug_addr` section. + RzBinDwarfAttr_AddrIndex, /// An index into a set of addresses in the `.debug_addr` section. RzBinDwarfAttr_Block, RzBinDwarfAttr_Constant, RzBinDwarfAttr_UConstant, @@ -1517,6 +1519,9 @@ RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_from_path( RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_search_debug_file_directory( RZ_BORROW RZ_NONNULL RzBinFile *bf, RZ_BORROW RZ_NONNULL RzList /**/ *debug_file_directorys); +RZ_API RZ_OWN RzBinDWARF *rz_bin_dwarf_from_debuginfod( + RZ_BORROW RZ_NONNULL RzBinFile *bf, + RZ_BORROW RZ_NONNULL RzList /**/ *debuginfod_urls); RZ_API void rz_bin_dwarf_free(RZ_OWN RZ_NULLABLE RzBinDWARF *dw); @@ -1800,6 +1805,15 @@ RZ_API bool rz_bin_dwarf_block_empty(const RzBinDwarfBlock *self); RZ_API void rz_bin_dwarf_block_dump(const RzBinDwarfBlock *self, RzStrBuf *sb); RZ_API const ut8 *rz_bin_dwarf_block_data(const RzBinDwarfBlock *self); +/// addr +RZ_API bool rz_bin_dwarf_addr_get( + RZ_BORROW RZ_NONNULL const RzBinDwarfAddr *self, + RZ_BORROW RZ_NONNULL ut64 *address, + ut8 address_size, ut64 base, ut64 index); +RZ_API void rz_bin_dwarf_addr_free(RzBinDwarfAddr *self); +RZ_API RZ_OWN RzBinDwarfAddr *rz_bin_dwarf_addr_new(RZ_OWN RZ_NONNULL RzBinEndianReader *reader); +RZ_API RZ_OWN RzBinDwarfAddr *rz_bin_dwarf_addr_from_file(RZ_BORROW RZ_NONNULL RzBinFile *bf); + /** * \brief Safely get the string from an RzBinDwarfAttrValue if it has one. */ @@ -1821,6 +1835,30 @@ static inline char *rz_bin_dwarf_attr_string( return NULL; } +static inline ut64 rz_bin_dwarf_attr_addr( + const RzBinDwarfAttr *attr, + RzBinDWARF *dw, + ut64 addr_size, ut64 base) { + rz_return_val_if_fail(attr, UT64_MAX); + + const RzBinDwarfAttrValue *v = &attr->value; + if (v->kind == RzBinDwarfAttr_Addr) { + return attr->value.u64; + } else if (v->kind == RzBinDwarfAttr_AddrIndex) { + ut64 addr = 0; + if (dw && rz_bin_dwarf_addr_get(dw->addr, &addr, addr_size, base, attr->value.u64)) { + return addr; + } else { + rz_warn_if_reached(); + } + } else if (v->kind == RzBinDwarfAttr_UConstant) { + return attr->value.u64; + } else { + rz_warn_if_reached(); + } + return attr->value.u64; +} + static inline ut64 rz_bin_dwarf_attr_udata(const RzBinDwarfAttr *attr) { rz_return_val_if_fail(attr, UT64_MAX); return attr->value.u64; diff --git a/test/db/archos/linux-x64/debuginfod b/test/db/archos/linux-x64/debuginfod new file mode 100644 index 00000000000..a6b6202afbf --- /dev/null +++ b/test/db/archos/linux-x64/debuginfod @@ -0,0 +1,125 @@ +NAME="Debugging Information in debuginfod" +FILE= +CMDS=< 34 sym.deregister_tm_clones +0x000010f0 4 57 -> 51 sym.register_tm_clones +0x00001130 5 57 -> 54 sym.__do_global_dtors_aux +0x00001080 1 6 sym.imp.__cxa_finalize +0x00001170 1 9 entry.init0 +0x000013b0 1 9 sym._fini +0x00001180 5 170 dbg.fn1 +0x00001060 1 6 sym.imp.malloc +0x00001030 1 6 sym.imp.strncpy +0x00001230 1 48 dbg.new_some +0x00001050 1 6 sym.imp.memset +0x00001260 6 335 dbg.main +0x00001000 3 23 sym._init +0x00001040 1 6 sym.imp.printf +0x00001070 1 6 sym.imp.strdup + ; CALL XREF from dbg.main @ 0x132a +/ _Bool fn1(int a, char *g, double q, struct Some *gg, some_t **out) +| ; var char **arg1 @ rdi +| ; var const char *arg2 @ rsi +| ; var int64_t arg7 @ xmm0 +| ; var uintmax_t arg3 @ rdx +| ; var some_t *arg4 @ rcx +| ; arg int a @ stack - 0x10 +| ; arg char *g @ stack - 0x18 +| ; arg double q @ stack - 0x20 +| ; arg struct Some *gg @ stack - 0x28 +| ; arg some_t **out @ stack - 0x30 +| 0x00001180 push rbp ; float_ex1.c:15 +| 0x00001181 mov rbp, rsp +| 0x00001184 sub rsp, 0x30 +| 0x00001188 mov dword [a], edi ; arg1 +| 0x0000118b mov qword [g], rsi ; arg2 +| 0x0000118f movsd qword [q], xmm0 ; arg7 +| 0x00001194 mov qword [gg], rdx ; arg3 +| 0x00001198 mov qword [out], rcx ; arg4 +| 0x0000119c cmp qword [gg], 0 ; float_ex1.c:16 +| ,=< 0x000011a1 je 0x11b2 +| | 0x000011a7 cmp qword [out], 0 +| ,==< 0x000011ac jne 0x11bb +| |`-> 0x000011b2 mov byte [a + 0x7], 0 ; float_ex1.c:17 +| |,=< 0x000011b6 jmp 0x121c +| `--> 0x000011bb mov edi, 0x18 ; float_ex1.c:19 ; size_t size +| | 0x000011c0 call sym.imp.malloc ; void *malloc(size_t size) +| | 0x000011c5 mov rcx, rax +| | 0x000011c8 mov rax, qword [out] +| | 0x000011cc mov qword [rax], rcx +| | 0x000011cf mov ecx, dword [a] ; float_ex1.c:20 +| | 0x000011d2 mov rax, qword [out] +| | 0x000011d6 mov rax, qword [rax] +| | 0x000011d9 mov dword [rax], ecx +| | 0x000011db mov rax, qword [out] ; float_ex1.c:21 +| | 0x000011df mov rdi, qword [rax] +| | 0x000011e2 add rdi, 4 ; char *dest +| | 0x000011e6 mov rsi, qword [g] ; const char *src +| | 0x000011ea mov edx, 5 ; size_t n +| | 0x000011ef call sym.imp.strncpy ; char *strncpy(char *dest, const char *src, size_t n) +| | 0x000011f4 movsd xmm0, qword [q] ; float_ex1.c:22 +| | 0x000011f9 cvtsd2ss xmm0, xmm0 +| | 0x000011fd mov rax, qword [out] +| | 0x00001201 mov rax, qword [rax] +| | 0x00001204 movss dword [rax + 0xc], xmm0 +| | 0x00001209 mov rcx, qword [gg] ; float_ex1.c:23 +| | 0x0000120d mov rax, qword [out] +| | 0x00001211 mov rax, qword [rax] +| | 0x00001214 mov qword [rax + 0x10], rcx +| | 0x00001218 mov byte [a + 0x7], 1 ; float_ex1.c:24 +| | ; CODE XREF from dbg.fn1 @ 0x11b6 +| `-> 0x0000121c mov al, byte [a + 0x7] ; float_ex1.c:25 +| 0x0000121f and al, 1 +| 0x00001221 movzx eax, al +| 0x00001224 add rsp, 0x30 +| 0x00001228 pop rbp +\ 0x00001229 ret +EOF +RUN