Update ebacktrace to avoid crashes and improve the quality of the diagnostic output.

git-svn-id: https://svn.eduke32.com/eduke32@4503 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2014-06-13 09:03:06 +00:00
parent a03f9bce40
commit e647b6a42f
3 changed files with 94 additions and 32 deletions

View file

@ -43,6 +43,10 @@
# define PACKAGE_VERSION 1 # define PACKAGE_VERSION 1
#endif #endif
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(_WIN64)
# define EBACKTRACE64
#endif
#include <bfd.h> #include <bfd.h>
#include <psapi.h> #include <psapi.h>
#include <stdlib.h> #include <stdlib.h>
@ -58,6 +62,9 @@
#include <stdint.h> #include <stdint.h>
#ifndef MS_VC_EXCEPTION
# define MS_VC_EXCEPTION 1080890248
#endif
#if defined __GNUC__ || defined __clang__ #if defined __GNUC__ || defined __clang__
# define ATTRIBUTE(attrlist) __attribute__(attrlist) # define ATTRIBUTE(attrlist) __attribute__(attrlist)
@ -180,6 +187,7 @@ init_bfd_ctx(struct bfd_ctx *bc, const char * procname, struct output_buffer *ob
if (!(r1 && r2 && r3)) { if (!(r1 && r2 && r3)) {
bfd_close(b); bfd_close(b);
if (!(r1 && r2))
output_print(ob,"Failed to init bfd from (%s): %d %d %d\n", procname, r1, r2, r3); output_print(ob,"Failed to init bfd from (%s): %d %d %d\n", procname, r1, r2, r3);
return 1; return 1;
} }
@ -238,6 +246,7 @@ release_set(struct bfd_set *set)
{ {
while(set) { while(set) {
struct bfd_set * temp = set->next; struct bfd_set * temp = set->next;
if (set->name)
free(set->name); free(set->name);
close_bfd_ctx(set->bc); close_bfd_ctx(set->bc);
free(set); free(set);
@ -247,7 +256,7 @@ release_set(struct bfd_set *set)
static char procname[MAX_PATH]; static char procname[MAX_PATH];
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) #ifdef EBACKTRACE64
# define MachineType IMAGE_FILE_MACHINE_AMD64 # define MachineType IMAGE_FILE_MACHINE_AMD64
# define MAYBE64(x) x ## 64 # define MAYBE64(x) x ## 64
#else #else
@ -268,7 +277,7 @@ _backtrace(struct output_buffer *ob, struct bfd_set *set, int depth , LPCONTEXT
memset(&frame,0,sizeof(frame)); memset(&frame,0,sizeof(frame));
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) #ifdef EBACKTRACE64
frame.AddrPC.Offset = context->Rip; frame.AddrPC.Offset = context->Rip;
frame.AddrStack.Offset = context->Rsp; frame.AddrStack.Offset = context->Rsp;
frame.AddrFrame.Offset = context->Rbp; frame.AddrFrame.Offset = context->Rbp;
@ -330,23 +339,34 @@ _backtrace(struct output_buffer *ob, struct bfd_set *set, int depth , LPCONTEXT
file = "[unknown file]"; file = "[unknown file]";
} }
} }
if (func == NULL) {
output_print(ob,"0x%x : %s : %s \n", output_print(ob,"0x%p : %s : %s", frame.AddrPC.Offset, module_name, file);
frame.AddrPC.Offset, if (func != NULL)
module_name, output_print(ob, " (%d) : in function (%s)", line, func);
file); output_print(ob, "\n");
}
else {
output_print(ob,"0x%x : %s : %s (%d) : in function (%s) \n",
frame.AddrPC.Offset,
module_name,
file,
line,
func);
} }
} }
static LPTSTR FormatErrorMessage(DWORD dwMessageId)
{
LPTSTR lpBuffer = NULL;
// from http://stackoverflow.com/a/455533
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwMessageId,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
(LPTSTR)&lpBuffer,
0,
NULL);
return lpBuffer; // must be LocalFree()'d by caller
} }
static char * g_output = NULL; static char * g_output = NULL;
static PVOID g_prev = NULL; static PVOID g_prev = NULL;
@ -355,12 +375,53 @@ exception_filter(LPEXCEPTION_POINTERS info)
{ {
struct output_buffer ob; struct output_buffer ob;
int logfd, written; int logfd, written;
output_init(&ob, g_output, BUFFER_MAX); PEXCEPTION_RECORD exception;
BOOL initialized = FALSE;
if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) { for (exception = info->ExceptionRecord; exception != NULL; exception = exception->ExceptionRecord)
output_print(&ob,"Failed to init symbol context\n"); {
#if 0
if (exception->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
continuable = FALSE;
#endif
switch (exception->ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
case DBG_CONTROL_C:
case MS_VC_EXCEPTION:
break;
default:
if (!initialized)
{
output_init(&ob, g_output, BUFFER_MAX);
initialized = TRUE;
} }
else { output_print(&ob, "Caught exception 0x%08X at 0x%p\n", exception->ExceptionCode, exception->ExceptionAddress);
break;
}
}
if (!initialized)
return EXCEPTION_CONTINUE_SEARCH; // EXCEPTION_CONTINUE_EXECUTION
{
DWORD error = 0;
BOOL SymInitialized = SymInitialize(GetCurrentProcess(), NULL, TRUE);
if (!SymInitialized)
{
LPTSTR errorText;
error = GetLastError();
errorText = FormatErrorMessage(error);
output_print(&ob, "SymInitialize() failed with error %d: %s\n", error, errorText);
LocalFree(errorText);
}
if (SymInitialized || error == 87)
{
struct bfd_set *set = calloc(1,sizeof(*set)); struct bfd_set *set = calloc(1,sizeof(*set));
bfd_init(); bfd_init();
_backtrace(&ob , set , 128 , info->ContextRecord); _backtrace(&ob , set , 128 , info->ContextRecord);
@ -368,6 +429,7 @@ exception_filter(LPEXCEPTION_POINTERS info)
SymCleanup(GetCurrentProcess()); SymCleanup(GetCurrentProcess());
} }
}
logfd = open(CRASH_LOG_FILE, O_APPEND | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); logfd = open(CRASH_LOG_FILE, O_APPEND | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
@ -393,9 +455,9 @@ exception_filter(LPEXCEPTION_POINTERS info)
//fputs(g_output, stderr); //fputs(g_output, stderr);
exit(1); exit(0xBAC);
return 0; return EXCEPTION_CONTINUE_SEARCH;
} }
static void static void