From 942a9cf2a958113d2ab46f5b015c36e569abedcf Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 28 Apr 2024 11:14:17 -0700 Subject: [PATCH] libbacktrace: load Windows modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch from Björn Schäpers . * configure.ac: Checked for tlhelp32.h * pecoff.c: Include if available. (backtrace_initialize): Use tlhelp32 api for a snapshot to detect loaded modules. (coff_add): New argument for the module handle of the file, to get the base address. * configure, config.h.in: Regenerate. --- libbacktrace/config.h.in | 3 ++ libbacktrace/configure | 15 ++++++++ libbacktrace/configure.ac | 4 +++ libbacktrace/pecoff.c | 73 ++++++++++++++++++++++++++++++++++----- 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index ee2616335c7..9b8ab88ab63 100644 --- a/libbacktrace/config.h.in +++ b/libbacktrace/config.h.in @@ -101,6 +101,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_TLHELP32_H + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H diff --git a/libbacktrace/configure b/libbacktrace/configure index d6d6606a72c..ab94a85f45c 100755 --- a/libbacktrace/configure +++ b/libbacktrace/configure @@ -13523,6 +13523,21 @@ fi done +for ac_header in tlhelp32.h +do : + ac_fn_c_check_header_compile "$LINENO" "tlhelp32.h" "ac_cv_header_tlhelp32_h" "#ifdef HAVE_WINDOWS_H +# include +#endif +" +if test "x$ac_cv_header_tlhelp32_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TLHELP32_H 1 +_ACEOF + +fi + +done + # Check for the fcntl function. if test -n "${with_target_subdir}"; then diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac index 3e0075a2b79..59e9c415db8 100644 --- a/libbacktrace/configure.ac +++ b/libbacktrace/configure.ac @@ -380,6 +380,10 @@ if test "$have_loadquery" = "yes"; then fi AC_CHECK_HEADERS(windows.h) +AC_CHECK_HEADERS(tlhelp32.h, [], [], +[#ifdef HAVE_WINDOWS_H +# include +#endif]) # Check for the fcntl function. if test -n "${with_target_subdir}"; then diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c index 9e437d810c7..4f267841178 100644 --- a/libbacktrace/pecoff.c +++ b/libbacktrace/pecoff.c @@ -49,6 +49,18 @@ POSSIBILITY OF SUCH DAMAGE. */ #endif #include + +#ifdef HAVE_TLHELP32_H +#include + +#ifdef UNICODE +/* If UNICODE is defined, all the symbols are replaced by a macro to use the + wide variant. But we need the ansi variant, so undef the macros. */ +#undef MODULEENTRY32 +#undef Module32First +#undef Module32Next +#endif +#endif #endif /* Coff file header. */ @@ -592,7 +604,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 +883,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, @@ -917,12 +925,61 @@ backtrace_initialize (struct backtrace_state *state, int found_sym; int found_dwarf; fileline coff_fileline_fn; + uintptr_t module_handle = 0; +#ifdef HAVE_TLHELP32_H + fileline module_fileline_fn; + int module_found_sym; + HANDLE snapshot; +#endif + +#ifdef HAVE_WINDOWS_H + 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_TLHELP32_H + do + { + snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0); + } + while (snapshot == INVALID_HANDLE_VALUE + && GetLastError () == ERROR_BAD_LENGTH); + + if (snapshot != INVALID_HANDLE_VALUE) + { + MODULEENTRY32 entry; + BOOL ok; + entry.dwSize = sizeof (MODULEENTRY32); + + for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry)) + { + if (strcmp (filename, entry.szExePath) == 0) + continue; + + module_handle = (uintptr_t) entry.hModule; + if (module_handle == 0) + continue; + + descriptor = backtrace_open (entry.szExePath, 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; + } + + CloseHandle (snapshot); + } +#endif + if (!state->threaded) { if (found_sym)