aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2024-01-26 15:01:51 +0200
committerEli Zaretskii2024-01-26 15:01:51 +0200
commitde020255a5cef4349d786fceb19481352c49557b (patch)
tree983b2f255dbdeeb4c3c302adcf7f92ea77c6b75b
parent723b0973512c0e6e9fb0f07678124347ccd44b54 (diff)
downloademacs-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.
-rw-r--r--configure.ac2
-rw-r--r--etc/DEBUG33
-rw-r--r--src/w32fns.c26
3 files changed, 57 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 55f742ba8ef..fa8b04ec685 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7463,6 +7463,8 @@ case "$opsys" in
7463 7463
7464 mingw32) 7464 mingw32)
7465 ## Is it any better under MinGW64 to relocate emacs into higher addresses? 7465 ## Is it any better under MinGW64 to relocate emacs into higher addresses?
7466 ## If the values of -image-base are modified, the corresponding
7467 ## values of DEFAULT_IMAGE_BASE in w32fns.c should be kept in sync.
7466 case "$canonical" in 7468 case "$canonical" in
7467 x86_64-*-*) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x400000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;; 7469 x86_64-*-*) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x400000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;;
7468 *) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x01000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;; 7470 *) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x01000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;;
diff --git a/etc/DEBUG b/etc/DEBUG
index 1680aab4385..6c7f4040b8d 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -928,7 +928,10 @@ data that is modified only very rarely.)
928 928
929It is also useful to look at the corrupted object or data structure in 929It is also useful to look at the corrupted object or data structure in
930a fresh Emacs session and compare its contents with a session that you 930a fresh Emacs session and compare its contents with a session that you
931are debugging. 931are debugging. This might be somewhat harder on modern systems which
932randomize addresses of running executables (the so-called Address
933Space Layout Randomization, or ASLR, feature). If you have this
934problem, see below under "How to disable ASLR".
932 935
933** Debugging the TTY (non-windowed) version 936** Debugging the TTY (non-windowed) version
934 937
@@ -1080,6 +1083,34 @@ suppresses some Valgrind false alarms during Emacs garbage collection:
1080Unfortunately Valgrind suppression files tend to be system-dependent, 1083Unfortunately Valgrind suppression files tend to be system-dependent,
1081so you will need to keep one around that matches your system. 1084so you will need to keep one around that matches your system.
1082 1085
1086** How to disable ASLR
1087
1088Modern systems use the so-called Address Space Layout Randomization,
1089(ASLR) feature, which randomizes the base address of running programs,
1090making it harder for malicious software or hackers to find the address
1091of some function or variable in a running program by looking at its
1092executable file. This causes the address of the same symbol to be
1093different across rerunning of the same program. Sometimes, it can be
1094useful to disable ASLR, for example, if you want to compare objects in
1095two different Emacs sessions.
1096
1097On GNU/Linux, you can disable ASLR temporarily with the following
1098shell command:
1099
1100 echo 0 > /proc/sys/kernel/randomize_va_space
1101
1102or by running Emacs in an environment where ASLR is temporarily
1103disabled:
1104
1105 setarch -R emacs [args...]
1106
1107To disable ASLR in Emacs on MS-Windows, you will have to rebuild Emacs
1108while adding '-Wl,-disable-dynamicbase' to LD_SWITCH_SYSTEM_TEMACS
1109variable defined in src/Makefile. Alternatively, use some tool to
1110edit the PE header of the Emacs executable file and reset the
1111DYNAMIC_BASE (0x40) flag in the DllCharacteristics flags recorded by
1112the PE header.
1113
1083** How to recover buffer contents from an Emacs core dump file 1114** How to recover buffer contents from an Emacs core dump file
1084 1115
1085The file etc/emacs-buffer.gdb defines a set of GDB commands for 1116The file etc/emacs-buffer.gdb defines a set of GDB commands for
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
11126typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, 11126typedef 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
11131static int 11139static int
11132w32_backtrace (void **buffer, int limit) 11140w32_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)