summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorРуслан Ижбулатов <lrn1986@gmail.com>2021-04-06 11:03:45 +0000
committerРуслан Ижбулатов <lrn1986@gmail.com>2021-06-08 08:38:59 +0000
commit6d9c3e3226c8953c90bb72befe6b5d4845e14c98 (patch)
treed9d25d23cb0dc3033462997d9e72de034a73f297
parent891e3a0bba8d67c64e247e57b00c71b97fa16197 (diff)
downloadglib-6d9c3e3226c8953c90bb72befe6b5d4845e14c98.tar.gz
W32: Remove allocations from the crash handler
Use OutputDebugStringA() instead of fprintf. The goal for this code is to inform the person running the debugger about the exception that caused the debugger to be attached. This is useful for debugging with gdb, because gdb does not catch Windows exception information (it just displays "Segmentation fault"). OutputDebugStringA() ensures that the output goes to the debugger, and the (ab)use of strcpy() with a stack-allocated buffer ensures that we do not allocate anything while the crash handler is running, nor to we call CRT functions that can be reasinably expected to allocate anything.
-rw-r--r--glib/gwin32.c122
1 files changed, 84 insertions, 38 deletions
diff --git a/glib/gwin32.c b/glib/gwin32.c
index 657b18e3e..8d29f376a 100644
--- a/glib/gwin32.c
+++ b/glib/gwin32.c
@@ -1049,6 +1049,24 @@ static DWORD debugger_spawn_flags = 0;
#include "gwin32-private.c"
+static char *
+copy_chars (char *buffer,
+ gsize *buffer_size,
+ const char *to_copy)
+{
+ gsize copy_count = strlen (to_copy);
+ if (copy_count <= *buffer_size)
+ memset (buffer, 0x20, copy_count);
+ else
+ memset (buffer, 0x20, *buffer_size);
+ strncpy_s (buffer, *buffer_size, to_copy, copy_count);
+ if (*buffer_size >= copy_count)
+ *buffer_size -= copy_count;
+ else
+ *buffer_size = 0;
+ return &buffer[copy_count];
+}
+
/* Handles exceptions (useful for debugging).
* Issues a DebugBreak() call if the process is being debugged (not really
* useful - if the process is being debugged, this handler won't be invoked
@@ -1092,10 +1110,17 @@ g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo)
gsize i;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
+#define ITOA_BUFFER_SIZE 100
+ char itoa_buffer[ITOA_BUFFER_SIZE];
+#define DEBUG_STRING_SIZE 1024
+ gsize dbgs = DEBUG_STRING_SIZE;
+ char debug_string[DEBUG_STRING_SIZE];
+ char *dbgp;
if (ExceptionInfo == NULL ||
ExceptionInfo->ExceptionRecord == NULL ||
- IsDebuggerPresent ())
+ IsDebuggerPresent () ||
+ debugger[0] == 0)
return EXCEPTION_CONTINUE_SEARCH;
er = ExceptionInfo->ExceptionRecord;
@@ -1117,43 +1142,6 @@ g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo)
break;
}
- fprintf_s (stderr,
- "Exception code=0x%lx flags=0x%lx at 0x%p",
- er->ExceptionCode,
- er->ExceptionFlags,
- er->ExceptionAddress);
-
- switch (er->ExceptionCode)
- {
- case EXCEPTION_ACCESS_VIOLATION:
- fprintf_s (stderr,
- ". Access violation - attempting to %s at address 0x%p\n",
- er->ExceptionInformation[0] == 0 ? "read data" :
- er->ExceptionInformation[0] == 1 ? "write data" :
- er->ExceptionInformation[0] == 8 ? "execute data" :
- "do something bad",
- (void *) er->ExceptionInformation[1]);
- break;
- case EXCEPTION_IN_PAGE_ERROR:
- fprintf_s (stderr,
- ". Page access violation - attempting to %s at address 0x%p with status %Ix\n",
- er->ExceptionInformation[0] == 0 ? "read from an inaccessible page" :
- er->ExceptionInformation[0] == 1 ? "write to an inaccessible page" :
- er->ExceptionInformation[0] == 8 ? "execute data in page" :
- "do something bad with a page",
- (void *) er->ExceptionInformation[1],
- er->ExceptionInformation[2]);
- break;
- default:
- fprintf_s (stderr, "\n");
- break;
- }
-
- fflush (stderr);
-
- if (debugger[0] == 0)
- return EXCEPTION_CONTINUE_SEARCH;
-
memset (&si, 0, sizeof (si));
memset (&pi, 0, sizeof (pi));
si.cb = sizeof (si);
@@ -1170,6 +1158,64 @@ g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo)
* event signalling.
*/
WaitForSingleObject (debugger_wakeup_event, 60000);
+
+ dbgp = &debug_string[0];
+
+ dbgp = copy_chars (dbgp, &dbgs, "Exception code=0x");
+ itoa_buffer[0] = 0;
+ _ui64toa_s (er->ExceptionCode, itoa_buffer, ITOA_BUFFER_SIZE, 16);
+ dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
+ dbgp = copy_chars (dbgp, &dbgs, " flags=0x");
+ itoa_buffer[0] = 0;
+ _ui64toa_s (er->ExceptionFlags, itoa_buffer, ITOA_BUFFER_SIZE, 16);
+ dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
+ dbgp = copy_chars (dbgp, &dbgs, " at 0x");
+ itoa_buffer[0] = 0;
+ _ui64toa_s ((guintptr) er->ExceptionAddress, itoa_buffer, ITOA_BUFFER_SIZE, 16);
+ dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
+
+ switch (er->ExceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ dbgp = copy_chars (dbgp, &dbgs, ". Access violation - attempting to ");
+ if (er->ExceptionInformation[0] == 0)
+ dbgp = copy_chars (dbgp, &dbgs, "read data");
+ else if (er->ExceptionInformation[0] == 1)
+ dbgp = copy_chars (dbgp, &dbgs, "write data");
+ else if (er->ExceptionInformation[0] == 8)
+ dbgp = copy_chars (dbgp, &dbgs, "execute data");
+ else
+ dbgp = copy_chars (dbgp, &dbgs, "do something bad");
+ dbgp = copy_chars (dbgp, &dbgs, " at address 0x");
+ itoa_buffer[0] = 0;
+ _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16);
+ dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
+ break;
+ case EXCEPTION_IN_PAGE_ERROR:
+ dbgp = copy_chars (dbgp, &dbgs, ". Page access violation - attempting to ");
+ if (er->ExceptionInformation[0] == 0)
+ dbgp = copy_chars (dbgp, &dbgs, "read from an inaccessible page");
+ else if (er->ExceptionInformation[0] == 1)
+ dbgp = copy_chars (dbgp, &dbgs, "write to an inaccessible page");
+ else if (er->ExceptionInformation[0] == 8)
+ dbgp = copy_chars (dbgp, &dbgs, "execute data in page");
+ else
+ dbgp = copy_chars (dbgp, &dbgs, "do something bad with a page");
+ dbgp = copy_chars (dbgp, &dbgs, " at address 0x");
+ itoa_buffer[0] = 0;
+ _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16);
+ dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
+ dbgp = copy_chars (dbgp, &dbgs, " with status ");
+ itoa_buffer[0] = 0;
+ _ui64toa_s (er->ExceptionInformation[2], itoa_buffer, ITOA_BUFFER_SIZE, 16);
+ dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
+ break;
+ default:
+ break;
+ }
+
+ dbgp = copy_chars (dbgp, &dbgs, "\n");
+ OutputDebugStringA (debug_string);
}
/* Now the debugger is present, and we can try