Ruby  2.5.0dev(2017-10-22revision60238)
vm_dump.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm_dump.c -
4 
5  $Author$
6 
7  Copyright (C) 2004-2007 Koichi Sasada
8 
9 **********************************************************************/
10 
11 
12 #include "internal.h"
13 #include "addr2line.h"
14 #include "vm_core.h"
15 #include "iseq.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)->ec.vm_stack + (th)->ec.vm_stack_size) - \
26  (rb_control_frame_t *)(cfp))
27 
28 static void
29 control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
30 {
31  ptrdiff_t pc = -1;
32  ptrdiff_t ep = cfp->ep - th->ec.vm_stack;
33  char ep_in_heap = ' ';
34  char posbuf[MAX_POSBUF+1];
35  int line = 0;
36 
37  const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-";
38  VALUE tmp;
39 
41 
42  if (ep < 0 || (size_t)ep > th->ec.vm_stack_size) {
43  ep = (ptrdiff_t)cfp->ep;
44  ep_in_heap = 'p';
45  }
46 
47  switch (VM_FRAME_TYPE(cfp)) {
48  case VM_FRAME_MAGIC_TOP:
49  magic = "TOP";
50  break;
52  magic = "METHOD";
53  break;
55  magic = "CLASS";
56  break;
58  magic = "BLOCK";
59  break;
61  magic = "CFUNC";
62  break;
64  magic = "IFUNC";
65  break;
67  magic = "EVAL";
68  break;
70  magic = "RESCUE";
71  break;
72  case 0:
73  magic = "------";
74  break;
75  default:
76  magic = "(none)";
77  break;
78  }
79 
80  if (0) {
81  tmp = rb_inspect(cfp->self);
82  selfstr = StringValueCStr(tmp);
83  }
84  else {
85  selfstr = "";
86  }
87 
88  if (cfp->iseq != 0) {
89 #define RUBY_VM_IFUNC_P(ptr) imemo_type_p((VALUE)ptr, imemo_ifunc)
90  if (RUBY_VM_IFUNC_P(cfp->iseq)) {
91  iseq_name = "<ifunc>";
92  }
93  else if (SYMBOL_P(cfp->iseq)) {
94  tmp = rb_sym2str((VALUE)cfp->iseq);
95  iseq_name = RSTRING_PTR(tmp);
96  snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
97  line = -1;
98  }
99  else {
100  pc = cfp->pc - cfp->iseq->body->iseq_encoded;
101  iseq_name = RSTRING_PTR(cfp->iseq->body->location.label);
102  line = rb_vm_get_sourceline(cfp);
103  if (line) {
104  snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(rb_iseq_path(cfp->iseq)), line);
105  }
106  }
107  }
108  else if ((me = rb_vm_frame_method_entry(cfp)) != NULL) {
109  iseq_name = rb_id2name(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->ec.vm_stack + th->ec.vm_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->ec.vm_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_FINISHED_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->ec.vm_stack; p < sp; p++) {
149  fprintf(stderr, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p);
150 
151  t = (VALUE *)*p;
152  if (th->ec.vm_stack <= t && t < sp) {
153  fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->ec.vm_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->ec.vm_stack + th->ec.vm_stack_size)) {
166  control_frame_dump(th, cfp);
167  cfp++;
168  }
169  fprintf(stderr, "\n");
170 }
171 
172 void
174 {
177 }
178 
179 void
181 {
182  unsigned 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)", i, env->env[i], (void *)&env->env[i]);
189  if (&env->env[i] == ep) fprintf(stderr, " <- ep");
190  fprintf(stderr, "\n");
191  }
192 
193  env = rb_vm_env_prev_env(env);
194  }
195  fprintf(stderr, "---------------------------\n");
196 }
197 
198 void
200 {
201  const rb_env_t *env;
202  char *selfstr;
203  VALUE val = rb_inspect(vm_block_self(&proc->block));
204  selfstr = StringValueCStr(val);
205 
206  fprintf(stderr, "-- proc -------------------\n");
207  fprintf(stderr, "self: %s\n", selfstr);
208  env = VM_ENV_ENVVAL_PTR(vm_block_ep(&proc->block));
209  rb_vmdebug_env_dump_raw(env, vm_block_ep(&proc->block));
210 }
211 
212 void
214 {
215  rb_thread_t *target_th = rb_thread_ptr(thval);
216  rb_vmdebug_stack_dump_raw(target_th, target_th->ec.cfp);
217 }
218 
219 #if VMDEBUG > 2
220 
221 /* copy from vm.c */
222 static const VALUE *
223 vm_base_ptr(rb_control_frame_t *cfp)
224 {
226  const VALUE *bp = prev_cfp->sp + cfp->iseq->body->local_table_size + VM_ENV_DATA_SIZE;
227 
228  if (cfp->iseq->body->type == ISEQ_TYPE_METHOD) {
229  bp += 1;
230  }
231  return bp;
232 }
233 
234 static void
235 vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
236 {
237  int i, argc = 0, local_table_size = 0;
238  VALUE rstr;
239  VALUE *sp = cfp->sp;
240  const VALUE *ep = cfp->ep;
241 
242  if (VM_FRAME_RUBYFRAME_P(cfp)) {
243  const rb_iseq_t *iseq = cfp->iseq;
244  argc = iseq->body->param.lead_num;
245  local_table_size = iseq->body->local_table_size;
246  }
247 
248  /* stack trace header */
249 
250  if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_METHOD||
251  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_TOP ||
252  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_BLOCK ||
253  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CLASS ||
254  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC ||
255  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC ||
256  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL ||
257  VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_RESCUE)
258  {
259  const VALUE *ptr = ep - local_table_size;
260 
261  control_frame_dump(th, cfp);
262 
263  for (i = 0; i < argc; i++) {
264  rstr = rb_inspect(*ptr);
265  fprintf(stderr, " arg %2d: %8s (%p)\n", i, StringValueCStr(rstr),
266  (void *)ptr++);
267  }
268  for (; i < local_table_size - 1; i++) {
269  rstr = rb_inspect(*ptr);
270  fprintf(stderr, " local %2d: %8s (%p)\n", i, StringValueCStr(rstr),
271  (void *)ptr++);
272  }
273 
274  ptr = vm_base_ptr(cfp);
275  for (; ptr < sp; ptr++, i++) {
276  switch (TYPE(*ptr)) {
277  case T_UNDEF:
278  rstr = rb_str_new2("undef");
279  break;
280  case T_IMEMO:
281  rstr = rb_str_new2("imemo"); /* TODO: can put mode detail information */
282  break;
283  default:
284  rstr = rb_inspect(*ptr);
285  break;
286  }
287  fprintf(stderr, " stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr),
288  (ptr - th->ec.vm_stack));
289  }
290  }
291  else if (VM_FRAME_FINISHED_P(cfp)) {
292  if ((th)->ec.vm_stack + (th)->ec.vm_stack_size > (VALUE *)(cfp + 1)) {
293  vm_stack_dump_each(th, cfp + 1);
294  }
295  else {
296  /* SDR(); */
297  }
298  }
299  else {
300  rb_bug("unsupport frame type: %08lx", VM_FRAME_TYPE(cfp));
301  }
302 }
303 #endif
304 
305 void
307 {
308  rb_control_frame_t *cfp = th->ec.cfp;
309  ptrdiff_t pc = -1;
310  ptrdiff_t ep = cfp->ep - th->ec.vm_stack;
311  ptrdiff_t cfpi;
312 
313  if (VM_FRAME_RUBYFRAME_P(cfp)) {
314  pc = cfp->pc - cfp->iseq->body->iseq_encoded;
315  }
316 
317  if (ep < 0 || (size_t)ep > th->ec.vm_stack_size) {
318  ep = -1;
319  }
320 
321  cfpi = ((rb_control_frame_t *)(th->ec.vm_stack + th->ec.vm_stack_size)) - cfp;
322  fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
323  pc, (cfp->sp - th->ec.vm_stack), ep, cfpi);
324 }
325 
326 void
328 {
329  rb_vmdebug_debug_print_register(rb_thread_ptr(thval));
330 }
331 
332 void
334 {
335  const rb_iseq_t *iseq = cfp->iseq;
336 
337  if (iseq != 0) {
338  ptrdiff_t pc = _pc - iseq->body->iseq_encoded;
339  int i;
340 
341  for (i=0; i<(int)VM_CFP_CNT(th, cfp); i++) {
342  printf(" ");
343  }
344  printf("| ");
345  if(0)printf("[%03ld] ", (long)(cfp->sp - th->ec.vm_stack));
346 
347  /* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */
348  if (pc >= 0) {
349  const VALUE *iseq_original = rb_iseq_original_iseq((rb_iseq_t *)iseq);
350 
351  rb_iseq_disasm_insn(0, iseq_original, (size_t)pc, iseq, 0);
352  }
353  }
354 
355 #if VMDEBUG > 3
356  fprintf(stderr, " (1)");
358 #endif
359 }
360 
361 void
364  , VALUE reg_a, VALUE reg_b
365 #endif
366  )
367 {
368 #if VMDEBUG > 9
369  SDR2(cfp);
370 #endif
371 
372 #if VMDEBUG > 3
373  fprintf(stderr, " (2)");
375 #endif
376  /* stack_dump_raw(th, cfp); */
377 
378 #if VMDEBUG > 2
379  /* stack_dump_thobj(th); */
380  vm_stack_dump_each(th, th->ec.cfp);
381 
382 #if OPT_STACK_CACHING
383  {
384  VALUE rstr;
385  rstr = rb_inspect(reg_a);
386  fprintf(stderr, " sc reg A: %s\n", StringValueCStr(rstr));
387  rstr = rb_inspect(reg_b);
388  fprintf(stderr, " sc reg B: %s\n", StringValueCStr(rstr));
389  }
390 #endif
391  printf
392  ("--------------------------------------------------------------\n");
393 #endif
394 }
395 
396 VALUE
398 {
399  rb_thread_t *th = rb_thread_ptr(self);
400  rb_control_frame_t *cfp = th->ec.cfp;
401 
402  fprintf(stderr, "Thread state dump:\n");
403  fprintf(stderr, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp);
404  fprintf(stderr, "cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep);
405 
406  return Qnil;
407 }
408 
409 #if defined(HAVE_BACKTRACE)
410 # ifdef HAVE_LIBUNWIND
411 # undef backtrace
412 # define backtrace unw_backtrace
413 # elif defined(__APPLE__) && defined(__x86_64__) && defined(HAVE_LIBUNWIND_H)
414 # define UNW_LOCAL_ONLY
415 # include <libunwind.h>
416 # include <sys/mman.h>
417 # undef backtrace
418 int
419 backtrace(void **trace, int size)
420 {
421  unw_cursor_t cursor; unw_context_t uc;
422  unw_word_t ip;
423  int n = 0;
424 
425  unw_getcontext(&uc);
426  unw_init_local(&cursor, &uc);
427  while (unw_step(&cursor) > 0) {
428  unw_get_reg(&cursor, UNW_REG_IP, &ip);
429  trace[n++] = (void *)ip;
430  {
431  char buf[256];
432  unw_get_proc_name(&cursor, buf, 256, &ip);
433  if (strncmp("_sigtramp", buf, sizeof("_sigtramp")) == 0) {
434  goto darwin_sigtramp;
435  }
436  }
437  }
438  return n;
439 darwin_sigtramp:
440  /* darwin's bundled libunwind doesn't support signal trampoline */
441  {
442  ucontext_t *uctx;
443  char vec[1];
444  int r;
445  /* get previous frame information from %rbx at _sigtramp and set values to cursor
446  * http://www.opensource.apple.com/source/Libc/Libc-825.25/i386/sys/_sigtramp.s
447  * http://www.opensource.apple.com/source/libunwind/libunwind-35.1/src/unw_getcontext.s
448  */
449  unw_get_reg(&cursor, UNW_X86_64_RBX, &ip);
450  uctx = (ucontext_t *)ip;
451  unw_set_reg(&cursor, UNW_X86_64_RAX, uctx->uc_mcontext->__ss.__rax);
452  unw_set_reg(&cursor, UNW_X86_64_RBX, uctx->uc_mcontext->__ss.__rbx);
453  unw_set_reg(&cursor, UNW_X86_64_RCX, uctx->uc_mcontext->__ss.__rcx);
454  unw_set_reg(&cursor, UNW_X86_64_RDX, uctx->uc_mcontext->__ss.__rdx);
455  unw_set_reg(&cursor, UNW_X86_64_RDI, uctx->uc_mcontext->__ss.__rdi);
456  unw_set_reg(&cursor, UNW_X86_64_RSI, uctx->uc_mcontext->__ss.__rsi);
457  unw_set_reg(&cursor, UNW_X86_64_RBP, uctx->uc_mcontext->__ss.__rbp);
458  unw_set_reg(&cursor, UNW_X86_64_RSP, 8+(uctx->uc_mcontext->__ss.__rsp));
459  unw_set_reg(&cursor, UNW_X86_64_R8, uctx->uc_mcontext->__ss.__r8);
460  unw_set_reg(&cursor, UNW_X86_64_R9, uctx->uc_mcontext->__ss.__r9);
461  unw_set_reg(&cursor, UNW_X86_64_R10, uctx->uc_mcontext->__ss.__r10);
462  unw_set_reg(&cursor, UNW_X86_64_R11, uctx->uc_mcontext->__ss.__r11);
463  unw_set_reg(&cursor, UNW_X86_64_R12, uctx->uc_mcontext->__ss.__r12);
464  unw_set_reg(&cursor, UNW_X86_64_R13, uctx->uc_mcontext->__ss.__r13);
465  unw_set_reg(&cursor, UNW_X86_64_R14, uctx->uc_mcontext->__ss.__r14);
466  unw_set_reg(&cursor, UNW_X86_64_R15, uctx->uc_mcontext->__ss.__r15);
467  ip = uctx->uc_mcontext->__ss.__rip;
468 
469  /* There're 4 cases for SEGV:
470  * (1) called invalid address
471  * (2) read or write invalid address
472  * (3) received signal
473  *
474  * Detail:
475  * (1) called invalid address
476  * In this case, saved ip is invalid address.
477  * It needs to just save the address for the information,
478  * skip the frame, and restore the frame calling the
479  * invalid address from %rsp.
480  * The problem is how to check whether the ip is valid or not.
481  * This code uses mincore(2) and assume the address's page is
482  * incore/referenced or not reflects the problem.
483  * Note that High Sierra's mincore(2) may return -128.
484  * (2) read or write invalid address
485  * saved ip is valid. just restart backtracing.
486  * (3) received signal in user space
487  * Same as (2).
488  * (4) received signal in kernel
489  * In this case saved ip points just after syscall, but registers are
490  * already overwritten by kernel. To fix register consistency,
491  * skip libc's kernel wrapper.
492  * To detect this case, just previous two bytes of ip is "\x0f\x05",
493  * syscall instruction of x86_64.
494  */
495  r = mincore((const void *)ip, 1, vec);
496  if (r || vec[0] <= 0 || memcmp((const char *)ip-2, "\x0f\x05", 2) == 0) {
497  /* if segv is caused by invalid call or signal received in syscall */
498  /* the frame is invalid; skip */
499  trace[n++] = (void *)ip;
500  ip = *(unw_word_t*)uctx->uc_mcontext->__ss.__rsp;
501  }
502  trace[n++] = (void *)ip;
503  unw_set_reg(&cursor, UNW_REG_IP, ip);
504  }
505  while (unw_step(&cursor) > 0) {
506  unw_get_reg(&cursor, UNW_REG_IP, &ip);
507  trace[n++] = (void *)ip;
508  }
509  return n;
510 }
511 # elif defined(BROKEN_BACKTRACE)
512 # undef HAVE_BACKTRACE
513 # define HAVE_BACKTRACE 0
514 # endif
515 #else
516 # define HAVE_BACKTRACE 0
517 #endif
518 
519 #if HAVE_BACKTRACE
520 # include <execinfo.h>
521 #elif defined(_WIN32)
522 # include <imagehlp.h>
523 # ifndef SYMOPT_DEBUG
524 # define SYMOPT_DEBUG 0x80000000
525 # endif
526 # ifndef MAX_SYM_NAME
527 # define MAX_SYM_NAME 2000
528 typedef struct {
529  DWORD64 Offset;
530  WORD Segment;
531  ADDRESS_MODE Mode;
532 } ADDRESS64;
533 typedef struct {
534  DWORD64 Thread;
535  DWORD ThCallbackStack;
536  DWORD ThCallbackBStore;
537  DWORD NextCallback;
538  DWORD FramePointer;
539  DWORD64 KiCallUserMode;
540  DWORD64 KeUserCallbackDispatcher;
541  DWORD64 SystemRangeStart;
542  DWORD64 KiUserExceptionDispatcher;
543  DWORD64 StackBase;
544  DWORD64 StackLimit;
545  DWORD64 Reserved[5];
546 } KDHELP64;
547 typedef struct {
548  ADDRESS64 AddrPC;
549  ADDRESS64 AddrReturn;
550  ADDRESS64 AddrFrame;
551  ADDRESS64 AddrStack;
552  ADDRESS64 AddrBStore;
553  void *FuncTableEntry;
554  DWORD64 Params[4];
555  BOOL Far;
556  BOOL Virtual;
557  DWORD64 Reserved[3];
558  KDHELP64 KdHelp;
559 } STACKFRAME64;
560 typedef struct {
561  ULONG SizeOfStruct;
562  ULONG TypeIndex;
563  ULONG64 Reserved[2];
564  ULONG Index;
565  ULONG Size;
566  ULONG64 ModBase;
567  ULONG Flags;
568  ULONG64 Value;
569  ULONG64 Address;
570  ULONG Register;
571  ULONG Scope;
572  ULONG Tag;
573  ULONG NameLen;
574  ULONG MaxNameLen;
575  char Name[1];
576 } SYMBOL_INFO;
577 typedef struct {
578  DWORD SizeOfStruct;
579  void *Key;
580  DWORD LineNumber;
581  char *FileName;
582  DWORD64 Address;
583 } IMAGEHLP_LINE64;
584 typedef void *PREAD_PROCESS_MEMORY_ROUTINE64;
585 typedef void *PFUNCTION_TABLE_ACCESS_ROUTINE64;
586 typedef void *PGET_MODULE_BASE_ROUTINE64;
587 typedef void *PTRANSLATE_ADDRESS_ROUTINE64;
588 # endif
589 
590 static void
591 dump_thread(void *arg)
592 {
593  HANDLE dbghelp;
594  BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL);
595  BOOL (WINAPI *pSymCleanup)(HANDLE);
596  BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
597  DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64);
598  BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *);
599  BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *);
600  HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD);
601  DWORD tid = *(DWORD *)arg;
602  HANDLE ph;
603  HANDLE th;
604 
605  dbghelp = LoadLibrary("dbghelp.dll");
606  if (!dbghelp) return;
607  pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize");
608  pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup");
609  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");
610  pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64");
611  pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr");
612  pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64");
613  pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread");
614  if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 &&
615  pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) {
616  SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
617  ph = GetCurrentProcess();
618  pSymInitialize(ph, NULL, TRUE);
619  th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid);
620  if (th) {
621  if (SuspendThread(th) != (DWORD)-1) {
622  CONTEXT context;
623  memset(&context, 0, sizeof(context));
624  context.ContextFlags = CONTEXT_FULL;
625  if (GetThreadContext(th, &context)) {
626  char libpath[MAX_PATH];
627  char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
628  SYMBOL_INFO *info = (SYMBOL_INFO *)buf;
629  DWORD mac;
630  STACKFRAME64 frame;
631  memset(&frame, 0, sizeof(frame));
632 #if defined(_M_AMD64) || defined(__x86_64__)
633  mac = IMAGE_FILE_MACHINE_AMD64;
634  frame.AddrPC.Mode = AddrModeFlat;
635  frame.AddrPC.Offset = context.Rip;
636  frame.AddrFrame.Mode = AddrModeFlat;
637  frame.AddrFrame.Offset = context.Rbp;
638  frame.AddrStack.Mode = AddrModeFlat;
639  frame.AddrStack.Offset = context.Rsp;
640 #elif defined(_M_IA64) || defined(__ia64__)
641  mac = IMAGE_FILE_MACHINE_IA64;
642  frame.AddrPC.Mode = AddrModeFlat;
643  frame.AddrPC.Offset = context.StIIP;
644  frame.AddrBStore.Mode = AddrModeFlat;
645  frame.AddrBStore.Offset = context.RsBSP;
646  frame.AddrStack.Mode = AddrModeFlat;
647  frame.AddrStack.Offset = context.IntSp;
648 #else /* i386 */
649  mac = IMAGE_FILE_MACHINE_I386;
650  frame.AddrPC.Mode = AddrModeFlat;
651  frame.AddrPC.Offset = context.Eip;
652  frame.AddrFrame.Mode = AddrModeFlat;
653  frame.AddrFrame.Offset = context.Ebp;
654  frame.AddrStack.Mode = AddrModeFlat;
655  frame.AddrStack.Offset = context.Esp;
656 #endif
657 
658  while (pStackWalk64(mac, ph, th, &frame, &context, NULL,
659  NULL, NULL, NULL)) {
660  DWORD64 addr = frame.AddrPC.Offset;
661  IMAGEHLP_LINE64 line;
662  DWORD64 displacement;
663  DWORD tmp;
664 
665  if (addr == frame.AddrReturn.Offset || addr == 0 ||
666  frame.AddrReturn.Offset == 0)
667  break;
668 
669  memset(buf, 0, sizeof(buf));
670  info->SizeOfStruct = sizeof(SYMBOL_INFO);
671  info->MaxNameLen = MAX_SYM_NAME;
672  if (pSymFromAddr(ph, addr, &displacement, info)) {
673  if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
674  fprintf(stderr, "%s", libpath);
675  fprintf(stderr, "(%s+0x%I64x)",
676  info->Name, displacement);
677  }
678  fprintf(stderr, " [0x%p]", (void *)(VALUE)addr);
679  memset(&line, 0, sizeof(line));
680  line.SizeOfStruct = sizeof(line);
681  if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
682  fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber);
683  fprintf(stderr, "\n");
684  }
685  }
686 
687  ResumeThread(th);
688  }
689  CloseHandle(th);
690  }
691  pSymCleanup(ph);
692  }
693  FreeLibrary(dbghelp);
694 }
695 #endif
696 
697 void
699 {
700 #if HAVE_BACKTRACE
701 #define MAX_NATIVE_TRACE 1024
702  static void *trace[MAX_NATIVE_TRACE];
703  int n = (int)backtrace(trace, MAX_NATIVE_TRACE);
704 #if defined(USE_ELF) && defined(HAVE_DLADDR) && !defined(__sparc)
705  rb_dump_backtrace_with_lines(n, trace);
706 #else
707  char **syms = backtrace_symbols(trace, n);
708  if (syms) {
709  int i;
710  for (i=0; i<n; i++) {
711  fprintf(stderr, "%s\n", syms[i]);
712  }
713  free(syms);
714  }
715 #endif
716 #elif defined(_WIN32)
717  DWORD tid = GetCurrentThreadId();
718  HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid);
719  if (th != (HANDLE)-1)
720  WaitForSingleObject(th, INFINITE);
721 #endif
722 }
723 
724 #ifdef HAVE_LIBPROCSTAT
725 #include <sys/user.h>
726 #include <sys/sysctl.h>
727 #include <sys/param.h>
728 #include <libprocstat.h>
729 # ifndef KVME_TYPE_MGTDEVICE
730 # define KVME_TYPE_MGTDEVICE 8
731 # endif
732 void
733 procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
734 {
735  struct kinfo_vmentry *freep, *kve;
736  int ptrwidth;
737  unsigned int i, cnt;
738  const char *str;
739 #ifdef __x86_64__
740  ptrwidth = 14;
741 #else
742  ptrwidth = 2*sizeof(void *) + 2;
743 #endif
744  fprintf(stderr, "%*s %*s %3s %4s %4s %3s %3s %4s %-2s %-s\n",
745  ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
746  "PRES", "REF", "SHD", "FL", "TP", "PATH");
747 
748 #ifdef HAVE_PROCSTAT_GETVMMAP
749  freep = procstat_getvmmap(procstat, kipp, &cnt);
750 #else
751  freep = kinfo_getvmmap(kipp->ki_pid, &cnt);
752 #endif
753  if (freep == NULL)
754  return;
755  for (i = 0; i < cnt; i++) {
756  kve = &freep[i];
757  fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
758  fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
759  fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
760  fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
761  fprintf(stderr, "%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");
762  fprintf(stderr, "%4d ", kve->kve_resident);
763  fprintf(stderr, "%4d ", kve->kve_private_resident);
764  fprintf(stderr, "%3d ", kve->kve_ref_count);
765  fprintf(stderr, "%3d ", kve->kve_shadow_count);
766  fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-");
767  fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" :
768  "-");
769  fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-");
770  fprintf(stderr, "%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" :
771  kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-");
772  switch (kve->kve_type) {
773  case KVME_TYPE_NONE:
774  str = "--";
775  break;
776  case KVME_TYPE_DEFAULT:
777  str = "df";
778  break;
779  case KVME_TYPE_VNODE:
780  str = "vn";
781  break;
782  case KVME_TYPE_SWAP:
783  str = "sw";
784  break;
785  case KVME_TYPE_DEVICE:
786  str = "dv";
787  break;
788  case KVME_TYPE_PHYS:
789  str = "ph";
790  break;
791  case KVME_TYPE_DEAD:
792  str = "dd";
793  break;
794  case KVME_TYPE_SG:
795  str = "sg";
796  break;
797  case KVME_TYPE_MGTDEVICE:
798  str = "md";
799  break;
800  case KVME_TYPE_UNKNOWN:
801  default:
802  str = "??";
803  break;
804  }
805  fprintf(stderr, "%-2s ", str);
806  fprintf(stderr, "%-s\n", kve->kve_path);
807  }
808  free(freep);
809 }
810 #endif
811 
812 #if defined __linux__
813 # if defined __x86_64__ || defined __i386__
814 # define HAVE_PRINT_MACHINE_REGISTERS 1
815 # endif
816 #elif defined __APPLE__
817 # if defined __x86_64__ || defined __i386__
818 # define HAVE_PRINT_MACHINE_REGISTERS 1
819 # endif
820 #endif
821 
822 #ifdef HAVE_PRINT_MACHINE_REGISTERS
823 static int
824 print_machine_register(size_t reg, const char *reg_name, int col_count, int max_col)
825 {
826  int ret;
827  char buf[64];
828 
829 #ifdef __LP64__
830  ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%016zx", reg_name, reg);
831 #else
832  ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%08zx", reg_name, reg);
833 #endif
834  if (col_count + ret > max_col) {
835  fputs("\n", stderr);
836  col_count = 0;
837  }
838  col_count += ret;
839  fputs(buf, stderr);
840  return col_count;
841 }
842 # ifdef __linux__
843 # define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80))
844 # elif defined __APPLE__
845 # define dump_machine_register(reg) (col_count = print_machine_register(mctx->__ss.__##reg, #reg, col_count, 80))
846 # endif
847 
848 static void
849 rb_dump_machine_register(const ucontext_t *ctx)
850 {
851  int col_count = 0;
852  if (!ctx) return;
853 
854  fprintf(stderr, "-- Machine register context "
855  "------------------------------------------------\n");
856 
857 # if defined __linux__
858  {
859  const mcontext_t *const mctx = &ctx->uc_mcontext;
860 # if defined __x86_64__
861  dump_machine_register(RIP);
862  dump_machine_register(RBP);
863  dump_machine_register(RSP);
864  dump_machine_register(RAX);
865  dump_machine_register(RBX);
866  dump_machine_register(RCX);
867  dump_machine_register(RDX);
868  dump_machine_register(RDI);
869  dump_machine_register(RSI);
870  dump_machine_register(R8);
871  dump_machine_register(R9);
872  dump_machine_register(R10);
873  dump_machine_register(R11);
874  dump_machine_register(R12);
875  dump_machine_register(R13);
876  dump_machine_register(R14);
877  dump_machine_register(R15);
878  dump_machine_register(EFL);
879 # elif defined __i386__
880  dump_machine_register(GS);
881  dump_machine_register(FS);
882  dump_machine_register(ES);
883  dump_machine_register(DS);
884  dump_machine_register(EDI);
885  dump_machine_register(ESI);
886  dump_machine_register(EBP);
887  dump_machine_register(ESP);
888  dump_machine_register(EBX);
889  dump_machine_register(EDX);
890  dump_machine_register(ECX);
891  dump_machine_register(EAX);
892  dump_machine_register(TRAPNO);
893  dump_machine_register(ERR);
894  dump_machine_register(EIP);
895  dump_machine_register(CS);
896  dump_machine_register(EFL);
897  dump_machine_register(UESP);
898  dump_machine_register(SS);
899 # endif
900  }
901 # elif defined __APPLE__
902  {
903  const mcontext_t mctx = ctx->uc_mcontext;
904 # if defined __x86_64__
905  dump_machine_register(rax);
906  dump_machine_register(rbx);
907  dump_machine_register(rcx);
908  dump_machine_register(rdx);
909  dump_machine_register(rdi);
910  dump_machine_register(rsi);
911  dump_machine_register(rbp);
912  dump_machine_register(rsp);
913  dump_machine_register(r8);
914  dump_machine_register(r9);
915  dump_machine_register(r10);
916  dump_machine_register(r11);
917  dump_machine_register(r12);
918  dump_machine_register(r13);
919  dump_machine_register(r14);
920  dump_machine_register(r15);
921  dump_machine_register(rip);
922  dump_machine_register(rflags);
923 # elif defined __i386__
924  dump_machine_register(eax);
925  dump_machine_register(ebx);
926  dump_machine_register(ecx);
927  dump_machine_register(edx);
928  dump_machine_register(edi);
929  dump_machine_register(esi);
930  dump_machine_register(ebp);
931  dump_machine_register(esp);
932  dump_machine_register(ss);
933  dump_machine_register(eflags);
934  dump_machine_register(eip);
935  dump_machine_register(cs);
936  dump_machine_register(ds);
937  dump_machine_register(es);
938  dump_machine_register(fs);
939  dump_machine_register(gs);
940 # endif
941  }
942 # endif
943  fprintf(stderr, "\n\n");
944 }
945 #else
946 # define rb_dump_machine_register(ctx) ((void)0)
947 #endif /* HAVE_PRINT_MACHINE_REGISTERS */
948 
949 void
950 rb_vm_bugreport(const void *ctx)
951 {
952 #ifdef __linux__
953 # define PROC_MAPS_NAME "/proc/self/maps"
954 #endif
955 #ifdef PROC_MAPS_NAME
956  enum {other_runtime_info = 1};
957 #else
958  enum {other_runtime_info = 0};
959 #endif
960  const rb_vm_t *const vm = GET_VM();
961 
962  if (vm) {
963  SDR();
965  fputs("\n", stderr);
966  }
967 
969 
970 #if HAVE_BACKTRACE || defined(_WIN32)
971  fprintf(stderr, "-- C level backtrace information "
972  "-------------------------------------------\n");
974 
975 
976  fprintf(stderr, "\n");
977 #endif /* HAVE_BACKTRACE */
978 
979  if (other_runtime_info || vm) {
980  fprintf(stderr, "-- Other runtime information "
981  "-----------------------------------------------\n\n");
982  }
983  if (vm) {
984  int i;
985  VALUE name;
986  long len;
987  const int max_name_length = 1024;
988 # define LIMITED_NAME_LENGTH(s) \
989  (((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len)
990 
991  name = vm->progname;
992  fprintf(stderr, "* Loaded script: %.*s\n",
993  LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
994  fprintf(stderr, "\n");
995  fprintf(stderr, "* Loaded features:\n\n");
996  for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
997  name = RARRAY_AREF(vm->loaded_features, i);
998  if (RB_TYPE_P(name, T_STRING)) {
999  fprintf(stderr, " %4d %.*s\n", i,
1000  LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
1001  }
1002  else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
1003  const char *const type = RB_TYPE_P(name, T_CLASS) ?
1004  "class" : "module";
1005  name = rb_search_class_path(rb_class_real(name));
1006  if (!RB_TYPE_P(name, T_STRING)) {
1007  fprintf(stderr, " %4d %s:<unnamed>\n", i, type);
1008  continue;
1009  }
1010  fprintf(stderr, " %4d %s:%.*s\n", i, type,
1011  LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
1012  }
1013  else {
1015  if (!RB_TYPE_P(klass, T_STRING)) {
1016  fprintf(stderr, " %4d #<%p:%p>\n", i,
1017  (void *)CLASS_OF(name), (void *)name);
1018  continue;
1019  }
1020  fprintf(stderr, " %4d #<%.*s:%p>\n", i,
1021  LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
1022  (void *)name);
1023  }
1024  }
1025  fprintf(stderr, "\n");
1026  }
1027 
1028  {
1029 #ifdef PROC_MAPS_NAME
1030  {
1031  FILE *fp = fopen(PROC_MAPS_NAME, "r");
1032  if (fp) {
1033  fprintf(stderr, "* Process memory map:\n\n");
1034 
1035  while (!feof(fp)) {
1036  char buff[0x100];
1037  size_t rn = fread(buff, 1, 0x100, fp);
1038  if (fwrite(buff, 1, rn, stderr) != rn)
1039  break;
1040  }
1041 
1042  fclose(fp);
1043  fprintf(stderr, "\n\n");
1044  }
1045  }
1046 #endif /* __linux__ */
1047 #ifdef HAVE_LIBPROCSTAT
1048 # define MIB_KERN_PROC_PID_LEN 4
1049  int mib[MIB_KERN_PROC_PID_LEN];
1050  struct kinfo_proc kp;
1051  size_t len = sizeof(struct kinfo_proc);
1052  mib[0] = CTL_KERN;
1053  mib[1] = KERN_PROC;
1054  mib[2] = KERN_PROC_PID;
1055  mib[3] = getpid();
1056  if (sysctl(mib, MIB_KERN_PROC_PID_LEN, &kp, &len, NULL, 0) == -1) {
1057  perror("sysctl");
1058  }
1059  else {
1060  struct procstat *prstat = procstat_open_sysctl();
1061  fprintf(stderr, "* Process memory map:\n\n");
1062  procstat_vm(prstat, &kp);
1063  procstat_close(prstat);
1064  fprintf(stderr, "\n");
1065  }
1066 #endif /* __FreeBSD__ */
1067  }
1068 }
1069 
1070 #ifdef NON_SCALAR_THREAD_ID
1071 const char *ruby_fill_thread_id_string(rb_nativethread_id_t thid, rb_thread_id_string_t buf);
1072 #endif
1073 
1074 void
1076 {
1077  rb_vm_t *vm = GET_THREAD()->vm;
1078  rb_thread_t *th = NULL;
1079 
1080  list_for_each(&vm->living_threads, th, vmlt_node) {
1081 #ifdef NON_SCALAR_THREAD_ID
1083  ruby_fill_thread_id_string(th->thread_id, buf);
1084  fprintf(stderr, "th: %p, native_id: %s\n", th, buf);
1085 #else
1086  fprintf(stderr, "th: %p, native_id: %p\n", th, (void *)th->thread_id);
1087 #endif
1088  rb_vmdebug_stack_dump_raw(th, th->ec.cfp);
1089  }
1090 }
void rb_vmdebug_env_dump_raw(const rb_env_t *env, const VALUE *ep)
Definition: vm_dump.c:180
const VALUE * ep
Definition: vm_core.h:667
void rb_bug(const char *fmt,...)
Definition: error.c:521
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define FALSE
Definition: nkf.h:174
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:38
#define VM_CFP_CNT(th, cfp)
Definition: vm_dump.c:24
rb_control_frame_t * cfp
Definition: vm_core.h:744
VALUE rb_vmdebug_thread_dump_state(VALUE self)
Definition: vm_dump.c:397
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:1238
#define CLASS_OF(v)
Definition: ruby.h:453
#define T_MODULE
Definition: ruby.h:494
VALUE progname
Definition: vm_core.h:567
const VALUE * env
Definition: vm_core.h:921
struct rb_method_definition_struct *const def
Definition: method.h:62
const rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
rb_thread_t * th
Definition: vm_core.h:1639
void rb_vmdebug_stack_dump_th(VALUE thval)
Definition: vm_dump.c:213
struct rb_iseq_constant_body * body
Definition: vm_core.h:423
#define MAX_POSBUF
Definition: vm_dump.c:22
#define SDR2(cfp)
Definition: vm_core.h:1474
#define PRIxVALUE
Definition: ruby.h:133
#define SDR()
Definition: vm_core.h:1473
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
#define T_UNDEF
Definition: ruby.h:512
void rb_vmdebug_stack_dump_all_threads(void)
Definition: vm_dump.c:1075
#define GET_THREAD()
Definition: vm_core.h:1583
const VALUE * iseq_encoded
Definition: vm_core.h:314
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
Definition: object.c:277
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
const rb_iseq_t * iseq
Definition: vm_core.h:665
const rb_env_t * rb_vm_env_prev_env(const rb_env_t *env)
Definition: vm.c:741
unsigned int local_table_size
Definition: vm_core.h:410
#define val
IUnknown DWORD
Definition: win32ole.c:32
#define snprintf
Definition: subst.h:6
rb_control_frame_t * cfp
Definition: vm_core.h:1640
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:525
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
VALUE * rb_iseq_original_iseq(const rb_iseq_t *iseq)
Definition: compile.c:753
Definition: method.h:59
#define rb_str_new2
Definition: intern.h:835
#define PRIdPTRDIFF
Definition: ruby.h:159
void rb_vmdebug_debug_print_register(rb_thread_t *th)
Definition: vm_dump.c:306
void rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp, const VALUE *_pc)
Definition: vm_dump.c:333
#define TRUE
Definition: nkf.h:175
struct rb_iseq_constant_body::@135 param
parameter information
VALUE loaded_features
Definition: vm_core.h:544
void rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
Definition: vm_dump.c:141
#define VM_ENV_DATA_SIZE
Definition: vm_core.h:1047
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
#define T_IMEMO
Definition: ruby.h:511
unsigned int env_size
Definition: vm_core.h:922
#define Qnil
Definition: ruby.h:438
unsigned int uintptr_t
Definition: win32.h:106
unsigned long VALUE
Definition: ruby.h:85
void rb_vm_bugreport(const void *ctx)
Definition: vm_dump.c:950
#define OPT_STACK_CACHING
Definition: vm_opts.h:48
const char * rb_id2name(ID)
Definition: symbol.c:751
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
enum rb_iseq_constant_body::iseq_type type
register unsigned int len
Definition: zonetab.h:51
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:975
int size
Definition: encoding.c:57
void rb_print_backtrace(void)
Definition: vm_dump.c:698
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
int rb_iseq_disasm_insn(VALUE ret, const VALUE *code, size_t pos, const rb_iseq_t *iseq, VALUE child)
Disassemble a instruction Iseq -> Iseq inspect object.
Definition: iseq.c:1431
void rb_vmdebug_thread_dump_regs(VALUE thval)
Definition: vm_dump.c:327
rb_nativethread_id_t thread_id
Definition: vm_core.h:808
const struct rb_block block
Definition: vm_core.h:911
#define T_STRING
Definition: ruby.h:496
const VALUE * pc
Definition: vm_core.h:663
#define rb_dump_machine_register(ctx)
Definition: vm_dump.c:946
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:692
#define RUBY_VM_IFUNC_P(ptr)
#define T_CLASS
Definition: ruby.h:492
void rb_vmdebug_proc_dump_raw(rb_proc_t *proc)
Definition: vm_dump.c:199
rb_execution_context_t ec
Definition: vm_core.h:790
char rb_thread_id_string_t[sizeof(rb_nativethread_id_t) *2+3]
Definition: vm_core.h:736
const char * name
Definition: nkf.c:208
void rb_vmdebug_stack_dump_raw_current(void)
Definition: vm_dump.c:173
struct list_head living_threads
Definition: vm_core.h:524
#define ERR(err)
Definition: getaddrinfo.c:198
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:1008
void rb_backtrace_print_as_bugreport(void)
Definition: vm_backtrace.c:754
#define SYMBOL_P(x)
Definition: ruby.h:382
#define feof(p)
Definition: vsnprintf.c:214
#define env
#define PRIxPTRDIFF
Definition: ruby.h:163
#define NULL
Definition: _sdbm.c:102
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
Definition: object.c:251
VALUE rb_search_class_path(VALUE)
Definition: variable.c:337
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:362
#define LIMITED_NAME_LENGTH(s)
rb_iseq_location_t location
Definition: vm_core.h:386
#define rb_sym2str(sym)
Definition: console.c:107
#define GET_VM()
Definition: vm_core.h:1582