* 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.
(cherry picked from commit
de020255a5cef4349d786fceb19481352c49557b)
mingw32)
## Is it any better under MinGW64 to relocate emacs into higher addresses?
+ ## If the values of -image-base are modified, the corresponding
+ ## values of DEFAULT_IMAGE_BASE in w32fns.c should be kept in sync.
case "$canonical" in
x86_64-*-*) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x400000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;;
*) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x01000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;;
It is also useful to look at the corrupted object or data structure in
a fresh Emacs session and compare its contents with a session that you
-are debugging.
+are debugging. This might be somewhat harder on modern systems which
+randomize addresses of running executables (the so-called Address
+Space Layout Randomization, or ASLR, feature). If you have this
+problem, see below under "How to disable ASLR".
** Debugging the TTY (non-windowed) version
Unfortunately Valgrind suppression files tend to be system-dependent,
so you will need to keep one around that matches your system.
+** How to disable ASLR
+
+Modern systems use the so-called Address Space Layout Randomization,
+(ASLR) feature, which randomizes the base address of running programs,
+making it harder for malicious software or hackers to find the address
+of some function or variable in a running program by looking at its
+executable file. This causes the address of the same symbol to be
+different across rerunning of the same program. Sometimes, it can be
+useful to disable ASLR, for example, if you want to compare objects in
+two different Emacs sessions.
+
+On GNU/Linux, you can disable ASLR temporarily with the following
+shell command:
+
+ echo 0 > /proc/sys/kernel/randomize_va_space
+
+or by running Emacs in an environment where ASLR is temporarily
+disabled:
+
+ setarch -R emacs [args...]
+
+To disable ASLR in Emacs on MS-Windows, you will have to rebuild Emacs
+while adding '-Wl,-disable-dynamicbase' to LD_SWITCH_SYSTEM_TEMACS
+variable defined in src/Makefile. Alternatively, use some tool to
+edit the PE header of the Emacs executable file and reset the
+DYNAMIC_BASE (0x40) flag in the DllCharacteristics flags recorded by
+the PE header.
+
** How to recover buffer contents from an Emacs core dump file
The file etc/emacs-buffer.gdb defines a set of GDB commands for
return prev_exception_handler (exception_data);
return EXCEPTION_EXECUTE_HANDLER;
}
-#endif
+#endif /* !CYGWIN */
typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
PULONG);
#define BACKTRACE_LIMIT_MAX 62
+/* The below must be kept in sync with the value of the
+ -Wl,-image-base switch we use in LD_SWITCH_SYSTEM_TEMACS, see
+ configure.ac. */
+#if defined MINGW_W64 && EMACS_INT_MAX > LONG_MAX
+# define DEFAULT_IMAGE_BASE (ptrdiff_t)0x400000000
+#else /* 32-bit MinGW build */
+# define DEFAULT_IMAGE_BASE (ptrdiff_t)0x01000000
+#endif
static int
w32_backtrace (void **buffer, int limit)
{
void *stack[BACKTRACE_LIMIT_MAX + 1];
int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1);
+#ifdef CYGWIN
+ ptrdiff_t addr_offset = 0;
+#else /* MinGW */
+ /* The offset below is zero unless ASLR is in effect. */
+ ptrdiff_t addr_offset
+ = DEFAULT_IMAGE_BASE - (ptrdiff_t)GetModuleHandle (NULL);
+#endif /* MinGW */
if (i)
{
{
/* stack[] gives the return addresses, whereas we want
the address of the call, so decrease each address
- by approximate size of 1 CALL instruction. */
- sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *));
+ by approximate size of 1 CALL instruction. We add
+ ADDR_OFFSET to account for ASLR which changes the
+ base address of the program's image in memory,
+ whereas 'addr2line' needs to see addresses relative
+ to the fixed base recorded in the PE header. */
+ sprintf (buf, "%p\r\n",
+ (char *)stack[j] - sizeof(void *) + addr_offset);
if (stderr_fd >= 0)
write (stderr_fd, buf, strlen (buf));
if (errfile_fd >= 0)