mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm_dump.c (rb_vm_bugreport): add windows support.
based on patchs from Peter Weldon at [ruby-core:32551] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29352 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
86a8b820d6
commit
340997aec7
2 changed files with 194 additions and 5 deletions
|
@ -1,3 +1,8 @@
|
|||
Tue Sep 28 20:06:14 2010 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* vm_dump.c (rb_vm_bugreport): add windows support.
|
||||
based on patchs from Peter Weldon at [ruby-core:32551]
|
||||
|
||||
Mon Sep 27 23:30:34 2010 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* insns.def (opt_case_dispatch), vm_insnhelper.c:
|
||||
|
|
194
vm_dump.c
194
vm_dump.c
|
@ -584,8 +584,183 @@ bugreport_backtrace(void *arg, VALUE file, int line, VALUE method)
|
|||
}
|
||||
|
||||
#if HAVE_BACKTRACE
|
||||
#include <execinfo.h>
|
||||
# include <execinfo.h>
|
||||
#elif defined(_WIN32)
|
||||
# include <imagehlp.h>
|
||||
# ifndef SYMOPT_DEBUG
|
||||
# define SYMOPT_DEBUG 0x80000000
|
||||
# endif
|
||||
# ifndef MAX_SYM_NAME
|
||||
# define MAX_SYM_NAME 2000
|
||||
typedef struct {
|
||||
DWORD64 Offset;
|
||||
WORD Segment;
|
||||
ADDRESS_MODE Mode;
|
||||
} ADDRESS64;
|
||||
typedef struct {
|
||||
DWORD64 Thread;
|
||||
DWORD ThCallbackStack;
|
||||
DWORD ThCallbackBStore;
|
||||
DWORD NextCallback;
|
||||
DWORD FramePointer;
|
||||
DWORD64 KiCallUserMode;
|
||||
DWORD64 KeUserCallbackDispatcher;
|
||||
DWORD64 SystemRangeStart;
|
||||
DWORD64 KiUserExceptionDispatcher;
|
||||
DWORD64 StackBase;
|
||||
DWORD64 StackLimit;
|
||||
DWORD64 Reserved[5];
|
||||
} KDHELP64;
|
||||
typedef struct {
|
||||
ADDRESS64 AddrPC;
|
||||
ADDRESS64 AddrReturn;
|
||||
ADDRESS64 AddrFrame;
|
||||
ADDRESS64 AddrStack;
|
||||
ADDRESS64 AddrBStore;
|
||||
void *FuncTableEntry;
|
||||
DWORD64 Params[4];
|
||||
BOOL Far;
|
||||
BOOL Virtual;
|
||||
DWORD64 Reserved[3];
|
||||
KDHELP64 KdHelp;
|
||||
} STACKFRAME64;
|
||||
typedef struct {
|
||||
ULONG SizeOfStruct;
|
||||
ULONG TypeIndex;
|
||||
ULONG64 Reserved[2];
|
||||
ULONG Index;
|
||||
ULONG Size;
|
||||
ULONG64 ModBase;
|
||||
ULONG Flags;
|
||||
ULONG64 Value;
|
||||
ULONG64 Address;
|
||||
ULONG Register;
|
||||
ULONG Scope;
|
||||
ULONG Tag;
|
||||
ULONG NameLen;
|
||||
ULONG MaxNameLen;
|
||||
char Name[1];
|
||||
} SYMBOL_INFO;
|
||||
typedef struct {
|
||||
DWORD SizeOfStruct;
|
||||
void *Key;
|
||||
DWORD LineNumber;
|
||||
char *FileName;
|
||||
DWORD64 Address;
|
||||
} IMAGEHLP_LINE64;
|
||||
typedef void *PREAD_PROCESS_MEMORY_ROUTINE64;
|
||||
typedef void *PFUNCTION_TABLE_ACCESS_ROUTINE64;
|
||||
typedef void *PGET_MODULE_BASE_ROUTINE64;
|
||||
typedef void *PTRANSLATE_ADDRESS_ROUTINE64;
|
||||
# endif
|
||||
|
||||
static void
|
||||
dump_thread(void *arg)
|
||||
{
|
||||
HANDLE dbghelp;
|
||||
BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL);
|
||||
BOOL (WINAPI *pSymCleanup)(HANDLE);
|
||||
BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
|
||||
BOOL (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64);
|
||||
BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *);
|
||||
BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *);
|
||||
HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD);
|
||||
DWORD tid = *(DWORD *)arg;
|
||||
HANDLE ph;
|
||||
HANDLE th;
|
||||
|
||||
dbghelp = LoadLibrary("dbghelp.dll");
|
||||
if (!dbghelp) return;
|
||||
pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize");
|
||||
pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup");
|
||||
pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64");
|
||||
pSymGetModuleBase64 = (BOOL (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64");
|
||||
pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr");
|
||||
pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64");
|
||||
pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread");
|
||||
if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 &&
|
||||
pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) {
|
||||
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
|
||||
ph = GetCurrentProcess();
|
||||
pSymInitialize(ph, NULL, TRUE);
|
||||
th = pOpenThread(THREAD_ALL_ACCESS, FALSE, tid);
|
||||
if (th) {
|
||||
if (SuspendThread(th) != (DWORD)-1) {
|
||||
CONTEXT context;
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
if (GetThreadContext(th, &context)) {
|
||||
char libpath[MAX_PATH];
|
||||
char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
|
||||
SYMBOL_INFO *info = (SYMBOL_INFO *)buf;
|
||||
DWORD mac;
|
||||
STACKFRAME64 frame;
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
#if defined(_M_AMD64) || defined(__x86_64__)
|
||||
mac = IMAGE_FILE_MACHINE_AMD64;
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrPC.Offset = context.Rip;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
frame.AddrFrame.Offset = context.Rbp;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
#elif defined(_M_IA64) || defined(__ia64__)
|
||||
mac = IMAGE_FILE_MACHINE_IA64;
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrPC.Offset = context.StIIP;
|
||||
frame.AddrBStore.Mode = AddrModeFlat;
|
||||
frame.AddrBStore.Offset = context.RsBSP;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Offset = context.IntSp;
|
||||
#else /* i386 */
|
||||
mac = IMAGE_FILE_MACHINE_I386;
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrPC.Offset = context.Eip;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
frame.AddrFrame.Offset = context.Ebp;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Offset = context.Esp;
|
||||
#endif
|
||||
|
||||
while (pStackWalk64(mac, ph, th, &frame, &context, NULL,
|
||||
NULL, NULL, NULL)) {
|
||||
DWORD64 addr = frame.AddrPC.Offset;
|
||||
DWORD64 displace64;
|
||||
DWORD displace;
|
||||
IMAGEHLP_LINE64 line;
|
||||
|
||||
if (addr == frame.AddrReturn.Offset ||
|
||||
addr == 0 || frame.AddrReturn.Offset == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
info->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
info->MaxNameLen = MAX_SYM_NAME;
|
||||
if (pSymFromAddr(ph, addr, &displace64, info)) {
|
||||
if (GetModuleFileName((HANDLE)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
|
||||
fprintf(stderr, "%s", libpath);
|
||||
fprintf(stderr, "(%s)", info->Name);
|
||||
}
|
||||
|
||||
memset(&line, 0, sizeof(line));
|
||||
line.SizeOfStruct = sizeof(line);
|
||||
if (pSymGetLineFromAddr64(ph, addr, &displace, &line))
|
||||
fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber);
|
||||
fprintf(stderr, " [0x%"PRIxVALUE"]\n", addr);
|
||||
}
|
||||
}
|
||||
|
||||
ResumeThread(th);
|
||||
}
|
||||
CloseHandle(th);
|
||||
}
|
||||
pSymCleanup(ph);
|
||||
}
|
||||
FreeLibrary(dbghelp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
rb_vm_bugreport(void)
|
||||
{
|
||||
|
@ -598,23 +773,32 @@ rb_vm_bugreport(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if HAVE_BACKTRACE || defined(_WIN32)
|
||||
fprintf(stderr, "-- C level backtrace information "
|
||||
"-------------------------------------------\n");
|
||||
|
||||
{
|
||||
#if HAVE_BACKTRACE
|
||||
#define MAX_NATIVE_TRACE 1024
|
||||
{
|
||||
static void *trace[MAX_NATIVE_TRACE];
|
||||
int n = backtrace(trace, MAX_NATIVE_TRACE);
|
||||
char **syms = backtrace_symbols(trace, n);
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "-- C level backtrace information "
|
||||
"-------------------------------------------\n");
|
||||
if (syms) {
|
||||
for (i=0; i<n; i++) {
|
||||
fprintf(stderr, "%s\n", syms[i]);
|
||||
}
|
||||
free(syms);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
#elif defined(_WIN32)
|
||||
DWORD tid = GetCurrentThreadId();
|
||||
HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid);
|
||||
if (th != (HANDLE)-1)
|
||||
WaitForSingleObject(th, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue