Crashlog: Re-use BFD instances for the same object

This commit is contained in:
Jonathan G Rennison
2024-02-02 20:06:44 +00:00
parent fcc6529b6a
commit a4c14171a7
4 changed files with 51 additions and 17 deletions

View File

@@ -1236,10 +1236,10 @@ void CrashLog::MakeCrashSavegameAndScreenshot()
sym_info_bfd::sym_info_bfd(bfd_vma addr_) : addr(addr_), abfd(nullptr), syms(nullptr), sym_count(0), sym_info_bfd::sym_info_bfd(bfd_vma addr_) : addr(addr_), abfd(nullptr), syms(nullptr), sym_count(0),
file_name(nullptr), function_name(nullptr), function_addr(0), line(0), found(false) {} file_name(nullptr), function_name(nullptr), function_addr(0), line(0), found(false) {}
sym_info_bfd::~sym_info_bfd() sym_bfd_obj::~sym_bfd_obj()
{ {
free(syms); free(this->syms);
if (abfd != nullptr) bfd_close(abfd); if (this->abfd != nullptr) bfd_close(this->abfd);
} }
static void find_address_in_section(bfd *abfd, asection *section, void *data) static void find_address_in_section(bfd *abfd, asection *section, void *data)
@@ -1282,20 +1282,33 @@ static void find_address_in_section(bfd *abfd, asection *section, void *data)
} }
} }
void lookup_addr_bfd(const char *obj_file_name, sym_info_bfd &info) void lookup_addr_bfd(const char *obj_file_name, sym_bfd_obj_cache &bfdc, sym_info_bfd &info)
{ {
info.abfd = bfd_openr(obj_file_name, nullptr); auto res = bfdc.cache.try_emplace(obj_file_name);
sym_bfd_obj &obj = res.first->second;
if (res.second) {
/* New sym_bfd_obj */
obj.abfd = bfd_openr(obj_file_name, nullptr);
if (info.abfd == nullptr) return; if (obj.abfd == nullptr) return;
if (!bfd_check_format(info.abfd, bfd_object) || (bfd_get_file_flags(info.abfd) & HAS_SYMS) == 0) return; if (!bfd_check_format(obj.abfd, bfd_object) || (bfd_get_file_flags(obj.abfd) & HAS_SYMS) == 0) return;
unsigned int size; unsigned int size;
info.sym_count = bfd_read_minisymbols(info.abfd, false, (void**) &(info.syms), &size); obj.sym_count = bfd_read_minisymbols(obj.abfd, false, (void**) &(obj.syms), &size);
if (info.sym_count <= 0) { if (obj.sym_count <= 0) {
info.sym_count = bfd_read_minisymbols(info.abfd, true, (void**) &(info.syms), &size); obj.sym_count = bfd_read_minisymbols(obj.abfd, true, (void**) &(obj.syms), &size);
}
if (obj.sym_count <= 0) return;
obj.usable = true;
} }
if (info.sym_count <= 0) return;
if (!obj.usable) return;
info.abfd = obj.abfd;
info.syms = obj.syms;
info.sym_count = obj.sym_count;
bfd_map_over_sections(info.abfd, find_address_in_section, &info); bfd_map_over_sections(info.abfd, find_address_in_section, &info);
} }

View File

