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>
|
Mon Sep 27 23:30:34 2010 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* insns.def (opt_case_dispatch), vm_insnhelper.c:
|
* 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
|
#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
|
#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
|
void
|
||||||
rb_vm_bugreport(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
|
#if HAVE_BACKTRACE
|
||||||
#define MAX_NATIVE_TRACE 1024
|
#define MAX_NATIVE_TRACE 1024
|
||||||
{
|
|
||||||
static void *trace[MAX_NATIVE_TRACE];
|
static void *trace[MAX_NATIVE_TRACE];
|
||||||
int n = backtrace(trace, MAX_NATIVE_TRACE);
|
int n = backtrace(trace, MAX_NATIVE_TRACE);
|
||||||
char **syms = backtrace_symbols(trace, n);
|
char **syms = backtrace_symbols(trace, n);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stderr, "-- C level backtrace information "
|
|
||||||
"-------------------------------------------\n");
|
|
||||||
if (syms) {
|
if (syms) {
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
fprintf(stderr, "%s\n", syms[i]);
|
fprintf(stderr, "%s\n", syms[i]);
|
||||||
}
|
}
|
||||||
free(syms);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue