diff options
| author | Eli Zaretskii | 2024-01-26 15:01:51 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2024-01-26 15:01:51 +0200 |
| commit | de020255a5cef4349d786fceb19481352c49557b (patch) | |
| tree | 983b2f255dbdeeb4c3c302adcf7f92ea77c6b75b /src | |
| parent | 723b0973512c0e6e9fb0f07678124347ccd44b54 (diff) | |
| download | emacs-de020255a5cef4349d786fceb19481352c49557b.tar.gz emacs-de020255a5cef4349d786fceb19481352c49557b.zip | |
Fix crash backtraces on MS-Windows, broken by ASLR
* src/w32fns.c (DEFAULT_IMAGE_BASE): Define for 64-bit and 32-bit
MinGW builds.
(emacs_abort): Correct the callstack addresses for potential
relocation of the image base due to ASLR. This makes 'addr2line'
be able to interpret emacs_backtrace.txt when ASLR is in effect,
which it is on every modern version of MS-Windows. (Bug#63365)
* configure.ac (LD_SWITCH_SYSTEM_TEMACS) [mingw32]: Add comment
about keeping the image-base values in sync with w32fns.c.
* etc/DEBUG (How to disable ASLR): New section.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32fns.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/src/w32fns.c b/src/w32fns.c index f8de45da7c9..f44460e52c0 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -11121,12 +11121,20 @@ my_exception_handler (EXCEPTION_POINTERS * exception_data) | |||
| 11121 | return prev_exception_handler (exception_data); | 11121 | return prev_exception_handler (exception_data); |
| 11122 | return EXCEPTION_EXECUTE_HANDLER; | 11122 | return EXCEPTION_EXECUTE_HANDLER; |
| 11123 | } | 11123 | } |
| 11124 | #endif | 11124 | #endif /* !CYGWIN */ |
| 11125 | 11125 | ||
| 11126 | typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, | 11126 | typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, |
| 11127 | PULONG); | 11127 | PULONG); |
| 11128 | 11128 | ||
| 11129 | #define BACKTRACE_LIMIT_MAX 62 | 11129 | #define BACKTRACE_LIMIT_MAX 62 |
| 11130 | /* The below must be kept in sync with the value of the | ||
| 11131 | -Wl,-image-base switch we use in LD_SWITCH_SYSTEM_TEMACS, see | ||
| 11132 | configure.ac. */ | ||
| 11133 | #if defined MINGW_W64 && EMACS_INT_MAX > LONG_MAX | ||
| 11134 | # define DEFAULT_IMAGE_BASE (ptrdiff_t)0x400000000 | ||
| 11135 | #else /* 32-bit MinGW build */ | ||
| 11136 | # define DEFAULT_IMAGE_BASE (ptrdiff_t)0x01000000 | ||
| 11137 | #endif | ||
| 11130 | 11138 | ||
| 11131 | static int | 11139 | static int |
| 11132 | w32_backtrace (void **buffer, int limit) | 11140 | w32_backtrace (void **buffer, int limit) |
| @@ -11181,6 +11189,13 @@ emacs_abort (void) | |||
| 11181 | { | 11189 | { |
| 11182 | void *stack[BACKTRACE_LIMIT_MAX + 1]; | 11190 | void *stack[BACKTRACE_LIMIT_MAX + 1]; |
| 11183 | int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1); | 11191 | int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1); |
| 11192 | #ifdef CYGWIN | ||
| 11193 | ptrdiff_t addr_offset = 0; | ||
| 11194 | #else /* MinGW */ | ||
| 11195 | /* The offset below is zero unless ASLR is in effect. */ | ||
| 11196 | ptrdiff_t addr_offset | ||
| 11197 | = DEFAULT_IMAGE_BASE - (ptrdiff_t)GetModuleHandle (NULL); | ||
| 11198 | #endif /* MinGW */ | ||
| 11184 | 11199 | ||
| 11185 | if (i) | 11200 | if (i) |
| 11186 | { | 11201 | { |
| @@ -11231,8 +11246,13 @@ emacs_abort (void) | |||
| 11231 | { | 11246 | { |
| 11232 | /* stack[] gives the return addresses, whereas we want | 11247 | /* stack[] gives the return addresses, whereas we want |
| 11233 | the address of the call, so decrease each address | 11248 | the address of the call, so decrease each address |
| 11234 | by approximate size of 1 CALL instruction. */ | 11249 | by approximate size of 1 CALL instruction. We add |
| 11235 | sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *)); | 11250 | ADDR_OFFSET to account for ASLR which changes the |
| 11251 | base address of the program's image in memory, | ||
| 11252 | whereas 'addr2line' needs to see addresses relative | ||
| 11253 | to the fixed base recorded in the PE header. */ | ||
| 11254 | sprintf (buf, "%p\r\n", | ||
| 11255 | (char *)stack[j] - sizeof(void *) + addr_offset); | ||
| 11236 | if (stderr_fd >= 0) | 11256 | if (stderr_fd >= 0) |
| 11237 | write (stderr_fd, buf, strlen (buf)); | 11257 | write (stderr_fd, buf, strlen (buf)); |
| 11238 | if (errfile_fd >= 0) | 11258 | if (errfile_fd >= 0) |