16 #define MAX_POSBUF 128
18 #define VM_CFP_CNT(th, cfp) \
19 ((rb_control_frame_t *)((th)->stack + (th)->stack_size) - (rb_control_frame_t *)(cfp))
24 ptrdiff_t pc = -1,
bp = -1;
25 ptrdiff_t lfp = cfp->
lfp - th->
stack;
26 ptrdiff_t dfp = cfp->
dfp - th->
stack;
27 char lfp_in_heap =
' ', dfp_in_heap =
' ';
32 const char *magic, *iseq_name =
"-", *selfstr =
"-", *biseq_name =
"-";
40 lfp = (ptrdiff_t)cfp->
lfp;
44 dfp = (ptrdiff_t)cfp->
dfp;
102 else if (cfp->
iseq != 0) {
104 iseq_name =
"<ifunc>";
124 fprintf(stderr,
"p:---- ");
130 fprintf(stderr, lfp_in_heap ==
' ' ?
"l:%06"PRIdPTRDIFF
" " :
"l:%06"PRIxPTRDIFF" ", lfp % 10000);
131 fprintf(stderr, dfp_in_heap ==
' ' ?
"d:%06"PRIdPTRDIFF
" " :
"d:%06"PRIxPTRDIFF
" ", dfp % 10000);
132 fprintf(stderr,
"%-6s", magic);
133 if (line && !nopos) {
134 fprintf(stderr,
" %s", posbuf);
137 fprintf(stderr,
" \t");
138 fprintf(stderr,
"iseq: %-24s ", iseq_name);
139 fprintf(stderr,
"self: %-24s ", selfstr);
140 fprintf(stderr,
"%-1s ", biseq_name);
142 fprintf(stderr,
"\n");
154 fprintf(stderr,
"-- stack frame ------------\n");
155 for (p = st = th->
stack; p < sp; p++) {
156 fprintf(stderr,
"%04ld (%p): %08"PRIxVALUE, (
long)(p - st), p, *p);
159 if (th->
stack <= t && t < sp) {
164 fprintf(stderr,
" <- lfp");
166 fprintf(stderr,
" <- dfp");
168 fprintf(stderr,
" <- bp");
170 fprintf(stderr,
"\n");
174 fprintf(stderr,
"-- Control frame information "
175 "-----------------------------------------------\n");
180 fprintf(stderr,
"\n");
194 fprintf(stderr,
"-- env --------------------\n");
197 fprintf(stderr,
"--\n");
198 for (i = 0; i < env->
env_size; i++) {
200 (
void *)&env->
env[i]);
201 if (&env->
env[i] == lfp)
202 fprintf(stderr,
" <- lfp");
203 if (&env->
env[i] == dfp)
204 fprintf(stderr,
" <- dfp");
205 fprintf(stderr,
"\n");
215 fprintf(stderr,
"---------------------------\n");
226 fprintf(stderr,
"-- proc -------------------\n");
227 fprintf(stderr,
"self: %s\n", selfstr);
251 int argc = 0, local_size = 0;
284 VALUE *ptr = dfp - local_size;
286 vm_stack_dump_each(th, cfp + 1);
292 for (i = 0; i <
argc; i++) {
297 for (; i < local_size - 1; i++) {
304 for (; ptr < sp; ptr++, i++) {
316 if ((th)->stack + (th)->stack_size > (
VALUE *)(cfp + 2)) {
317 vm_stack_dump_each(th, cfp + 1);
334 ptrdiff_t lfp = cfp->
lfp - th->
stack;
335 ptrdiff_t dfp = cfp->
dfp - th->
stack;
349 pc, (cfp->
sp - th->
stack), lfp, dfp, cfpi);
376 fprintf(stderr,
" (1)");
383 #
if OPT_STACK_CACHING
393 fprintf(stderr,
" (2)");
400 vm_stack_dump_each(th, th->
cfp);
401 #if OPT_STACK_CACHING
411 (
"--------------------------------------------------------------\n");
415 #ifdef COLLECT_USAGE_ANALYSIS
432 static int prev_insn = -1;
438 CONST_ID(usage_hash,
"USAGE_ANALYSIS_INSN");
439 CONST_ID(bigram_hash,
"USAGE_ANALYSIS_INSN_BIGRAM");
451 if (prev_insn != -1) {
484 CONST_ID(usage_hash,
"USAGE_ANALYSIS_INSN");
512 static const char regstrs[][5] = {
521 static const char getsetstr[][4] = {
525 static VALUE syms[
sizeof(regstrs) /
sizeof(regstrs[0])][2];
529 CONST_ID(usage_hash,
"USAGE_ANALYSIS_REGS");
534 for (i = 0; i <
sizeof(regstrs) /
sizeof(regstrs[0]); i++) {
536 for (j = 0; j < 2; j++) {
537 snfprintf(stderr, buff, 0x10,
"%d %s %-4s", i, getsetstr[j],
543 valstr = syms[reg][isset];
563 fprintf(stderr,
"Thread state dump:\n");
564 fprintf(stderr,
"pc : %p, sp : %p\n", (
void *)cfp->
pc, (
void *)cfp->
sp);
565 fprintf(stderr,
"cfp: %p, lfp: %p, dfp: %p\n", (
void *)cfp, (
void *)cfp->
lfp, (
void *)cfp->
dfp);
575 fprintf(stderr,
"-- Ruby level backtrace information "
576 "----------------------------------------\n");
580 fprintf(stderr,
"%s:%d:in unknown method\n", filename, line);
583 fprintf(stderr,
"%s:%d:in `%s'\n", filename, line,
RSTRING_PTR(method));
588 #if defined(__FreeBSD__) && defined(__OPTIMIZE__)
589 #undef HAVE_BACKTRACE
592 # include <execinfo.h>
593 #elif defined(_WIN32)
594 # include <imagehlp.h>
595 # ifndef SYMOPT_DEBUG
596 # define SYMOPT_DEBUG 0x80000000
598 # ifndef MAX_SYM_NAME
599 # define MAX_SYM_NAME 2000
607 DWORD ThCallbackStack;
608 DWORD ThCallbackBStore;
611 DWORD64 KiCallUserMode;
612 DWORD64 KeUserCallbackDispatcher;
613 DWORD64 SystemRangeStart;
614 DWORD64 KiUserExceptionDispatcher;
621 ADDRESS64 AddrReturn;
624 ADDRESS64 AddrBStore;
625 void *FuncTableEntry;
656 typedef void *PREAD_PROCESS_MEMORY_ROUTINE64;
657 typedef void *PFUNCTION_TABLE_ACCESS_ROUTINE64;
658 typedef void *PGET_MODULE_BASE_ROUTINE64;
659 typedef void *PTRANSLATE_ADDRESS_ROUTINE64;
663 dump_thread(
void *
arg)
666 BOOL (WINAPI *pSymInitialize)(HANDLE,
const char *, BOOL);
667 BOOL (WINAPI *pSymCleanup)(HANDLE);
668 BOOL (WINAPI *pStackWalk64)(
DWORD, HANDLE, HANDLE, STACKFRAME64 *,
void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
669 DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64);
670 BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *);
671 BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64,
DWORD *, IMAGEHLP_LINE64 *);
672 HANDLE (WINAPI *pOpenThread)(
DWORD, BOOL,
DWORD);
673 DWORD tid = *(DWORD *)arg;
677 dbghelp = LoadLibrary(
"dbghelp.dll");
678 if (!dbghelp)
return;
679 pSymInitialize = (BOOL (WINAPI *)(HANDLE,
const char *, BOOL))GetProcAddress(dbghelp,
"SymInitialize");
680 pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp,
"SymCleanup");
681 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");
682 pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp,
"SymGetModuleBase64");
683 pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp,
"SymFromAddr");
684 pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp,
"SymGetLineFromAddr64");
685 pOpenThread = (HANDLE (WINAPI *)(
DWORD, BOOL,
DWORD))GetProcAddress(GetModuleHandle(
"kernel32.dll"),
"OpenThread");
686 if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 &&
687 pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) {
688 SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
689 ph = GetCurrentProcess();
690 pSymInitialize(ph, NULL,
TRUE);
691 th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT,
FALSE, tid);
693 if (SuspendThread(th) != (DWORD)-1) {
695 memset(&context, 0,
sizeof(context));
696 context.ContextFlags = CONTEXT_FULL;
697 if (GetThreadContext(th, &context)) {
698 char libpath[MAX_PATH];
699 char buf[
sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
700 SYMBOL_INFO *info = (SYMBOL_INFO *)
buf;
703 memset(&frame, 0,
sizeof(frame));
704 #if defined(_M_AMD64) || defined(__x86_64__)
705 mac = IMAGE_FILE_MACHINE_AMD64;
706 frame.AddrPC.Mode = AddrModeFlat;
707 frame.AddrPC.Offset = context.Rip;
708 frame.AddrFrame.Mode = AddrModeFlat;
709 frame.AddrFrame.Offset = context.Rbp;
710 frame.AddrStack.Mode = AddrModeFlat;
711 frame.AddrStack.Offset = context.Rsp;
712 #elif defined(_M_IA64) || defined(__ia64__)
713 mac = IMAGE_FILE_MACHINE_IA64;
714 frame.AddrPC.Mode = AddrModeFlat;
715 frame.AddrPC.Offset = context.StIIP;
716 frame.AddrBStore.Mode = AddrModeFlat;
717 frame.AddrBStore.Offset = context.RsBSP;
718 frame.AddrStack.Mode = AddrModeFlat;
719 frame.AddrStack.Offset = context.IntSp;
721 mac = IMAGE_FILE_MACHINE_I386;
722 frame.AddrPC.Mode = AddrModeFlat;
723 frame.AddrPC.Offset = context.Eip;
724 frame.AddrFrame.Mode = AddrModeFlat;
725 frame.AddrFrame.Offset = context.Ebp;
726 frame.AddrStack.Mode = AddrModeFlat;
727 frame.AddrStack.Offset = context.Esp;
730 while (pStackWalk64(mac, ph, th, &frame, &context, NULL,
732 DWORD64 addr = frame.AddrPC.Offset;
733 IMAGEHLP_LINE64 line;
734 DWORD64 displacement;
737 if (addr == frame.AddrReturn.Offset || addr == 0 ||
738 frame.AddrReturn.Offset == 0)
741 memset(
buf, 0,
sizeof(
buf));
742 info->SizeOfStruct =
sizeof(SYMBOL_INFO);
743 info->MaxNameLen = MAX_SYM_NAME;
744 if (pSymFromAddr(ph, addr, &displacement, info)) {
745 if (GetModuleFileName((HANDLE)(
uintptr_t)pSymGetModuleBase64(ph, addr), libpath,
sizeof(libpath)))
746 fprintf(stderr,
"%s", libpath);
747 fprintf(stderr,
"(%s+0x%I64x)",
748 info->Name, displacement);
750 fprintf(stderr,
" [0x%p]", (
void *)(
VALUE)addr);
751 memset(&line, 0,
sizeof(line));
752 line.SizeOfStruct =
sizeof(line);
753 if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
754 fprintf(stderr,
" %s:%lu", line.FileName, line.LineNumber);
755 fprintf(stderr,
"\n");
765 FreeLibrary(dbghelp);
782 #if HAVE_BACKTRACE || defined(_WIN32)
783 fprintf(stderr,
"-- C level backtrace information "
784 "-------------------------------------------\n");
787 #if defined __MACH__ && defined __APPLE__
788 fprintf(stderr,
"\n");
789 fprintf(stderr,
" See Crash Report log file under "
790 "~/Library/Logs/CrashReporter or\n");
791 fprintf(stderr,
" /Library/Logs/CrashReporter, for "
792 "the more detail of.\n");
794 #define MAX_NATIVE_TRACE 1024
795 static void *trace[MAX_NATIVE_TRACE];
796 int n = backtrace(trace, MAX_NATIVE_TRACE);
797 char **syms = backtrace_symbols(trace, n);
801 rb_dump_backtrace_with_lines(n, trace, syms);
804 for (i=0; i<n; i++) {
805 fprintf(stderr,
"%s\n", syms[i]);
810 #elif defined(_WIN32)
811 DWORD tid = GetCurrentThreadId();
812 HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid);
813 if (th != (HANDLE)-1)
814 WaitForSingleObject(th, INFINITE);
818 fprintf(stderr,
"\n");
821 fprintf(stderr,
"-- Other runtime information "
822 "-----------------------------------------------\n\n");
827 fprintf(stderr,
"\n");
828 fprintf(stderr,
"* Loaded features:\n\n");
832 fprintf(stderr,
"\n");
836 FILE *fp = fopen(
"/proc/self/maps",
"r");
838 fprintf(stderr,
"* Process memory map:\n\n");
842 size_t rn = fread(buff, 1, 0x100, fp);
843 fwrite(buff, 1, rn, stderr);
847 fprintf(stderr,
"\n\n");