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.
This commit is contained in:
parent
723b097351
commit
de020255a5
3 changed files with 57 additions and 4 deletions
|
@ -7463,6 +7463,8 @@ case "$opsys" in
|
|||
|
||||
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" ;;
|
||||
|
|
33
etc/DEBUG
33
etc/DEBUG
|
@ -928,7 +928,10 @@ data that is modified only very rarely.)
|
|||
|
||||
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
|
||||
|
||||
|
@ -1080,6 +1083,34 @@ suppresses some Valgrind false alarms during Emacs garbage collection:
|
|||
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
|
||||
|
|
26
src/w32fns.c
26
src/w32fns.c
|
@ -11121,12 +11121,20 @@ my_exception_handler (EXCEPTION_POINTERS * exception_data)
|
|||
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)
|
||||
|
@ -11181,6 +11189,13 @@ emacs_abort (void)
|
|||
{
|
||||
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)
|
||||
{
|
||||
|
@ -11231,8 +11246,13 @@ emacs_abort (void)
|
|||
{
|
||||
/* 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)
|
||||
|
|
Loading…
Add table
Reference in a new issue