Ruby  2.1.10p492(2016-04-01revision54464)
vm_dump.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm_dump.c -
4 
5  $Author: usa $
6 
7  Copyright (C) 2004-2007 Koichi Sasada
8 
9 **********************************************************************/
10 
11 
12 #include "ruby/ruby.h"
13 #include "addr2line.h"
14 #include "vm_core.h"
15 #include "internal.h"
16 
17 /* see vm_insnhelper.h for the values */
18 #ifndef VMDEBUG
19 #define VMDEBUG 0
20 #endif
21 
22 #define MAX_POSBUF 128
23 
24 #define VM_CFP_CNT(th, cfp) \
25  ((rb_control_frame_t *)((th)->stack + (th)->stack_size) - (rb_control_frame_t *)(cfp))
26 
27 static void
29 {
30  ptrdiff_t pc = -1;
31  ptrdiff_t ep = cfp->ep - th->stack;
32  char ep_in_heap = ' ';
33  char posbuf[MAX_POSBUF+1];
34  int line = 0;
35 
36  const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-";
37  VALUE tmp;
38 
39  if (cfp->block_iseq != 0 && BUILTIN_TYPE(cfp->block_iseq) != T_NODE) {
40  biseq_name = ""; /* RSTRING(cfp->block_iseq->location.label)->ptr; */
41  }
42 
43  if (ep < 0 || (size_t)ep > th->stack_size) {
44  ep = (ptrdiff_t)cfp->ep;
45  ep_in_heap = 'p';
46  }
47 
48  switch (VM_FRAME_TYPE(cfp)) {
49  case VM_FRAME_MAGIC_TOP:
50  magic = "TOP";
51  break;
53  magic = "METHOD";
54  break;
56  magic = "CLASS";
57  break;
59  magic = "BLOCK";
60  break;
62  magic = "CFUNC";
63  break;
65  magic = "PROC";
66  break;
68  magic = "LAMBDA";
69  break;
71  magic = "IFUNC";
72  break;
74  magic = "EVAL";
75  break;
77  magic = "RESCUE";
78  break;
79  case 0:
80  magic = "------";
81  break;
82  default:
83  magic = "(none)";
84  break;
85  }
86 
87  if (0) {
88  tmp = rb_inspect(cfp->self);
89  selfstr = StringValueCStr(tmp);
90  }
91  else {
92  selfstr = "";
93  }
94 
95  if (cfp->iseq != 0) {
96  if (RUBY_VM_IFUNC_P(cfp->iseq)) {
97  iseq_name = "<ifunc>";
98  }
99  else {
100  pc = cfp->pc - cfp->iseq->iseq_encoded;
101  iseq_name = RSTRING_PTR(cfp->iseq->location.label);
102  line = rb_vm_get_sourceline(cfp);
103  if (line) {
104  snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->location.path), line);
105  }
106  }
107  }
108  else if (cfp->me) {
109  iseq_name = rb_id2name(cfp->me->def->original_id);
110  snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
111  line = -1;
112  }
113 
114  fprintf(stderr, "c:%04"PRIdPTRDIFF" ",
115  ((rb_control_frame_t *)(th->stack + th->stack_size) - cfp));
116  if (pc == -1) {
117  fprintf(stderr, "p:---- ");
118  }
119  else {
120  fprintf(stderr, "p:%04"PRIdPTRDIFF" ", pc);
121  }
122  fprintf(stderr, "s:%04"PRIdPTRDIFF" ", cfp->sp - th->stack);
123  fprintf(stderr, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000);
124  fprintf(stderr, "%-6s", magic);
125  if (line) {
126  fprintf(stderr, " %s", posbuf);
127  }
128  if (VM_FRAME_TYPE_FINISH_P(cfp)) {
129  fprintf(stderr, " [FINISH]");
130  }
131  if (0) {
132  fprintf(stderr, " \t");
133  fprintf(stderr, "iseq: %-24s ", iseq_name);
134  fprintf(stderr, "self: %-24s ", selfstr);
135  fprintf(stderr, "%-1s ", biseq_name);
136  }
137  fprintf(stderr, "\n");
138 }
139 
140 void
142 {
143 #if 0
144  VALUE *sp = cfp->sp, *ep = cfp->ep;
145  VALUE *p, *st, *t;
146 
147  fprintf(stderr, "-- stack frame ------------\n");
148  for (p = st = th->stack; p < sp; p++) {
149  fprintf(stderr, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p);
150 
151  t = (VALUE *)*p;
152  if (th->stack <= t && t < sp) {
153  fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->stack));
154  }
155 
156  if (p == ep)
157  fprintf(stderr, " <- ep");
158 
159  fprintf(stderr, "\n");
160  }
161 #endif
162 
163  fprintf(stderr, "-- Control frame information "
164  "-----------------------------------------------\n");
165  while ((void *)cfp < (void *)(th->stack + th->stack_size)) {
166  control_frame_dump(th, cfp);
167  cfp++;
168  }
169  fprintf(stderr, "\n");
170 }
171 
172 void
174 {
175  rb_thread_t *th = GET_THREAD();
177 }
178 
179 void
181 {
182  int i;
183  fprintf(stderr, "-- env --------------------\n");
184 
185  while (env) {
186  fprintf(stderr, "--\n");
187  for (i = 0; i < env->env_size; i++) {
188  fprintf(stderr, "%04d: %08"PRIxVALUE" (%p)", -env->local_size + i, env->env[i],
189  (void *)&env->env[i]);
190  if (&env->env[i] == ep)
191  fprintf(stderr, " <- ep");
192  fprintf(stderr, "\n");
193  }
194 
195  if (env->prev_envval != 0) {
196  GetEnvPtr(env->prev_envval, env);
197  }
198  else {
199  env = 0;
200  }
201  }
202  fprintf(stderr, "---------------------------\n");
203 }
204 
205 void
207 {
208  rb_env_t *env;
209  char *selfstr;
210  VALUE val = rb_inspect(proc->block.self);
211  selfstr = StringValueCStr(val);
212 
213  fprintf(stderr, "-- proc -------------------\n");
214  fprintf(stderr, "self: %s\n", selfstr);
215  GetEnvPtr(proc->envval, env);
217 }
218 
219 void
221 {
222  rb_thread_t *th;
223  GetThreadPtr(thval, th);
225 }
226 
227 #if VMDEBUG > 2
228 
229 /* copy from vm.c */
230 static VALUE *
232 {
234  VALUE *bp = prev_cfp->sp + cfp->iseq->local_size + 1;
235 
236  if (cfp->iseq->type == ISEQ_TYPE_METHOD) {
237  bp += 1;
238  }
239  return bp;
240 }
241 
242 static void
243 vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
244 {
245  int i;
246 
247  VALUE rstr;
248  VALUE *sp = cfp->sp;
249  VALUE *ep = cfp->ep;
250 
251  int argc = 0, local_size = 0;
252  const char *name;
253  rb_iseq_t *iseq = cfp->iseq;
254 
255  if (iseq == 0) {
256  if (RUBYVM_CFUNC_FRAME_P(cfp)) {
257  name = rb_id2name(cfp->me->called_id);
258  }
259  else {
260  name = "?";
261  }
262  }
263  else if (RUBY_VM_IFUNC_P(iseq)) {
264  name = "<ifunc>";
265  }
266  else {
267  argc = iseq->argc;
268  local_size = iseq->local_size;
269  name = RSTRING_PTR(iseq->location.label);
270  }
271 
272  /* stack trace header */
273 
284  {
285 
286  VALUE *ptr = ep - local_size;
287 
288  control_frame_dump(th, cfp);
289 
290  for (i = 0; i < argc; i++) {
291  rstr = rb_inspect(*ptr);
292  fprintf(stderr, " arg %2d: %8s (%p)\n", i, StringValueCStr(rstr),
293  (void *)ptr++);
294  }
295  for (; i < local_size - 1; i++) {
296  rstr = rb_inspect(*ptr);
297  fprintf(stderr, " local %2d: %8s (%p)\n", i, StringValueCStr(rstr),
298  (void *)ptr++);
299  }
300 
301  ptr = vm_base_ptr(cfp);
302  for (; ptr < sp; ptr++, i++) {
303  if (*ptr == Qundef) {
304  rstr = rb_str_new2("undef");
305  }
306  else {
307  rstr = rb_inspect(*ptr);
308  }
309  fprintf(stderr, " stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr),
310  (ptr - th->stack));
311  }
312  }
313  else if (VM_FRAME_TYPE_FINISH_P(cfp)) {
314  if ((th)->stack + (th)->stack_size > (VALUE *)(cfp + 1)) {
315  vm_stack_dump_each(th, cfp + 1);
316  }
317  else {
318  /* SDR(); */
319  }
320  }
321  else {
322  rb_bug("unsupport frame type: %08lx", VM_FRAME_TYPE(cfp));
323  }
324 }
325 #endif
326 
327 void
329 {
330  rb_control_frame_t *cfp = th->cfp;
331  ptrdiff_t pc = -1;
332  ptrdiff_t ep = cfp->ep - th->stack;
333  ptrdiff_t cfpi;
334 
335  if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
336  pc = cfp->pc - cfp->iseq->iseq_encoded;
337  }
338 
339  if (ep < 0 || (size_t)ep > th->stack_size) {
340  ep = -1;
341  }
342 
343  cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp;
344  fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
345  pc, (cfp->sp - th->stack), ep, cfpi);
346 }
347 
348 void
350 {
351  rb_thread_t *th;
352  GetThreadPtr(thval, th);
354 }
355 
356 void
358 {
359  rb_iseq_t *iseq = cfp->iseq;
360 
361  if (iseq != 0) {
362  VALUE *seq = iseq->iseq;
363  ptrdiff_t pc = _pc - iseq->iseq_encoded;
364  int i;
365 
366  for (i=0; i<(int)VM_CFP_CNT(th, cfp); i++) {
367  printf(" ");
368  }
369  printf("| ");
370  if(0)printf("[%03ld] ", (long)(cfp->sp - th->stack));
371 
372  /* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */
373  if (pc >= 0) {
374  rb_iseq_disasm_insn(0, seq, (size_t)pc, iseq, 0);
375  }
376  }
377 
378 #if VMDEBUG > 3
379  fprintf(stderr, " (1)");
381 #endif
382 }
383 
384 void
387  , VALUE reg_a, VALUE reg_b
388 #endif
389  )
390 {
391 #if VMDEBUG > 9
392  SDR2(cfp);
393 #endif
394 
395 #if VMDEBUG > 3
396  fprintf(stderr, " (2)");
398 #endif
399  /* stack_dump_raw(th, cfp); */
400 
401 #if VMDEBUG > 2
402  /* stack_dump_thobj(th); */
403  vm_stack_dump_each(th, th->cfp);
404 
405 #if OPT_STACK_CACHING
406  {
407  VALUE rstr;
408  rstr = rb_inspect(reg_a);
409  fprintf(stderr, " sc reg A: %s\n", StringValueCStr(rstr));
410  rstr = rb_inspect(reg_b);
411  fprintf(stderr, " sc reg B: %s\n", StringValueCStr(rstr));
412  }
413 #endif
414  printf
415  ("--------------------------------------------------------------\n");
416 #endif
417 }
418 
419 VALUE
421 {
422  rb_thread_t *th;
423  rb_control_frame_t *cfp;
424  GetThreadPtr(self, th);
425  cfp = th->cfp;
426 
427  fprintf(stderr, "Thread state dump:\n");
428  fprintf(stderr, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp);
429  fprintf(stderr, "cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep);
430 
431  return Qnil;
432 }
433 
434 #if defined(HAVE_BACKTRACE)
435 # if HAVE_LIBUNWIND
436 # undef backtrace
437 # define backtrace unw_backtrace
438 # elif defined(__APPLE__) && defined(__x86_64__) && defined(HAVE_LIBUNWIND_H)
439 # define UNW_LOCAL_ONLY
440 # include <libunwind.h>
441 # undef backtrace
442 int backtrace (void **trace, int size) {
443  unw_cursor_t cursor; unw_context_t uc;
444  unw_word_t ip;
445  int n = 0;
446 
447  unw_getcontext(&uc);
448  unw_init_local(&cursor, &uc);
449  while (unw_step(&cursor) > 0) {
450  unw_get_reg(&cursor, UNW_REG_IP, &ip);
451  trace[n++] = (void *)ip;
452  {
453  char buf[256];
454  unw_get_proc_name(&cursor, buf, 256, &ip);
455  if (strncmp("_sigtramp", buf, sizeof("_sigtramp")) == 0) {
456  goto darwin_sigtramp;
457  }
458  }
459  }
460  return n;
461 darwin_sigtramp:
462  /* darwin's bundled libunwind doesn't support signal trampoline */
463  {
464  ucontext_t *uctx;
465  /* get _sigtramp's ucontext_t and set values to cursor
466  * http://www.opensource.apple.com/source/Libc/Libc-825.25/i386/sys/_sigtramp.s
467  * http://www.opensource.apple.com/source/libunwind/libunwind-35.1/src/unw_getcontext.s
468  */
469  unw_get_reg(&cursor, UNW_X86_64_RBX, &ip);
470  uctx = (ucontext_t *)ip;
471  unw_set_reg(&cursor, UNW_X86_64_RAX, uctx->uc_mcontext->__ss.__rax);
472  unw_set_reg(&cursor, UNW_X86_64_RBX, uctx->uc_mcontext->__ss.__rbx);
473  unw_set_reg(&cursor, UNW_X86_64_RCX, uctx->uc_mcontext->__ss.__rcx);
474  unw_set_reg(&cursor, UNW_X86_64_RDX, uctx->uc_mcontext->__ss.__rdx);
475  unw_set_reg(&cursor, UNW_X86_64_RDI, uctx->uc_mcontext->__ss.__rdi);
476  unw_set_reg(&cursor, UNW_X86_64_RSI, uctx->uc_mcontext->__ss.__rsi);
477  unw_set_reg(&cursor, UNW_X86_64_RBP, uctx->uc_mcontext->__ss.__rbp);
478  unw_set_reg(&cursor, UNW_X86_64_RSP, 8+(uctx->uc_mcontext->__ss.__rsp));
479  unw_set_reg(&cursor, UNW_X86_64_R8, uctx->uc_mcontext->__ss.__r8);
480  unw_set_reg(&cursor, UNW_X86_64_R9, uctx->uc_mcontext->__ss.__r9);
481  unw_set_reg(&cursor, UNW_X86_64_R10, uctx->uc_mcontext->__ss.__r10);
482  unw_set_reg(&cursor, UNW_X86_64_R11, uctx->uc_mcontext->__ss.__r11);
483  unw_set_reg(&cursor, UNW_X86_64_R12, uctx->uc_mcontext->__ss.__r12);
484  unw_set_reg(&cursor, UNW_X86_64_R13, uctx->uc_mcontext->__ss.__r13);
485  unw_set_reg(&cursor, UNW_X86_64_R14, uctx->uc_mcontext->__ss.__r14);
486  unw_set_reg(&cursor, UNW_X86_64_R15, uctx->uc_mcontext->__ss.__r15);
487  ip = *(unw_word_t*)uctx->uc_mcontext->__ss.__rsp;
488  unw_set_reg(&cursor, UNW_REG_IP, ip);
489  trace[n++] = (void *)uctx->uc_mcontext->__ss.__rip;
490  trace[n++] = (void *)ip;
491  }
492  while (unw_step(&cursor) > 0) {
493  unw_get_reg(&cursor, UNW_REG_IP, &ip);
494  trace[n++] = (void *)ip;
495  }
496  return n;
497 }
498 # elif defined(BROKEN_BACKTRACE)
499 # undef HAVE_BACKTRACE
500 # define HAVE_BACKTRACE 0
501 # endif
502 #else
503 # define HAVE_BACKTRACE 0
504 #endif
505 
506 #if HAVE_BACKTRACE
507 # include <execinfo.h>
508 #elif defined(_WIN32)
509 # include <imagehlp.h>
510 # ifndef SYMOPT_DEBUG
511 # define SYMOPT_DEBUG 0x80000000
512 # endif
513 # ifndef MAX_SYM_NAME
514 # define MAX_SYM_NAME 2000
515 typedef struct {
516  DWORD64 Offset;
517  WORD Segment;
518  ADDRESS_MODE Mode;
519 } ADDRESS64;
520 typedef struct {
521  DWORD64 Thread;
522  DWORD ThCallbackStack;
523  DWORD ThCallbackBStore;
524  DWORD NextCallback;
525  DWORD FramePointer;
526  DWORD64 KiCallUserMode;
527  DWORD64 KeUserCallbackDispatcher;
528  DWORD64 SystemRangeStart;
529  DWORD64 KiUserExceptionDispatcher;
530  DWORD64 StackBase;
531  DWORD64 StackLimit;
532  DWORD64 Reserved[5];
533 } KDHELP64;
534 typedef struct {
535  ADDRESS64 AddrPC;
536  ADDRESS64 AddrReturn;
537  ADDRESS64 AddrFrame;
538  ADDRESS64 AddrStack;
539  ADDRESS64 AddrBStore;
540  void *FuncTableEntry;
541  DWORD64 Params[4];
542  BOOL Far;
543  BOOL Virtual;
544  DWORD64 Reserved[3];
545  KDHELP64 KdHelp;
546 } STACKFRAME64;
547 typedef struct {
548  ULONG SizeOfStruct;
549  ULONG TypeIndex;
550  ULONG64 Reserved[2];
551  ULONG Index;
552  ULONG Size;
553  ULONG64 ModBase;
554  ULONG Flags;
555  ULONG64 Value;
556  ULONG64 Address;
557  ULONG Register;
558  ULONG Scope;
559  ULONG Tag;
560  ULONG NameLen;
561  ULONG MaxNameLen;
562  char Name[1];
563 } SYMBOL_INFO;
564 typedef struct {
565  DWORD SizeOfStruct;
566  void *Key;
567  DWORD LineNumber;
568  char *FileName;
569  DWORD64 Address;
570 } IMAGEHLP_LINE64;
571 typedef void *PREAD_PROCESS_MEMORY_ROUTINE64;
572 typedef void *PFUNCTION_TABLE_ACCESS_ROUTINE64;
573 typedef void *PGET_MODULE_BASE_ROUTINE64;
574 typedef void *PTRANSLATE_ADDRESS_ROUTINE64;
575 # endif
576 
577 static void
578 dump_thread(void *arg)
579 {
580  HANDLE dbghelp;
581  BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL);
582  BOOL (WINAPI *pSymCleanup)(HANDLE);
583  BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
584  DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64);
585  BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *);
586  BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *);
587  HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD);
588  DWORD tid = *(DWORD *)arg;
589  HANDLE ph;
590  HANDLE th;
591 
592  dbghelp = LoadLibrary("dbghelp.dll");
593  if (!dbghelp) return;
594  pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize");
595  pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup");
596  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");
597  pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64");
598  pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr");
599  pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64");
600  pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread");
601  if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 &&
602  pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) {
603  SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
604  ph = GetCurrentProcess();
605  pSymInitialize(ph, NULL, TRUE);
606  th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid);
607  if (th) {
608  if (SuspendThread(th) != (DWORD)-1) {
609  CONTEXT context;
610  memset(&context, 0, sizeof(context));
611  context.ContextFlags = CONTEXT_FULL;
612  if (GetThreadContext(th, &context)) {
613  char libpath[MAX_PATH];
614  char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
615  SYMBOL_INFO *info = (SYMBOL_INFO *)buf;
616  DWORD mac;
617  STACKFRAME64 frame;
618  memset(&frame, 0, sizeof(frame));
619 #if defined(_M_AMD64) || defined(__x86_64__)
620  mac = IMAGE_FILE_MACHINE_AMD64;
621  frame.AddrPC.Mode = AddrModeFlat;
622  frame.AddrPC.Offset = context.Rip;
623  frame.AddrFrame.Mode = AddrModeFlat;
624  frame.AddrFrame.Offset = context.Rbp;
625  frame.AddrStack.Mode = AddrModeFlat;
626  frame.AddrStack.Offset = context.Rsp;
627 #elif defined(_M_IA64) || defined(__ia64__)
628  mac = IMAGE_FILE_MACHINE_IA64;
629  frame.AddrPC.Mode = AddrModeFlat;
630  frame.AddrPC.Offset = context.StIIP;
631  frame.AddrBStore.Mode = AddrModeFlat;
632  frame.AddrBStore.Offset = context.RsBSP;
633  frame.AddrStack.Mode = AddrModeFlat;
634  frame.AddrStack.Offset = context.IntSp;
635 #else /* i386 */
636  mac = IMAGE_FILE_MACHINE_I386;
637  frame.AddrPC.Mode = AddrModeFlat;
638  frame.AddrPC.Offset = context.Eip;
639  frame.AddrFrame.Mode = AddrModeFlat;
640  frame.AddrFrame.Offset = context.Ebp;
641  frame.AddrStack.Mode = AddrModeFlat;
642  frame.AddrStack.Offset = context.Esp;
643 #endif
644 
645  while (pStackWalk64(mac, ph, th, &frame, &context, NULL,
646  NULL, NULL, NULL)) {
647  DWORD64 addr = frame.AddrPC.Offset;
648  IMAGEHLP_LINE64 line;
649  DWORD64 displacement;
650  DWORD tmp;
651 
652  if (addr == frame.AddrReturn.Offset || addr == 0 ||
653  frame.AddrReturn.Offset == 0)
654  break;
655 
656  memset(buf, 0, sizeof(buf));
657  info->SizeOfStruct = sizeof(SYMBOL_INFO);
658  info->MaxNameLen = MAX_SYM_NAME;
659  if (pSymFromAddr(ph, addr, &displacement, info)) {
660  if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
661  fprintf(stderr, "%s", libpath);
662  fprintf(stderr, "(%s+0x%I64x)",
663  info->Name, displacement);
664  }
665  fprintf(stderr, " [0x%p]", (void *)(VALUE)addr);
666  memset(&line, 0, sizeof(line));
667  line.SizeOfStruct = sizeof(line);
668  if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
669  fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber);
670  fprintf(stderr, "\n");
671  }
672  }
673 
674  ResumeThread(th);
675  }
676  CloseHandle(th);
677  }
678  pSymCleanup(ph);
679  }
680  FreeLibrary(dbghelp);
681 }
682 #endif
683 
684 void
686 {
687 #if HAVE_BACKTRACE
688 #define MAX_NATIVE_TRACE 1024
689  static void *trace[MAX_NATIVE_TRACE];
690  int n = backtrace(trace, MAX_NATIVE_TRACE);
691  char **syms = backtrace_symbols(trace, n);
692 
693  if (syms) {
694 #ifdef USE_ELF
695  rb_dump_backtrace_with_lines(n, trace, syms);
696 #else
697  int i;
698  for (i=0; i<n; i++) {
699  fprintf(stderr, "%s\n", syms[i]);
700  }
701 #endif
702  free(syms);
703  }
704 #elif defined(_WIN32)
705  DWORD tid = GetCurrentThreadId();
706  HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid);
707  if (th != (HANDLE)-1)
708  WaitForSingleObject(th, INFINITE);
709 #endif
710 }
711 
712 void
714 {
715 #ifdef __linux__
716 # define PROC_MAPS_NAME "/proc/self/maps"
717 #endif
718 #ifdef PROC_MAPS_NAME
719  enum {other_runtime_info = 1};
720 #else
721  enum {other_runtime_info = 0};
722 #endif
723  const rb_vm_t *const vm = GET_VM();
724 
725 #if defined __APPLE__
726  fputs("-- Crash Report log information "
727  "--------------------------------------------\n"
728  " See Crash Report log file under the one of following:\n"
729  " * ~/Library/Logs/CrashReporter\n"
730  " * /Library/Logs/CrashReporter\n"
731  " * ~/Library/Logs/DiagnosticReports\n"
732  " * /Library/Logs/DiagnosticReports\n"
733  " for more details.\n"
734  "\n",
735  stderr);
736 #endif
737  if (vm) {
738  SDR();
740  fputs("\n", stderr);
741  }
742 
743 #if HAVE_BACKTRACE || defined(_WIN32)
744  fprintf(stderr, "-- C level backtrace information "
745  "-------------------------------------------\n");
747 
748 
749  fprintf(stderr, "\n");
750 #endif /* HAVE_BACKTRACE */
751 
752  if (other_runtime_info || vm) {
753  fprintf(stderr, "-- Other runtime information "
754  "-----------------------------------------------\n\n");
755  }
756  if (vm) {
757  int i;
758  VALUE name;
759  long len;
760  const int max_name_length = 1024;
761 # define LIMITED_NAME_LENGTH(s) \
762  (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len)
763 
764  name = vm->progname;
765  fprintf(stderr, "* Loaded script: %.*s\n",
767  fprintf(stderr, "\n");
768  fprintf(stderr, "* Loaded features:\n\n");
769  for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
770  name = RARRAY_AREF(vm->loaded_features, i);
771  if (RB_TYPE_P(name, T_STRING)) {
772  fprintf(stderr, " %4d %.*s\n", i,
774  }
775  else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
776  const char *const type = RB_TYPE_P(name, T_CLASS) ?
777  "class" : "module";
779  fprintf(stderr, " %4d %s:%.*s\n", i, type,
781  }
782  else {
783  VALUE klass = rb_class_name(CLASS_OF(name));
784  fprintf(stderr, " %4d #<%.*s:%p>\n", i,
785  LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
786  (void *)name);
787  }
788  }
789  fprintf(stderr, "\n");
790  }
791 
792  {
793 #ifdef PROC_MAPS_NAME
794  {
795  FILE *fp = fopen(PROC_MAPS_NAME, "r");
796  if (fp) {
797  fprintf(stderr, "* Process memory map:\n\n");
798 
799  while (!feof(fp)) {
800  char buff[0x100];
801  size_t rn = fread(buff, 1, 0x100, fp);
802  if (fwrite(buff, 1, rn, stderr) != rn)
803  break;
804  }
805 
806  fclose(fp);
807  fprintf(stderr, "\n\n");
808  }
809  }
810 #endif /* __linux__ */
811  }
812 }
rb_control_frame_t * cfp
Definition: vm_core.h:531
#define VM_FRAME_MAGIC_BLOCK
Definition: vm_core.h:760
int rb_iseq_disasm_insn(VALUE ret, VALUE *iseq, size_t pos, rb_iseq_t *iseqdat, VALUE child)
Disassemble a instruction Iseq -> Iseq inspect object.
Definition: iseq.c:1287
#define RARRAY_LEN(a)
Definition: ruby.h:878
void rb_bug(const char *fmt,...)
Definition: error.c:327
#define FALSE
Definition: nkf.h:174
#define RUBY_VM_IFUNC_P(ptr)
Definition: vm_core.h:834
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:33
#define VM_CFP_CNT(th, cfp)
Definition: vm_dump.c:24
static void control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm_dump.c:28
#define VM_FRAME_TYPE_FINISH_P(cfp)
Definition: vm_core.h:778
#define VM_FRAME_MAGIC_CFUNC
Definition: vm_core.h:763
VALUE rb_vmdebug_thread_dump_state(VALUE self)
Definition: vm_dump.c:420
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:825
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
Definition: vm_core.h:835
#define CLASS_OF(v)
Definition: ruby.h:440
#define T_MODULE
Definition: ruby.h:480
VALUE progname
Definition: vm_core.h:399
void rb_vmdebug_stack_dump_th(VALUE thval)
Definition: vm_dump.c:220
#define MAX_POSBUF
Definition: vm_dump.c:22
#define SDR2(cfp)
Definition: vm_core.h:854
#define PRIxVALUE
Definition: ruby.h:135
#define VM_FRAME_MAGIC_METHOD
Definition: vm_core.h:759
#define VM_FRAME_TYPE(cfp)
Definition: vm_core.h:772
ID called_id
Definition: method.h:101
#define VM_FRAME_MAGIC_IFUNC
Definition: vm_core.h:765
#define SDR()
Definition: vm_core.h:853
#define VM_FRAME_MAGIC_RESCUE
Definition: vm_core.h:768
#define GetEnvPtr(obj, ptr)
Definition: vm_core.h:710
VALUE envval
Definition: vm_core.h:703
VALUE * iseq
Definition: vm_core.h:225
VALUE * stack
Definition: vm_core.h:529
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1672
enum rb_iseq_struct::iseq_type type
int t(void)
Definition: conftest.c:13
VALUE rb_class_name(VALUE)
Definition: variable.c:391
#define val
rb_iseq_t * block_iseq
Definition: vm_core.h:453
IUnknown DWORD
Definition: win32ole.c:149
int argc
argument information
Definition: vm_core.h:274
#define snprintf
Definition: subst.h:6
rb_iseq_t * iseq
Definition: vm_core.h:448
int argc
Definition: ruby.c:131
#define VM_FRAME_MAGIC_CLASS
Definition: vm_core.h:761
void rb_vm_bugreport(void)
Definition: vm_dump.c:713
#define T_NODE
Definition: ruby.h:498
#define rb_str_new2
Definition: intern.h:840
#define PRIdPTRDIFF
Definition: ruby.h:161
void rb_vmdebug_debug_print_register(rb_thread_t *th)
Definition: vm_dump.c:328
#define TRUE
Definition: nkf.h:175
VALUE loaded_features
Definition: vm_core.h:376
void rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm_dump.c:141
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
const VALUE path
Definition: vm_core.h:197
#define RUBYVM_CFUNC_FRAME_P(cfp)
Definition: vm_core.h:781
#define Qnil
Definition: ruby.h:427
unsigned int uintptr_t
Definition: win32.h:103
int type
Definition: tcltklib.c:112
#define VM_FRAME_MAGIC_EVAL
Definition: vm_core.h:766
VALUE * iseq_encoded
Definition: vm_core.h:226
#define BUILTIN_TYPE(x)
Definition: ruby.h:502
unsigned long VALUE
Definition: ruby.h:88
static VALUE * vm_base_ptr(rb_control_frame_t *cfp)
rb_iseq_location_t location
Definition: vm_core.h:223
void rb_vmdebug_env_dump_raw(rb_env_t *env, VALUE *ep)
Definition: vm_dump.c:180
#define OPT_STACK_CACHING
Definition: vm_opts.h:47
#define StringValueCStr(v)
Definition: ruby.h:541
#define VM_FRAME_MAGIC_TOP
Definition: vm_core.h:762
#define VM_FRAME_MAGIC_PROC
Definition: vm_core.h:764
#define RSTRING_PTR(str)
Definition: ruby.h:845
int size
Definition: encoding.c:49
#define VM_FRAME_MAGIC_LAMBDA
Definition: vm_core.h:767
void rb_print_backtrace(void)
Definition: vm_dump.c:685
rb_block_t block
Definition: vm_core.h:701
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
rb_method_definition_t * def
Definition: method.h:100
const rb_method_entry_t * me
Definition: vm_core.h:455
void rb_vmdebug_thread_dump_regs(VALUE thval)
Definition: vm_dump.c:349
#define T_STRING
Definition: ruby.h:482
int local_size
Definition: vm_core.h:239
#define GetThreadPtr(obj, ptr)
Definition: vm_core.h:472
#define T_CLASS
Definition: ruby.h:478
void rb_vmdebug_proc_dump_raw(rb_proc_t *proc)
Definition: vm_dump.c:206
const char * name
Definition: nkf.c:208
void rb_vmdebug_stack_dump_raw_current(void)
Definition: vm_dump.c:173
const char * rb_id2name(ID id)
Definition: ripper.c:17271
size_t stack_size
Definition: vm_core.h:530
VALUE rb_inspect(VALUE)
Definition: object.c:470
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:800
void rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp, VALUE *_pc)
Definition: vm_dump.c:357
void rb_backtrace_print_as_bugreport(void)
Definition: vm_backtrace.c:766
#define feof(p)
Definition: vsnprintf.c:218
#define env
#define PRIxPTRDIFF
Definition: ruby.h:165
#define NULL
Definition: _sdbm.c:102
#define Qundef
Definition: ruby.h:428
const VALUE label
Definition: vm_core.h:200
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:929
static ULONG(STDMETHODCALLTYPE AddRef)(IDispatch __RPC_FAR *This)
Definition: win32ole.c:615
free(psz)
#define bp()
Definition: vm_debug.h:25
void rb_vmdebug_debug_print_post(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm_dump.c:385
#define LIMITED_NAME_LENGTH(s)
VALUE * ep
Definition: vm_core.h:465
#define GET_VM()
Definition: vm_core.h:922