Am 03.01.2024 um 00:12 schrieb Björn Schäpers:
Am 30.11.2023 um 20:53 schrieb Ian Lance Taylor:
On Fri, Jan 20, 2023 at 2:55 AM Björn Schäpers <g...@hazardy.de> wrote:
From: Björn Schäpers <bjo...@hazardy.de>
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.
Thanks, but I don't want a patch that loops using goto statements.
Please rewrite to avoid that. It may be simpler to call a function.
Also starting with a module count of 1000 seems like a lot. Do
typical Windows programs load that many modules?
Ian
Rewritten using a function.
If that is commited, could you attribute that commit to me (--author="Björn
Schäpers <bjo...@hazardy.de>")?
Thanks and kind regards,
Björn.
I noticed that under 64 bit libraries loaded with LoadLibrary were missing.
EnumProcessModules stated the correct number of modules, but did not fill the
the HMODULEs, but set them to 0. While trying to investigate I noticed if I do
the very same thing from main (in C++) I even got fewer module HMODULEs.
So I went a different way. This detects all libraries correctly, in 32 and 64
bit. The question is, if it should be a patch on top of the previous, or should
they be merged, or even only this solution and drop the EnumProcessModules variant?
Kind regards,
Björn.
From 784e01f1baf92c23c819aeb9e77010412023700f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjo...@hazardy.de>
Date: Thu, 4 Jan 2024 22:02:03 +0100
Subject: [PATCH 2/2] libbacktrace: improve getting debug information for
loaded dlls
EnumProcessModules does not always result in all modules loaded,
especially those that are loaded with LoadLibrary.
libbacktrace/Changelog:
* configure.ac: Checked for tlhelp32.h
* configure: Regenerate.
* config.h.in: Regenerate.
* pecoff.c: Include <tlhelp32.h> if available.
(backtrace_initialize): Use tlhelp32 api for a snapshot to
detect loaded modules.
---
libbacktrace/config.h.in | 3 +
libbacktrace/configure | 185 ++++++++++++++++++++------------------
libbacktrace/configure.ac | 4 +
libbacktrace/pecoff.c | 62 ++++++++++++-
4 files changed, 164 insertions(+), 90 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 <sys/types.h> header file. */
#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. */
#undef HAVE_UNISTD_H
diff --git a/libbacktrace/configure b/libbacktrace/configure
index 7ade966b54d..ca52ee3bafb 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -1866,7 +1866,7 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
+ which can conflict with char $2 (void); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
@@ -1884,7 +1884,7 @@ else
#ifdef __cplusplus
extern "C"
#endif
-char $2 ();
+char $2 (void);
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
@@ -1893,7 +1893,7 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
@@ -1932,7 +1932,7 @@ else
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof ($2))
return 0;
@@ -1945,7 +1945,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof (($2)))
return 0;
@@ -1983,7 +1983,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -2000,7 +2000,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2027,7 +2027,7 @@ else
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -2044,7 +2044,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -2079,7 +2079,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2104,12 +2104,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -2170,7 +2170,7 @@ else
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
#ifndef $as_decl_name
#ifdef __cplusplus
@@ -3073,7 +3073,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3213,7 +3213,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3277,7 +3277,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3328,7 +3328,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3369,7 +3369,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3384,7 +3384,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3400,7 +3400,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3449,9 +3449,7 @@ struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
+static char *e (char **p, int i)
{
return p[i];
}
@@ -3486,7 +3484,7 @@ int pairnames (int, char **, FILE *(*)(struct buf *,
struct stat *, int), int, i
int argc;
char **argv;
int
-main ()
+main (void)
{
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
;
@@ -3544,7 +3542,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3871,7 +3869,7 @@ else
#include <float.h>
int
-main ()
+main (void)
{
;
@@ -3941,7 +3939,7 @@ else
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
-main ()
+main (void)
{
int i;
for (i = 0; i < 256; i++)
@@ -4020,7 +4018,7 @@ else
# define __EXTENSIONS__ 1
$ac_includes_default
int
-main ()
+main (void)
{
;
@@ -5002,7 +5000,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -5043,7 +5041,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -5058,7 +5056,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -5074,7 +5072,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -5123,9 +5121,7 @@ struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
+static char *e (char **p, int i)
{
return p[i];
}
@@ -5160,7 +5156,7 @@ int pairnames (int, char **, FILE *(*)(struct buf *,
struct stat *, int), int, i
int argc;
char **argv;
int
-main ()
+main (void)
{
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
;
@@ -5218,7 +5214,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -7408,7 +7404,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -7994,7 +7990,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -9632,7 +9628,7 @@ _LT_EOF
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -9672,7 +9668,7 @@ if test -z "$aix_libpath"; then
aix_libpath="/usr/lib:/lib"; fi
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -10947,7 +10943,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -11388,9 +11384,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char dlopen ();
+char dlopen (void);
int
-main ()
+main (void)
{
return dlopen ();
;
@@ -11441,9 +11437,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char shl_load ();
+char shl_load (void);
int
-main ()
+main (void)
{
return shl_load ();
;
@@ -11484,9 +11480,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char dlopen ();
+char dlopen (void);
int
-main ()
+main (void)
{
return dlopen ();
;
@@ -11523,9 +11519,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char dlopen ();
+char dlopen (void);
int
-main ()
+main (void)
{
return dlopen ();
;
@@ -11562,9 +11558,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char dld_link ();
+char dld_link (void);
int
-main ()
+main (void)
{
return dld_link ();
;
@@ -11632,7 +11628,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11635 "configure"
+#line 11631 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11738,7 +11734,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11741 "configure"
+#line 11737 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12016,7 +12012,7 @@ else
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
-main ()
+main (void)
{
;
@@ -12062,7 +12058,7 @@ else
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
-main ()
+main (void)
{
;
@@ -12086,7 +12082,7 @@ rm -f core conftest.err conftest.$ac_objext
conftest.$ac_ext
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
-main ()
+main (void)
{
;
@@ -12131,7 +12127,7 @@ else
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
-main ()
+main (void)
{
;
@@ -12155,7 +12151,7 @@ rm -f core conftest.err conftest.$ac_objext
conftest.$ac_ext
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
-main ()
+main (void)
{
;
@@ -12228,7 +12224,7 @@ else
/* end confdefs.h. */
static int f() { return 0; }
int
-main ()
+main (void)
{
return f();
;
@@ -12259,7 +12255,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
@@ -12312,7 +12308,7 @@ case "$host" in
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if !defined(__SSE2__)
@@ -12339,7 +12335,7 @@ rm -f core conftest.err conftest.$ac_objext
conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
asm ("setssbsy");
;
@@ -12401,7 +12397,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -12490,7 +12486,7 @@ $as_echo_n "checking for _Unwind_GetIPInfo... " >&6; }
struct _Unwind_Context *context;
int ip_before_insn = 0;
int
-main ()
+main (void)
{
return _Unwind_GetIPInfo (context, &ip_before_insn);
;
@@ -12554,7 +12550,7 @@ case "$host" in
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if !defined(__SSE2__)
@@ -12580,7 +12576,7 @@ rm -f core conftest.err conftest.$ac_objext
conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
asm ("setssbsy");
;
@@ -12626,7 +12622,7 @@ if test x$may_have_cet = xyes; then
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
@@ -12763,7 +12759,7 @@ else
/* end confdefs.h. */
int i;
int
-main ()
+main (void)
{
__sync_bool_compare_and_swap (&i, i, i);
__sync_lock_test_and_set (&i, 1);
@@ -12805,7 +12801,7 @@ else
/* end confdefs.h. */
int i;
int
-main ()
+main (void)
{
__atomic_load_n (&i, __ATOMIC_ACQUIRE);
__atomic_store_n (&i, 1, __ATOMIC_RELEASE);
@@ -12843,7 +12839,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int i;
int
-main ()
+main (void)
{
int j;
;
@@ -13521,6 +13517,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 <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.
if test -n "${with_target_subdir}"; then
@@ -13625,7 +13636,7 @@ else
#include <sys/sysctl.h>
int
-main ()
+main (void)
{
int mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;
;
@@ -13659,7 +13670,7 @@ else
#include <sys/sysctl.h>
int
-main ()
+main (void)
{
int mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;
;
@@ -13715,9 +13726,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char clock_gettime ();
+char clock_gettime (void);
int
-main ()
+main (void)
{
return clock_gettime ();
;
@@ -13792,7 +13803,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int i;
int
-main ()
+main (void)
{
return 0;
;
@@ -13835,9 +13846,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char compress ();
+char compress (void);
int
-main ()
+main (void)
{
return compress ();
;
@@ -13881,7 +13892,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -13919,7 +13930,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -13962,9 +13973,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char ZSTD_compress ();
+char ZSTD_compress (void);
int
-main ()
+main (void)
{
return ZSTD_compress ();
;
@@ -14008,7 +14019,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -14338,9 +14349,9 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char lzma_auto_decoder ();
+char lzma_auto_decoder (void);
int
-main ()
+main (void)
{
return lzma_auto_decoder ();
;
@@ -14385,7 +14396,7 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index 0f61f2b28ab..b9a695ab402 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 <windows.h>
+#endif])
# Check for the fcntl function.
if test -n "${with_target_subdir}"; then
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index 64787a18411..647baa39640 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -50,6 +50,18 @@ POSSIBILITY OF SUCH DAMAGE. */
#include <windows.h>
#include <psapi.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
/* Coff file header. */
@@ -900,7 +912,7 @@ coff_add (struct backtrace_state *state, int descriptor,
return 0;
}
-#ifdef HAVE_WINDOWS_H
+#if defined(HAVE_WINDOWS_H) && !defined(HAVE_TLHELP32_H)
static void
free_modules (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data,
@@ -964,13 +976,19 @@ backtrace_initialize (struct backtrace_state *state,
uintptr_t module_handle = 0;
#ifdef HAVE_WINDOWS_H
+ fileline module_fileline_fn;
+ int module_found_sym;
+
+#ifdef HAVE_TLHELP32_H
+ HANDLE snapshot;
+#else
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;
+
+#endif
module_handle = (uintptr_t) GetModuleHandle (NULL);
#endif
@@ -981,6 +999,43 @@ backtrace_initialize (struct backtrace_state *state,
return 0;
#ifdef HAVE_WINDOWS_H
+#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);
+ }
+#else
get_all_modules (state, error_callback, data, &modules,
&module_count, &bytes_allocated_for_modules);
@@ -1009,6 +1064,7 @@ backtrace_initialize (struct backtrace_state *state,
if (modules)
free_modules (state, error_callback, data, &modules,
bytes_allocated_for_modules);
+#endif
#endif
if (!state->threaded)
--
2.42.1