diff --git a/src/symbols/dwarf/dwarf.hpp b/src/symbols/dwarf/dwarf.hpp index 835a7f9..f643285 100644 --- a/src/symbols/dwarf/dwarf.hpp +++ b/src/symbols/dwarf/dwarf.hpp @@ -531,6 +531,56 @@ namespace libdwarf { } } }; + + class srcfiles { + Dwarf_Debug dbg = nullptr; + char** dw_srcfiles = nullptr; + Dwarf_Unsigned dw_filecount = 0; + public: + srcfiles(Dwarf_Debug dbg, char** dw_srcfiles, Dwarf_Signed filecount) + : dbg(dbg), dw_srcfiles(dw_srcfiles), dw_filecount(static_cast(filecount)) + { + if(filecount < 0) { + throw internal_error(microfmt::format("Unexpected dw_filecount {}", filecount)); + } + } + ~srcfiles() { + if(dw_srcfiles) { + for(unsigned i = 0; i < dw_filecount; i++) { + dwarf_dealloc(dbg, dw_srcfiles[i], DW_DLA_STRING); + dw_srcfiles[i] = nullptr; + } + dwarf_dealloc(dbg, dw_srcfiles, DW_DLA_LIST); + } + } + srcfiles(const srcfiles&) = delete; + srcfiles(srcfiles&& other) { + std::swap(dbg, other.dbg); + std::swap(dw_srcfiles, other.dw_srcfiles); + std::swap(dw_filecount, other.dw_filecount); + } + srcfiles& operator=(const srcfiles&) = delete; + srcfiles& operator=(srcfiles&& other) { + std::swap(dbg, other.dbg); + std::swap(dw_srcfiles, other.dw_srcfiles); + std::swap(dw_filecount, other.dw_filecount); + return *this; + } + // note: dwarf uses 1-indexing + const char* get(Dwarf_Unsigned file_i) const { + if(file_i >= dw_filecount) { + throw internal_error(microfmt::format( + "Error while accessing the srcfiles list, requested index {} is out of bounds (count = {})", + file_i, + dw_filecount + )); + } + return dw_srcfiles[file_i]; + } + Dwarf_Unsigned count() const { + return dw_filecount; + } + }; } } } diff --git a/src/symbols/dwarf/dwarf_resolver.cpp b/src/symbols/dwarf/dwarf_resolver.cpp index d243e49..737e51b 100644 --- a/src/symbols/dwarf/dwarf_resolver.cpp +++ b/src/symbols/dwarf/dwarf_resolver.cpp @@ -93,7 +93,7 @@ namespace libdwarf { std::vector cu_cache; bool generated_cu_cache = false; // Map from CU -> {srcfiles, count} - std::unordered_map> srcfiles_cache; + std::unordered_map srcfiles_cache; // Map from CU -> split full cu resolver std::unordered_map> split_full_cu_resolvers; // info for resolving a dwo object @@ -205,15 +205,6 @@ namespace libdwarf { for(auto& entry : line_tables) { dwarf_srclines_dealloc_b(entry.second.line_context); } - for(auto& entry : srcfiles_cache) { - auto srcfiles = entry.second.first; - auto count = entry.second.second; - for(int i = 0; i < count; i++) { - dwarf_dealloc(dbg, srcfiles[i], DW_DLA_STRING); - srcfiles[i] = nullptr; - } - dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST); - } // subprograms_cache needs to be destroyed before dbg otherwise there will be another use after free subprograms_cache.clear(); split_full_cu_resolvers.clear(); @@ -354,15 +345,11 @@ namespace libdwarf { char** dw_srcfiles; Dwarf_Signed dw_filecount; VERIFY(wrap(dwarf_srcfiles, cu_die.get(), &dw_srcfiles, &dw_filecount) == DW_DLV_OK); + srcfiles srcfiles(cu_die.dbg, dw_srcfiles, dw_filecount); if(Dwarf_Signed(file_i) < dw_filecount) { // dwarf is using 1-indexing - filename = dw_srcfiles[file_i]; + filename = srcfiles.get(file_i); } - for(int i = 0; i < dw_filecount; i++) { - dwarf_dealloc(cu_die.dbg, dw_srcfiles[i], DW_DLA_STRING); - dw_srcfiles[i] = nullptr; - } - dwarf_dealloc(cu_die.dbg, dw_srcfiles, DW_DLA_LIST); } else { auto off = cu_die.get_global_offset(); auto it = srcfiles_cache.find(off); @@ -370,13 +357,11 @@ namespace libdwarf { char** dw_srcfiles; Dwarf_Signed dw_filecount; VERIFY(wrap(dwarf_srcfiles, cu_die.get(), &dw_srcfiles, &dw_filecount) == DW_DLV_OK); - it = srcfiles_cache.insert(it, {off, {dw_srcfiles, dw_filecount}}); + it = srcfiles_cache.insert(it, {off, srcfiles{cu_die.dbg, dw_srcfiles, dw_filecount}}); } - char** dw_srcfiles = it->second.first; - Dwarf_Signed dw_filecount = it->second.second; - if(Dwarf_Signed(file_i) < dw_filecount) { + if(file_i < it->second.count()) { // dwarf is using 1-indexing - filename = dw_srcfiles[file_i]; + filename = it->second.get(file_i); } } return filename;