Feature #3875 » 0001-Add-C-level-backtrace-for-MSWIN-x86.patch
include/ruby/win32.h | ||
---|---|---|
typedef uintptr_t (*asynchronous_func_t)(uintptr_t self, int argc, uintptr_t* argv);
|
||
uintptr_t rb_w32_asynchronize(asynchronous_func_t func, uintptr_t self, int argc, uintptr_t* argv, uintptr_t intrval);
|
||
/* backtrace */
|
||
void rb_w32_backtrace();
|
||
#if defined __GNUC__ && __GNUC__ >= 4
|
||
#pragma GCC visibility pop
|
||
#endif
|
vm_dump.c | ||
---|---|---|
}
|
||
fprintf(stderr, "\n");
|
||
}
|
||
#elif _WIN32
|
||
rb_w32_backtrace();
|
||
#endif
|
||
}
|
win32/win32.c | ||
---|---|---|
#ifdef __MINGW32__
|
||
#include <mswsock.h>
|
||
#endif
|
||
#if _MSC_VER && _M_IX86
|
||
#include <DbgHelp.h>
|
||
#endif
|
||
#include "ruby/win32.h"
|
||
#include "win32/dir.h"
|
||
#define isdirsep(x) ((x) == '/' || (x) == '\\')
|
||
... | ... | |
return *ip < 0;
|
||
}
|
||
#endif
|
||
#if _MSC_VER && _M_IX86
|
||
static struct DumpArgs {
|
||
DWORD thread_id;
|
||
HANDLE event;
|
||
};
|
||
static void
|
||
dump_thread(void *arg)
|
||
{
|
||
struct DumpArgs* dump_args = (struct DumpArgs*)arg;
|
||
HANDLE process = GetCurrentProcess();
|
||
HANDLE thread = OpenThread(THREAD_ALL_ACCESS, 0, dump_args->thread_id);
|
||
STACKFRAME64 stackFrame;
|
||
CONTEXT context;
|
||
BOOL bool_rc;
|
||
DWORD64 dwDisplacement;
|
||
DWORD64 dwAddress;
|
||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||
IMAGEHLP_LINE64 line;
|
||
DWORD dwLineDisplacement;
|
||
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
|
||
if (!SymInitialize(process, NULL, TRUE)) abort();
|
||
memset(&context, 0, sizeof(CONTEXT));
|
||
context.ContextFlags = CONTEXT_FULL;
|
||
bool_rc = GetThreadContext(thread, &context);
|
||
if(!bool_rc) abort();
|
||
memset(&stackFrame,0,sizeof(STACKFRAME64));
|
||
stackFrame.AddrPC.Mode = AddrModeFlat;
|
||
stackFrame.AddrPC.Offset = context.Eip;
|
||
stackFrame.AddrFrame.Mode = AddrModeFlat;
|
||
stackFrame.AddrFrame.Offset = context.Ebp;
|
||
stackFrame.AddrStack.Mode = AddrModeFlat;
|
||
stackFrame.AddrStack.Offset = context.Esp;
|
||
fprintf(stderr, "-- C level backtrace information "
|
||
"-------------------------------------------\n");
|
||
while(1)
|
||
{
|
||
bool_rc = StackWalk64(
|
||
IMAGE_FILE_MACHINE_I386,
|
||
process,
|
||
thread,
|
||
&stackFrame,
|
||
(PVOID)&context,
|
||
NULL,
|
||
SymFunctionTableAccess64,
|
||
SymGetModuleBase64,
|
||
NULL);
|
||
if(!bool_rc) break;
|
||
dwDisplacement = 0;
|
||
dwAddress = stackFrame.AddrPC.Offset;
|
||
memset(buffer, 0, sizeof(buffer));
|
||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||
if (SymFromAddr(process, dwAddress, &dwDisplacement, pSymbol))
|
||
{
|
||
fprintf(stderr, "(%s)", pSymbol->Name);
|
||
}
|
||
memset(&line, 0, sizeof(IMAGEHLP_LINE64));
|
||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||
if (SymGetLineFromAddr64(process, dwAddress, &dwLineDisplacement, &line))
|
||
{
|
||
fprintf(stderr, "(%s:%lu)", line.FileName, line.LineNumber);
|
||
}
|
||
fprintf(stderr, " [0x%08I64x]\n", dwAddress);
|
||
}
|
||
fprintf(stderr, "\n");
|
||
if (!CloseHandle(thread)) abort();
|
||
if (!SymCleanup(process)) abort();
|
||
if (!SetEvent(dump_args->event)) abort();
|
||
}
|
||
void
|
||
rb_w32_backtrace() {
|
||
struct DumpArgs dump_args;
|
||
dump_args.thread_id = GetCurrentThreadId();
|
||
dump_args.event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
if(!dump_args.event) abort();
|
||
_beginthread(dump_thread,0,&dump_args);
|
||
if (WaitForSingleObject(dump_args.event, INFINITE) != WAIT_OBJECT_0) abort();
|
||
}
|
||
#elif
|
||
void
|
||
rb_w32_backtrace() {
|
||
}
|
||
#endif
|
||
-
|