Message ID | 20230120105409.54949-2-gcc@hazardy.de |
---|---|
State | New |
Headers | show |
Series | [1/4] libbacktrace: change all pc related variables to uintptr_t | expand |
On Fri, Jan 20, 2023 at 2:56 AM Björn Schäpers <gcc@hazardy.de> wrote: > > From: Björn Schäpers <bjoern@hazardy.de> > > This is actually needed so that libstdc++'s <stacktrace> implementation > to be able to work on windows. > > Tested on x86_64-linux and i686-w64-mingw32. > > -- >8 -- > > * configure.ac: Add a check for windows.h. > * configure, config.h.in: Regenerate. > * fileline.c: Add windows_get_executable_path. > * fileline.c (fileline_initialiez): Add a pass using > windows_get_executable_path. > > +#ifdef HAVE_WINDOWS_H > + > +static char * > +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, > + void *data) > +{ > + if (GetModuleFileNameA (NULL, buf, MAX_PATH - 1) == 0) > + { > + error_callback (data, > + "could not get the filename of the current executable", > + (int) GetLastError ()); > + return NULL; > + } > + return buf; > +} Thanks, but this seems incomplete. The docs for GetModuleFileNameA say that if the pathname is too long to fit into the buffer it returns the size of the buffer and sets the error to ERROR_INSUFFICIENT_BUFFER. It seems to me that in that case we should allocate a larger buffer and try again. And, in general, it will be simpler if we always allocate the buffer, as macho_get_executable_path does. Unfortunately it appears that Windows does not provide a way to ask for the required length. On Windows it seems that MAX_PATH is not a true limit, as an extended length path may be up to 32767 bytes. So probably something like (untested) static char * windows_get_executable_path (struct backtrace_state *state, backtrace_error_callback error_callback, void *data) { uint32_t len; char *buf; len = MAX_PATH; while (1) { uint32_t got; name = (char *) backtrace_alloc (state, len, error_callback, data); if (name == NULL) return NULL; got = GetModuleFileNameA (NULL, name, len); if (got < len - 1) /* -1 because NULB is not counted */ return name; backtrace_free (state, name, len, error_callback, data); if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) return NULL; len *= 2; } } Ian
> Date: Mon, 23 Jan 2023 15:00:56 -0800 > Cc: gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > From: Ian Lance Taylor via Gcc <gcc@gcc.gnu.org> > > > +#ifdef HAVE_WINDOWS_H > > + > > +static char * > > +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, > > + void *data) > > +{ > > + if (GetModuleFileNameA (NULL, buf, MAX_PATH - 1) == 0) > > + { > > + error_callback (data, > > + "could not get the filename of the current executable", > > + (int) GetLastError ()); > > + return NULL; > > + } > > + return buf; > > +} > > Thanks, but this seems incomplete. The docs for GetModuleFileNameA > say that if the pathname is too long to fit into the buffer it returns > the size of the buffer and sets the error to > ERROR_INSUFFICIENT_BUFFER. It seems to me that in that case we should > allocate a larger buffer and try again. This is correct in general, but not in this particular case. > On Windows it seems that MAX_PATH is not > a true limit, as an extended length path may be up to 32767 bytes. The limit of 32767 characters (not bytes, AFAIK) is only applicable when using the Unicode (a.k.a. "wide") versions of the Windows Win32 APIs, see https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation Since the above code uses GetModuleFileNameA, which is an "ANSI" single-byte API, it is still subject to the MAX_PATH limitation, and MAX_PATH is defined as 260 on Windows headers.
On Tue, Jan 24, 2023 at 5:11 AM Eli Zaretskii via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > > Date: Mon, 23 Jan 2023 15:00:56 -0800 > > Cc: gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > > From: Ian Lance Taylor via Gcc <gcc@gcc.gnu.org> > > > > > +#ifdef HAVE_WINDOWS_H > > > + > > > +static char * > > > +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, > > > + void *data) > > > +{ > > > + if (GetModuleFileNameA (NULL, buf, MAX_PATH - 1) == 0) > > > + { > > > + error_callback (data, > > > + "could not get the filename of the current executable", > > > + (int) GetLastError ()); > > > + return NULL; > > > + } > > > + return buf; > > > +} > > > > Thanks, but this seems incomplete. The docs for GetModuleFileNameA > > say that if the pathname is too long to fit into the buffer it returns > > the size of the buffer and sets the error to > > ERROR_INSUFFICIENT_BUFFER. It seems to me that in that case we should > > allocate a larger buffer and try again. > > This is correct in general, but not in this particular case. > > > On Windows it seems that MAX_PATH is not > > a true limit, as an extended length path may be up to 32767 bytes. > > The limit of 32767 characters (not bytes, AFAIK) is only applicable > when using the Unicode (a.k.a. "wide") versions of the Windows Win32 > APIs, see > > https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation > > Since the above code uses GetModuleFileNameA, which is an "ANSI" > single-byte API, it is still subject to the MAX_PATH limitation, and > MAX_PATH is defined as 260 on Windows headers. Thanks. Should this code be using GetModuleFileNameW? Or would that mean that the later call to open will fail? 260 bytes does not seem like very much for a path name these days. Ian
> From: Ian Lance Taylor <iant@golang.org> > Date: Tue, 24 Jan 2023 06:35:21 -0800 > Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > > > > On Windows it seems that MAX_PATH is not > > > a true limit, as an extended length path may be up to 32767 bytes. > > > > The limit of 32767 characters (not bytes, AFAIK) is only applicable > > when using the Unicode (a.k.a. "wide") versions of the Windows Win32 > > APIs, see > > > > https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation > > > > Since the above code uses GetModuleFileNameA, which is an "ANSI" > > single-byte API, it is still subject to the MAX_PATH limitation, and > > MAX_PATH is defined as 260 on Windows headers. > > Thanks. Should this code be using GetModuleFileNameW? Or would that > mean that the later call to open will fail? We'd need to use _wopen or somesuch, and the file name will have to be a wchar_t array, not a char array, yes. So this is not very practical when file names need to be passed between functions, unless they are converted to UTF-8 (and back again before using them in Windows APIs). And note that even then, the 260-byte limit could be lifted only if the user has a new enough Windows version _and_ has opted in to the long-name feature by turning it on in the Registry. Otherwise, file names used in "wide" APIs can only break the 260-byte limit if they use the special format "\\?\D:\foo\bar", which means file names specified by user outside of the program or file names that come from other programs will need to be reformatted to this special format. > 260 bytes does not seem like very much for a path name these days. That's true. But complications with using longer file names are still a PITA on Windows, even though they are a step closer to practically possible.
On Tue, Jan 24, 2023 at 8:53 AM Eli Zaretskii via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > > From: Ian Lance Taylor <iant@golang.org> > > Date: Tue, 24 Jan 2023 06:35:21 -0800 > > Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > > > > > > On Windows it seems that MAX_PATH is not > > > > a true limit, as an extended length path may be up to 32767 bytes. > > > > > > The limit of 32767 characters (not bytes, AFAIK) is only applicable > > > when using the Unicode (a.k.a. "wide") versions of the Windows Win32 > > > APIs, see > > > > > > https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation > > > > > > Since the above code uses GetModuleFileNameA, which is an "ANSI" > > > single-byte API, it is still subject to the MAX_PATH limitation, and > > > MAX_PATH is defined as 260 on Windows headers. > > > > Thanks. Should this code be using GetModuleFileNameW? Or would that > > mean that the later call to open will fail? > > We'd need to use _wopen or somesuch, and the file name will have to be > a wchar_t array, not a char array, yes. So this is not very practical > when file names need to be passed between functions, unless they are > converted to UTF-8 (and back again before using them in Windows APIs). > > And note that even then, the 260-byte limit could be lifted only if > the user has a new enough Windows version _and_ has opted in to the > long-name feature by turning it on in the Registry. Otherwise, file > names used in "wide" APIs can only break the 260-byte limit if they > use the special format "\\?\D:\foo\bar", which means file names > specified by user outside of the program or file names that come from > other programs will need to be reformatted to this special format. > > > 260 bytes does not seem like very much for a path name these days. > > That's true. But complications with using longer file names are still > a PITA on Windows, even though they are a step closer to practically > possible. OK, thanks. I'd rather that the patch look like the appended. Can someone with a Windows system test to see what that builds and passes the tests? Thanks. Ian
> From: Ian Lance Taylor <iant@golang.org> > Date: Tue, 24 Jan 2023 09:58:10 -0800 > Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > > I'd rather that the patch look like the appended. Can someone with a > Windows system test to see what that builds and passes the tests? ENOPATCH
On Tue, Jan 24, 2023 at 10:12 AM Eli Zaretskii via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > > From: Ian Lance Taylor <iant@golang.org> > > Date: Tue, 24 Jan 2023 09:58:10 -0800 > > Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > > > > I'd rather that the patch look like the appended. Can someone with a > > Windows system test to see what that builds and passes the tests? > > ENOPATCH Gah. Ian diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index 94621c2e385..29d1ad3911a 100644 --- a/libbacktrace/config.h.in +++ b/libbacktrace/config.h.in @@ -100,6 +100,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the <windows.h> header file. */ +#undef HAVE_WINDOWS_H + /* Define if -lz is available. */ #undef HAVE_ZLIB diff --git a/libbacktrace/configure b/libbacktrace/configure index 6af2c04c81a..0a27cfb7799 100755 --- a/libbacktrace/configure +++ b/libbacktrace/configure @@ -13409,6 +13409,19 @@ $as_echo "#define HAVE_LOADQUERY 1" >>confdefs.h fi +for ac_header in windows.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINDOWS_H 1 +_ACEOF + +fi + +done + + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac index 39e6bf41e35..e3e10abd7b5 100644 --- a/libbacktrace/configure.ac +++ b/libbacktrace/configure.ac @@ -377,6 +377,8 @@ if test "$have_loadquery" = "yes"; then AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.]) fi +AC_CHECK_HEADERS(windows.h) + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c index 674bf33cdcf..e110b54ee24 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -47,6 +47,18 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <mach-o/dyld.h> #endif +#ifdef HAVE_WINDOWS_H +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include <windows.h> +#endif + #include "backtrace.h" #include "internal.h" @@ -155,6 +167,27 @@ macho_get_executable_path (struct backtrace_state *state, #endif /* !defined (HAVE_MACH_O_DYLD_H) */ +#ifdef HAVE_WINDOWS_H + +static char * +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, + void *data) +{ + size_t got; + + got = GetModuleFileNameA (NULL, buf, MAX_PATH - 1); + if (got == 0 + || (got == MAX_PATH - 1 && GetLastError () == ERROR_INSUFFICIENT_BUFFER)) + return NULL; + return buf; +} + +#else /* !defined (HAVE_WINDOWS_H) */ + +#define windows_get_executable_path(buf, error_callback, data) NULL + +#endif /* !defined (HAVE_WINDOWS_H) */ + /* Initialize the fileline information from the executable. Returns 1 on success, 0 on failure. */ @@ -168,7 +201,11 @@ fileline_initialize (struct backtrace_state *state, int called_error_callback; int descriptor; const char *filename; +#ifdef HAVE_WINDOWS_H + char buf[MAX_PATH]; +#else char buf[64]; +#endif if (!state->threaded) failed = state->fileline_initialization_failed; @@ -192,7 +229,7 @@ fileline_initialize (struct backtrace_state *state, descriptor = -1; called_error_callback = 0; - for (pass = 0; pass < 8; ++pass) + for (pass = 0; pass < 9; ++pass) { int does_not_exist; @@ -224,6 +261,9 @@ fileline_initialize (struct backtrace_state *state, case 7: filename = macho_get_executable_path (state, error_callback, data); break; + case 8: + filename = windows_get_executable_path (buf, error_callback, data); + break; default: abort (); }
Am 24.01.2023 um 17:52 schrieb Eli Zaretskii: >> From: Ian Lance Taylor <iant@golang.org> >> Date: Tue, 24 Jan 2023 06:35:21 -0800 >> Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org >> >>>> On Windows it seems that MAX_PATH is not >>>> a true limit, as an extended length path may be up to 32767 bytes. >>> >>> The limit of 32767 characters (not bytes, AFAIK) is only applicable >>> when using the Unicode (a.k.a. "wide") versions of the Windows Win32 >>> APIs, see >>> >>> https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation >>> >>> Since the above code uses GetModuleFileNameA, which is an "ANSI" >>> single-byte API, it is still subject to the MAX_PATH limitation, and >>> MAX_PATH is defined as 260 on Windows headers. >> >> Thanks. Should this code be using GetModuleFileNameW? Or would that >> mean that the later call to open will fail? > > We'd need to use _wopen or somesuch, and the file name will have to be > a wchar_t array, not a char array, yes. So this is not very practical > when file names need to be passed between functions, unless they are > converted to UTF-8 (and back again before using them in Windows APIs). > > And note that even then, the 260-byte limit could be lifted only if > the user has a new enough Windows version _and_ has opted in to the > long-name feature by turning it on in the Registry. Otherwise, file > names used in "wide" APIs can only break the 260-byte limit if they > use the special format "\\?\D:\foo\bar", which means file names > specified by user outside of the program or file names that come from > other programs will need to be reformatted to this special format. > >> 260 bytes does not seem like very much for a path name these days. > > That's true. But complications with using longer file names are still > a PITA on Windows, even though they are a step closer to practically > possible. That was basically also my reasoning for choosing the A variant instead of W.
Am 24.01.2023 um 19:32 schrieb Ian Lance Taylor: > On Tue, Jan 24, 2023 at 10:12 AM Eli Zaretskii via Gcc-patches > <gcc-patches@gcc.gnu.org> wrote: >> >>> From: Ian Lance Taylor <iant@golang.org> >>> Date: Tue, 24 Jan 2023 09:58:10 -0800 >>> Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org >>> >>> I'd rather that the patch look like the appended. Can someone with a >>> Windows system test to see what that builds and passes the tests? >> >> ENOPATCH > > Gah. > > Ian > That seems to be my original patch, right? That one I have tested (and am actually using) on x86 and x64 windows.
On Sun, Feb 5, 2023 at 1:21 AM Björn Schäpers <gcc@hazardy.de> wrote: > > Am 24.01.2023 um 19:32 schrieb Ian Lance Taylor: > > On Tue, Jan 24, 2023 at 10:12 AM Eli Zaretskii via Gcc-patches > > <gcc-patches@gcc.gnu.org> wrote: > >> > >>> From: Ian Lance Taylor <iant@golang.org> > >>> Date: Tue, 24 Jan 2023 09:58:10 -0800 > >>> Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org > >>> > >>> I'd rather that the patch look like the appended. Can someone with a > >>> Windows system test to see what that builds and passes the tests? > >> > >> ENOPATCH > > > > Gah. > > > > Ian > > > That seems to be my original patch, right? That one I have tested (and > am actually using) on x86 and x64 windows. It's very similar but I changed the windows_get_executable_path function. Ian
Hi, this is what I'm using with GCC 12 and 13 on my windows machines, rebased onto the current HEAD. Kind regards, Björn. Am 06.02.2023 um 01:22 schrieb Ian Lance Taylor: > On Sun, Feb 5, 2023 at 1:21 AM Björn Schäpers <gcc@hazardy.de> wrote: >> >> Am 24.01.2023 um 19:32 schrieb Ian Lance Taylor: >>> On Tue, Jan 24, 2023 at 10:12 AM Eli Zaretskii via Gcc-patches >>> <gcc-patches@gcc.gnu.org> wrote: >>>> >>>>> From: Ian Lance Taylor <iant@golang.org> >>>>> Date: Tue, 24 Jan 2023 09:58:10 -0800 >>>>> Cc: gcc@hazardy.de, gcc-patches@gcc.gnu.org, gcc@gcc.gnu.org >>>>> >>>>> I'd rather that the patch look like the appended. Can someone with a >>>>> Windows system test to see what that builds and passes the tests? >>>> >>>> ENOPATCH >>> >>> Gah. >>> >>> Ian >>> >> That seems to be my original patch, right? That one I have tested (and >> am actually using) on x86 and x64 windows. > > It's very similar but I changed the windows_get_executable_path function. > > Ian From e0ee58b71f726606205aa1f0168a724859162c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjoern@hazardy.de> Date: Sun, 30 Apr 2023 23:48:18 +0200 Subject: [PATCH 1/3] libbacktrace: detect executable path on windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested on x86_64-linux with GCC 12, i686-w64-mingw32 and x86_64-w64-mingw32 with GCC 12 & 13. This patch is rebased onto the current HEAD. -- >8 -- * configure.ac: Add a check for windows.h. * configure, config.h.in: Regenerate. * fileline.c: Add windows_get_executable_path. * fileline.c (fileline_initialize): Add a pass using windows_get_executable_path. Signed-off-by: Björn Schäpers <bjoern@hazardy.de> --- libbacktrace/config.h.in | 3 +++ libbacktrace/configure | 13 +++++++++++ libbacktrace/configure.ac | 2 ++ libbacktrace/fileline.c | 49 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index a4f5bddddf6..ee2616335c7 100644 --- a/libbacktrace/config.h.in +++ b/libbacktrace/config.h.in @@ -104,6 +104,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the <windows.h> header file. */ +#undef HAVE_WINDOWS_H + /* Define if -lz is available. */ #undef HAVE_ZLIB diff --git a/libbacktrace/configure b/libbacktrace/configure index 0ccc060901d..7ade966b54d 100755 --- a/libbacktrace/configure +++ b/libbacktrace/configure @@ -13509,6 +13509,19 @@ $as_echo "#define HAVE_LOADQUERY 1" >>confdefs.h fi +for ac_header in windows.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINDOWS_H 1 +_ACEOF + +fi + +done + + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac index 71cd50f8cdf..00acb42eb6d 100644 --- a/libbacktrace/configure.ac +++ b/libbacktrace/configure.ac @@ -379,6 +379,8 @@ if test "$have_loadquery" = "yes"; then AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.]) fi +AC_CHECK_HEADERS(windows.h) + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c index 0e560b44e7a..28d752e2625 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -47,6 +47,18 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <mach-o/dyld.h> #endif +#ifdef HAVE_WINDOWS_H +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include <windows.h> +#endif + #include "backtrace.h" #include "internal.h" @@ -165,6 +177,34 @@ macho_get_executable_path (struct backtrace_state *state, #endif /* !HAVE_DECL__PGMPTR */ +#ifdef HAVE_WINDOWS_H + +static char * +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, + void *data) +{ + size_t got; + int error; + + got = GetModuleFileNameA (NULL, buf, MAX_PATH - 1); + error = GetLastError (); + if (got == 0 + || (got == MAX_PATH - 1 && error == ERROR_INSUFFICIENT_BUFFER)) + { + error_callback (data, + "could not get the filename of the current executable", + error); + return NULL; + } + return buf; +} + +#else /* !defined (HAVE_WINDOWS_H) */ + +#define windows_get_executable_path(buf, error_callback, data) NULL + +#endif /* !defined (HAVE_WINDOWS_H) */ + /* Initialize the fileline information from the executable. Returns 1 on success, 0 on failure. */ @@ -178,7 +218,11 @@ fileline_initialize (struct backtrace_state *state, int called_error_callback; int descriptor; const char *filename; +#ifdef HAVE_WINDOWS_H + char buf[MAX_PATH]; +#else char buf[64]; +#endif if (!state->threaded) failed = state->fileline_initialization_failed; @@ -202,7 +246,7 @@ fileline_initialize (struct backtrace_state *state, descriptor = -1; called_error_callback = 0; - for (pass = 0; pass < 9; ++pass) + for (pass = 0; pass < 10; ++pass) { int does_not_exist; @@ -239,6 +283,9 @@ fileline_initialize (struct backtrace_state *state, case 8: filename = macho_get_executable_path (state, error_callback, data); break; + case 9: + filename = windows_get_executable_path (buf, error_callback, data); + break; default: abort (); }
On Mon, Nov 20, 2023 at 11:57 AM Björn Schäpers <gcc@hazardy.de> wrote: > > this is what I'm using with GCC 12 and 13 on my windows machines, rebased onto > the current HEAD. Thanks. Committed as follows. Ian * fileline.c: Include <windows.h> if available. (windows_get_executable_path): New static function. (fileline_initialize): Call windows_get_executable_path. * configure.ac: Checked for windows.h * configure: Regenerate. * config.h.in: Regenerate. 0ee01dfacbcc9bc05d11433a69c0a0ac13afa42f diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index a4f5bddddf6..ee2616335c7 100644 --- a/libbacktrace/config.h.in +++ b/libbacktrace/config.h.in @@ -104,6 +104,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the <windows.h> header file. */ +#undef HAVE_WINDOWS_H + /* Define if -lz is available. */ #undef HAVE_ZLIB diff --git a/libbacktrace/configure b/libbacktrace/configure index 0ccc060901d..7ade966b54d 100755 --- a/libbacktrace/configure +++ b/libbacktrace/configure @@ -13509,6 +13509,19 @@ $as_echo "#define HAVE_LOADQUERY 1" >>confdefs.h fi +for ac_header in windows.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINDOWS_H 1 +_ACEOF + +fi + +done + + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac index 71cd50f8cdf..00acb42eb6d 100644 --- a/libbacktrace/configure.ac +++ b/libbacktrace/configure.ac @@ -379,6 +379,8 @@ if test "$have_loadquery" = "yes"; then AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.]) fi +AC_CHECK_HEADERS(windows.h) + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c index 0e560b44e7a..773f3a92969 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -47,6 +47,18 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <mach-o/dyld.h> #endif +#ifdef HAVE_WINDOWS_H +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include <windows.h> +#endif + #include "backtrace.h" #include "internal.h" @@ -165,6 +177,37 @@ macho_get_executable_path (struct backtrace_state *state, #endif /* !HAVE_DECL__PGMPTR */ +#ifdef HAVE_WINDOWS_H + +#define FILENAME_BUF_SIZE (MAX_PATH) + +static char * +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, + void *data) +{ + size_t got; + int error; + + got = GetModuleFileNameA (NULL, buf, FILENAME_BUF_SIZE - 1); + error = GetLastError (); + if (got == 0 + || (got == FILENAME_BUF_SIZE - 1 && error == ERROR_INSUFFICIENT_BUFFER)) + { + error_callback (data, + "could not get the filename of the current executable", + error); + return NULL; + } + return buf; +} + +#else /* !defined (HAVE_WINDOWS_H) */ + +#define windows_get_executable_path(buf, error_callback, data) NULL +#define FILENAME_BUF_SIZE 64 + +#endif /* !defined (HAVE_WINDOWS_H) */ + /* Initialize the fileline information from the executable. Returns 1 on success, 0 on failure. */ @@ -178,7 +221,7 @@ fileline_initialize (struct backtrace_state *state, int called_error_callback; int descriptor; const char *filename; - char buf[64]; + char buf[FILENAME_BUF_SIZE]; if (!state->threaded) failed = state->fileline_initialization_failed; @@ -202,7 +245,7 @@ fileline_initialize (struct backtrace_state *state, descriptor = -1; called_error_callback = 0; - for (pass = 0; pass < 9; ++pass) + for (pass = 0; pass < 10; ++pass) { int does_not_exist; @@ -239,6 +282,9 @@ fileline_initialize (struct backtrace_state *state, case 8: filename = macho_get_executable_path (state, error_callback, data); break; + case 9: + filename = windows_get_executable_path (buf, error_callback, data); + break; default: abort (); }
diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index a21e2eaf525..355e820741b 100644 --- a/libbacktrace/config.h.in +++ b/libbacktrace/config.h.in @@ -100,6 +100,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the <windows.h> header file. */ +#undef HAVE_WINDOWS_H + /* Define if -lz is available. */ #undef HAVE_ZLIB diff --git a/libbacktrace/configure b/libbacktrace/configure index a5bd133f4e4..ef677423733 100755 --- a/libbacktrace/configure +++ b/libbacktrace/configure @@ -13403,6 +13403,19 @@ $as_echo "#define HAVE_LOADQUERY 1" >>confdefs.h fi +for ac_header in windows.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINDOWS_H 1 +_ACEOF + +fi + +done + + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac index 1daaa2f62d2..b5feb29bcdc 100644 --- a/libbacktrace/configure.ac +++ b/libbacktrace/configure.ac @@ -377,6 +377,8 @@ if test "$have_loadquery" = "yes"; then AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.]) fi +AC_CHECK_HEADERS(windows.h) + # Check for the fcntl function. if test -n "${with_target_subdir}"; then case "${host}" in diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c index a40cd498114..73c2c8e8bc9 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -47,6 +47,18 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <mach-o/dyld.h> #endif +#ifdef HAVE_WINDOWS_H +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include <windows.h> +#endif + #include "backtrace.h" #include "internal.h" @@ -155,6 +167,28 @@ macho_get_executable_path (struct backtrace_state *state, #endif /* !defined (HAVE_MACH_O_DYLD_H) */ +#ifdef HAVE_WINDOWS_H + +static char * +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, + void *data) +{ + if (GetModuleFileNameA (NULL, buf, MAX_PATH - 1) == 0) + { + error_callback (data, + "could not get the filename of the current executable", + (int) GetLastError ()); + return NULL; + } + return buf; +} + +#else /* !defined (HAVE_WINDOWS_H) */ + +#define windows_get_executable_path(buf, error_callback, data) NULL + +#endif /* !defined (HAVE_WINDOWS_H) */ + /* Initialize the fileline information from the executable. Returns 1 on success, 0 on failure. */ @@ -168,7 +202,11 @@ fileline_initialize (struct backtrace_state *state, int called_error_callback; int descriptor; const char *filename; +#ifdef HAVE_WINDOWS_H + char buf[MAX_PATH]; +#else char buf[64]; +#endif if (!state->threaded) failed = state->fileline_initialization_failed; @@ -192,7 +230,7 @@ fileline_initialize (struct backtrace_state *state, descriptor = -1; called_error_callback = 0; - for (pass = 0; pass < 8; ++pass) + for (pass = 0; pass < 9; ++pass) { int does_not_exist; @@ -224,6 +262,9 @@ fileline_initialize (struct backtrace_state *state, case 7: filename = macho_get_executable_path (state, error_callback, data); break; + case 8: + filename = windows_get_executable_path (buf, error_callback, data); + break; default: abort (); }