@@ -29,9 +29,23 @@
#undef PACKAGE_VERSION #undef PACKAGE_VERSION
#endif #endif
#include <map>
#if defined(WITH_BFD) #if defined(WITH_BFD)
struct sym_info_bfd;
void lookup_addr_bfd(const char *obj_file_name, sym_info_bfd &info); struct sym_bfd_obj {
bfd *abfd = nullptr;
asymbol **syms = nullptr;
const char *file_name = nullptr;
long sym_count = 0;
bool usable = false;
~sym_bfd_obj();
};
struct sym_bfd_obj_cache {
std::map<std::string, sym_bfd_obj> cache;
};
struct sym_info_bfd { struct sym_info_bfd {
bfd_vma addr; bfd_vma addr;
@@ -45,9 +59,10 @@ struct sym_info_bfd {
bool found; bool found;
sym_info_bfd(bfd_vma addr_); sym_info_bfd(bfd_vma addr_);
~sym_info_bfd();
}; };
void lookup_addr_bfd(const char *obj_file_name, sym_bfd_obj_cache &bfdc, sym_info_bfd &info);
#endif #endif
#endif /* CRASHLOG_BFD_H */ #endif /* CRASHLOG_BFD_H */

View File

@@ -521,6 +521,7 @@ class CrashLogUnix : public CrashLog {
char **messages = backtrace_symbols(trace, trace_size); char **messages = backtrace_symbols(trace, trace_size);
#if defined(WITH_BFD) #if defined(WITH_BFD)
sym_bfd_obj_cache bfd_cache;
bfd_init(); bfd_init();
#endif /* WITH_BFD */ #endif /* WITH_BFD */
@@ -574,7 +575,7 @@ class CrashLogUnix : public CrashLog {
/* subtract one to get the line before the return address, i.e. the function call line */ /* subtract one to get the line before the return address, i.e. the function call line */
sym_info_bfd bfd_info(reinterpret_cast<bfd_vma>(trace[i]) - reinterpret_cast<bfd_vma>(info.dli_fbase) - 1); sym_info_bfd bfd_info(reinterpret_cast<bfd_vma>(trace[i]) - reinterpret_cast<bfd_vma>(info.dli_fbase) - 1);
if (dladdr_result && info.dli_fname) { if (dladdr_result && info.dli_fname) {
lookup_addr_bfd(info.dli_fname, bfd_info); lookup_addr_bfd(info.dli_fname, bfd_cache, bfd_info);
if (bfd_info.file_name != nullptr) file_name = bfd_info.file_name; if (bfd_info.file_name != nullptr) file_name = bfd_info.file_name;
if (bfd_info.function_name != nullptr) func_name = bfd_info.function_name; if (bfd_info.function_name != nullptr) func_name = bfd_info.function_name;
if (bfd_info.function_addr != 0) func_addr = reinterpret_cast<void *>(bfd_info.function_addr + reinterpret_cast<bfd_vma>(info.dli_fbase)); if (bfd_info.function_addr != 0) func_addr = reinterpret_cast<void *>(bfd_info.function_addr + reinterpret_cast<bfd_vma>(info.dli_fbase));

View File

@@ -399,6 +399,11 @@ static const uint MAX_FRAMES = 64;
std::array<DWORD64, 8> last_offsets = {}; std::array<DWORD64, 8> last_offsets = {};
#if defined(WITH_BFD)
sym_bfd_obj_cache bfd_cache;
bfd_init();
#endif /* WITH_BFD */
/* Walk stack at most MAX_FRAMES deep in case the stack is corrupt. */ /* Walk stack at most MAX_FRAMES deep in case the stack is corrupt. */
for (uint num = 0; num < MAX_FRAMES; num++) { for (uint num = 0; num < MAX_FRAMES; num++) {
auto guard = scope_guard([&]() { auto guard = scope_guard([&]() {
@@ -448,7 +453,7 @@ static const uint MAX_FRAMES = 64;
#if defined (WITH_BFD) #if defined (WITH_BFD)
/* subtract one to get the line before the return address, i.e. the function call line */ /* subtract one to get the line before the return address, i.e. the function call line */
sym_info_bfd bfd_info(static_cast<bfd_vma>(frame.AddrPC.Offset) - 1); sym_info_bfd bfd_info(static_cast<bfd_vma>(frame.AddrPC.Offset) - 1);
lookup_addr_bfd(image_name, bfd_info); lookup_addr_bfd(image_name, bfd_cache, bfd_info);
if (bfd_info.function_name != nullptr) { if (bfd_info.function_name != nullptr) {
const char *func_name = bfd_info.function_name; const char *func_name = bfd_info.function_name;
#if defined(WITH_DEMANGLE) #if defined(WITH_DEMANGLE)