From bd552716ee7937cad9d54d4966532d6ea6dbc1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= Date: Sun, 30 Apr 2023 23:54:32 +0200 Subject: [PATCH] libbacktrace: get debug information for loaded dlls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/ianlancetaylor/libbacktrace/issues/53, except that libraries loaded after the backtrace_initialize are not handled. But as far as I can see that's the same for elf. Tested on x86_64-linux and i686-w64-mingw32. -- >8 -- * pecoff.c (coff_add): New argument for the module handle of the file, to get the base address. * pecoff.c (backtrace_initialize): Iterate over loaded libraries and call coff_add. Signed-off-by: Björn Schäpers --- libbacktrace/pecoff.c | 104 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 8 deletions(-) diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c index f976a963bf3..3eb9c4a4853 100644 --- a/libbacktrace/pecoff.c +++ b/libbacktrace/pecoff.c @@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #endif #include +#include #endif /* Coff file header. */ @@ -592,7 +593,8 @@ coff_syminfo (struct backtrace_state *state, uintptr_t addr, static int coff_add (struct backtrace_state *state, int descriptor, backtrace_error_callback error_callback, void *data, - fileline *fileline_fn, int *found_sym, int *found_dwarf) + fileline *fileline_fn, int *found_sym, int *found_dwarf, + uintptr_t module_handle ATTRIBUTE_UNUSED) { struct backtrace_view fhdr_view; off_t fhdr_off; @@ -870,12 +872,7 @@ coff_add (struct backtrace_state *state, int descriptor, } #ifdef HAVE_WINDOWS_H - { - uintptr_t module_handle; - - module_handle = (uintptr_t) GetModuleHandle (NULL); - base_address = module_handle - image_base; - } + base_address = module_handle - image_base; #endif if (!backtrace_dwarf_add (state, base_address, &dwarf_sections, @@ -903,6 +900,53 @@ coff_add (struct backtrace_state *state, int descriptor, return 0; } +#ifdef HAVE_WINDOWS_H +static void +free_modules (struct backtrace_state *state, + backtrace_error_callback error_callback, void *data, + HMODULE **modules, DWORD bytes_allocated) +{ + backtrace_free (state, *modules, bytes_allocated, error_callback, data); + *modules = NULL; +} + +static void +get_all_modules (struct backtrace_state *state, + backtrace_error_callback error_callback, void *data, + HMODULE **modules, DWORD *module_count, DWORD *bytes_allocated) +{ + DWORD bytes_needed = 0; + + for (;;) + { + *bytes_allocated = *module_count * sizeof(HMODULE); + *modules = backtrace_alloc (state, *bytes_allocated, error_callback, data); + + if (*modules == NULL) + return; + + if (!EnumProcessModules (GetCurrentProcess (), *modules, *module_count, + &bytes_needed)) + { + error_callback(data, "Could not enumerate process modules", + (int) GetLastError ()); + free_modules (state, error_callback, data, modules, *bytes_allocated); + return; + } + + *module_count = bytes_needed / sizeof(HMODULE); + if (bytes_needed <= *bytes_allocated) + { + return; + } + + free_modules (state, error_callback, data, modules, *bytes_allocated); + // Add an extra of 2, of some module is loaded in another thread. + *module_count += 2; + } +} +#endif + /* Initialize the backtrace data we need from an ELF executable. At the ELF level, all we need to do is find the debug info sections. */ @@ -917,12 +961,56 @@ backtrace_initialize (struct backtrace_state *state, int found_sym; int found_dwarf; fileline coff_fileline_fn; + uintptr_t module_handle = 0; + +#ifdef HAVE_WINDOWS_H + DWORD i; + DWORD module_count = 100; + DWORD bytes_allocated_for_modules = 0; + HMODULE *modules = NULL; + char module_name[MAX_PATH]; + int module_found_sym; + fileline module_fileline_fn; + + module_handle = (uintptr_t) GetModuleHandle (NULL); +#endif ret = coff_add (state, descriptor, error_callback, data, - &coff_fileline_fn, &found_sym, &found_dwarf); + &coff_fileline_fn, &found_sym, &found_dwarf, module_handle); if (!ret) return 0; +#ifdef HAVE_WINDOWS_H + get_all_modules (state, error_callback, data, &modules, + &module_count, &bytes_allocated_for_modules); + + for (i = 0; i < module_count; ++i) + { + if (GetModuleFileNameA (modules[i], module_name, MAX_PATH - 1)) + { + if (strcmp (filename, module_name) == 0) + continue; + + module_handle = (uintptr_t) GetModuleHandleA (module_name); + if (module_handle == 0) + continue; + + descriptor = backtrace_open (module_name, error_callback, data, NULL); + if (descriptor < 0) + continue; + + coff_add (state, descriptor, error_callback, data, + &module_fileline_fn, &module_found_sym, &found_dwarf, + module_handle); + if (module_found_sym) + found_sym = 1; + } + } + + if (modules) + free_modules (state, error_callback, data, &modules, bytes_allocated_for_modules); +#endif + if (!state->threaded) { if (found_sym) -- 2.42.1