libbacktrace: load Windows modules

Patch from Björn Schäpers <bjoern@hazardy.de>.

	* configure.ac: Checked for tlhelp32.h
	* pecoff.c: Include <tlhelp32.h> 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.
This commit is contained in:
Ian Lance Taylor 2024-04-28 11:14:17 -07:00
parent 507f3ce34c
commit 942a9cf2a9
4 changed files with 87 additions and 8 deletions

View File

@ -101,6 +101,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */ /* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H #undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <tlhelp32.h> header file. */
#undef HAVE_TLHELP32_H
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H

View File

@ -13523,6 +13523,21 @@ fi
done 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 <windows.h>
#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. # Check for the fcntl function.
if test -n "${with_target_subdir}"; then if test -n "${with_target_subdir}"; then

View File

@ -380,6 +380,10 @@ if test "$have_loadquery" = "yes"; then
fi fi
AC_CHECK_HEADERS(windows.h) AC_CHECK_HEADERS(windows.h)
AC_CHECK_HEADERS(tlhelp32.h, [], [],
[#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif])
# Check for the fcntl function. # Check for the fcntl function.
if test -n "${with_target_subdir}"; then if test -n "${with_target_subdir}"; then

View File

@ -49,6 +49,18 @@ POSSIBILITY OF SUCH DAMAGE. */
#endif #endif
#include <windows.h> #include <windows.h>
#ifdef HAVE_TLHELP32_H
#include <tlhelp32.h>
#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 #endif
/* Coff file header. */ /* Coff file header. */
@ -592,7 +604,8 @@ coff_syminfo (struct backtrace_state *state, uintptr_t addr,
static int static int
coff_add (struct backtrace_state *state, int descriptor, coff_add (struct backtrace_state *state, int descriptor,
backtrace_error_callback error_callback, void *data, 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; struct backtrace_view fhdr_view;
off_t fhdr_off; off_t fhdr_off;
@ -870,12 +883,7 @@ coff_add (struct backtrace_state *state, int descriptor,
} }
#ifdef HAVE_WINDOWS_H #ifdef HAVE_WINDOWS_H
{ base_address = module_handle - image_base;
uintptr_t module_handle;
module_handle = (uintptr_t) GetModuleHandle (NULL);
base_address = module_handle - image_base;
}
#endif #endif
if (!backtrace_dwarf_add (state, base_address, &dwarf_sections, if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
@ -917,12 +925,61 @@ backtrace_initialize (struct backtrace_state *state,
int found_sym; int found_sym;
int found_dwarf; int found_dwarf;
fileline coff_fileline_fn; 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, 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) if (!ret)
return 0; 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 (!state->threaded)
{ {
if (found_sym) if (found_sym)