Ruby  2.5.0dev(2017-10-22revision60238)
vm_backtrace.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm_backtrace.c -
4 
5  $Author: ko1 $
6  created at: Sun Jun 03 00:14:20 2012
7 
8  Copyright (C) 1993-2012 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "internal.h"
13 #include "ruby/debug.h"
14 
15 #include "vm_core.h"
16 #include "eval_intern.h"
17 #include "iseq.h"
18 
19 static VALUE rb_cBacktrace;
20 static VALUE rb_cBacktraceLocation;
21 
22 static VALUE
23 id2str(ID id)
24 {
25  VALUE str = rb_id2str(id);
26  if (!str) return Qnil;
27  return str;
28 }
29 #define rb_id2str(id) id2str(id)
30 
31 inline static int
32 calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
33 {
34  return rb_iseq_line_no(iseq, pc - iseq->body->iseq_encoded);
35 }
36 
37 int
39 {
40  if (VM_FRAME_RUBYFRAME_P(cfp) && cfp->iseq) {
41  return calc_lineno(cfp->iseq, cfp->pc);
42  }
43  else {
44  return 0;
45  }
46 }
47 
54  } type;
55 
56  union {
57  struct {
58  const rb_iseq_t *iseq;
59  union {
60  const VALUE *pc;
61  int lineno;
62  } lineno;
63  } iseq;
64  struct {
67  } cfunc;
68  } body;
70 
74 };
75 
76 static void
77 location_mark(void *ptr)
78 {
79  struct valued_frame_info *vfi = (struct valued_frame_info *)ptr;
80  rb_gc_mark(vfi->btobj);
81 }
82 
83 static void
84 location_mark_entry(rb_backtrace_location_t *fi)
85 {
86  switch (fi->type) {
87  case LOCATION_TYPE_ISEQ:
89  rb_gc_mark((VALUE)fi->body.iseq.iseq);
90  break;
93  default:
94  break;
95  }
96 }
97 
98 static size_t
99 location_memsize(const void *ptr)
100 {
101  /* rb_backtrace_location_t *fi = (rb_backtrace_location_t *)ptr; */
102  return sizeof(rb_backtrace_location_t);
103 }
104 
105 static const rb_data_type_t location_data_type = {
106  "frame_info",
107  {location_mark, RUBY_TYPED_DEFAULT_FREE, location_memsize,},
109 };
110 
111 static inline rb_backtrace_location_t *
112 location_ptr(VALUE locobj)
113 {
114  struct valued_frame_info *vloc;
115  GetCoreDataFromValue(locobj, struct valued_frame_info, vloc);
116  return vloc->loc;
117 }
118 
119 static int
120 location_lineno(rb_backtrace_location_t *loc)
121 {
122  switch (loc->type) {
123  case LOCATION_TYPE_ISEQ:
125  return (loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc));
127  return loc->body.iseq.lineno.lineno;
128  case LOCATION_TYPE_CFUNC:
129  if (loc->body.cfunc.prev_loc) {
130  return location_lineno(loc->body.cfunc.prev_loc);
131  }
132  return 0;
133  default:
134  rb_bug("location_lineno: unreachable");
135  UNREACHABLE;
136  }
137 }
138 
139 /*
140  * Returns the line number of this frame.
141  *
142  * For example, using +caller_locations.rb+ from Thread::Backtrace::Location
143  *
144  * loc = c(0..1).first
145  * loc.lineno #=> 2
146  */
147 static VALUE
148 location_lineno_m(VALUE self)
149 {
150  return INT2FIX(location_lineno(location_ptr(self)));
151 }
152 
153 static VALUE
154 location_label(rb_backtrace_location_t *loc)
155 {
156  switch (loc->type) {
157  case LOCATION_TYPE_ISEQ:
159  return loc->body.iseq.iseq->body->location.label;
160  case LOCATION_TYPE_CFUNC:
161  return rb_id2str(loc->body.cfunc.mid);
162  case LOCATION_TYPE_IFUNC:
163  default:
164  rb_bug("location_label: unreachable");
165  UNREACHABLE;
166  }
167 }
168 
169 /*
170  * Returns the label of this frame.
171  *
172  * Usually consists of method, class, module, etc names with decoration.
173  *
174  * Consider the following example:
175  *
176  * def foo
177  * puts caller_locations(0).first.label
178  *
179  * 1.times do
180  * puts caller_locations(0).first.label
181  *
182  * 1.times do
183  * puts caller_locations(0).first.label
184  * end
185  *
186  * end
187  * end
188  *
189  * The result of calling +foo+ is this:
190  *
191  * label: foo
192  * label: block in foo
193  * label: block (2 levels) in foo
194  *
195  */
196 static VALUE
197 location_label_m(VALUE self)
198 {
199  return location_label(location_ptr(self));
200 }
201 
202 static VALUE
203 location_base_label(rb_backtrace_location_t *loc)
204 {
205  switch (loc->type) {
206  case LOCATION_TYPE_ISEQ:
208  return loc->body.iseq.iseq->body->location.base_label;
209  case LOCATION_TYPE_CFUNC:
210  return rb_id2str(loc->body.cfunc.mid);
211  case LOCATION_TYPE_IFUNC:
212  default:
213  rb_bug("location_base_label: unreachable");
214  UNREACHABLE;
215  }
216 }
217 
218 /*
219  * Returns the base label of this frame.
220  *
221  * Usually same as #label, without decoration.
222  */
223 static VALUE
224 location_base_label_m(VALUE self)
225 {
226  return location_base_label(location_ptr(self));
227 }
228 
229 static VALUE
230 location_path(rb_backtrace_location_t *loc)
231 {
232  switch (loc->type) {
233  case LOCATION_TYPE_ISEQ:
235  return rb_iseq_path(loc->body.iseq.iseq);
236  case LOCATION_TYPE_CFUNC:
237  if (loc->body.cfunc.prev_loc) {
238  return location_path(loc->body.cfunc.prev_loc);
239  }
240  return Qnil;
241  case LOCATION_TYPE_IFUNC:
242  default:
243  rb_bug("location_path: unreachable");
244  UNREACHABLE;
245  }
246 }
247 
248 /*
249  * Returns the file name of this frame.
250  *
251  * For example, using +caller_locations.rb+ from Thread::Backtrace::Location
252  *
253  * loc = c(0..1).first
254  * loc.path #=> caller_locations.rb
255  */
256 static VALUE
257 location_path_m(VALUE self)
258 {
259  return location_path(location_ptr(self));
260 }
261 
262 static VALUE
263 location_realpath(rb_backtrace_location_t *loc)
264 {
265  switch (loc->type) {
266  case LOCATION_TYPE_ISEQ:
268  return rb_iseq_realpath(loc->body.iseq.iseq);
269  case LOCATION_TYPE_CFUNC:
270  if (loc->body.cfunc.prev_loc) {
271  return location_realpath(loc->body.cfunc.prev_loc);
272  }
273  return Qnil;
274  case LOCATION_TYPE_IFUNC:
275  default:
276  rb_bug("location_realpath: unreachable");
277  UNREACHABLE;
278  }
279 }
280 
281 /*
282  * Returns the full file path of this frame.
283  *
284  * Same as #path, but includes the absolute path.
285  */
286 static VALUE
287 location_absolute_path_m(VALUE self)
288 {
289  return location_realpath(location_ptr(self));
290 }
291 
292 static VALUE
293 location_format(VALUE file, int lineno, VALUE name)
294 {
295  VALUE s = rb_enc_sprintf(rb_enc_compatible(file, name), "%s", RSTRING_PTR(file));
296  if (lineno != 0) {
297  rb_str_catf(s, ":%d", lineno);
298  }
299  rb_str_cat_cstr(s, ":in ");
300  if (NIL_P(name)) {
301  rb_str_cat_cstr(s, "unknown method");
302  }
303  else {
304  rb_str_catf(s, "`%s'", RSTRING_PTR(name));
305  }
306  return s;
307 }
308 
309 static VALUE
310 location_to_str(rb_backtrace_location_t *loc)
311 {
312  VALUE file, name;
313  int lineno;
314 
315  switch (loc->type) {
316  case LOCATION_TYPE_ISEQ:
317  file = rb_iseq_path(loc->body.iseq.iseq);
318  name = loc->body.iseq.iseq->body->location.label;
319 
320  lineno = loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc);
322  break;
324  file = rb_iseq_path(loc->body.iseq.iseq);
325  lineno = loc->body.iseq.lineno.lineno;
326  name = loc->body.iseq.iseq->body->location.label;
327  break;
328  case LOCATION_TYPE_CFUNC:
329  if (loc->body.cfunc.prev_loc) {
330  file = rb_iseq_path(loc->body.cfunc.prev_loc->body.iseq.iseq);
331  lineno = location_lineno(loc->body.cfunc.prev_loc);
332  }
333  else {
334  rb_thread_t *th = GET_THREAD();
335  file = th->vm->progname;
336  lineno = INT2FIX(0);
337  }
338  name = rb_id2str(loc->body.cfunc.mid);
339  break;
340  case LOCATION_TYPE_IFUNC:
341  default:
342  rb_bug("location_to_str: unreachable");
343  }
344 
345  return location_format(file, lineno, name);
346 }
347 
348 /*
349  * Returns a Kernel#caller style string representing this frame.
350  */
351 static VALUE
352 location_to_str_m(VALUE self)
353 {
354  return location_to_str(location_ptr(self));
355 }
356 
357 /*
358  * Returns the same as calling +inspect+ on the string representation of
359  * #to_str
360  */
361 static VALUE
362 location_inspect_m(VALUE self)
363 {
364  return rb_str_inspect(location_to_str(location_ptr(self)));
365 }
366 
367 typedef struct rb_backtrace_struct {
374 
375 static void
376 backtrace_mark(void *ptr)
377 {
378  rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
379  size_t i, s = bt->backtrace_size;
380 
381  for (i=0; i<s; i++) {
382  location_mark_entry(&bt->backtrace[i]);
383  }
384  rb_gc_mark(bt->strary);
385  rb_gc_mark(bt->locary);
386 }
387 
388 static void
389 backtrace_free(void *ptr)
390 {
391  rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
392  if (bt->backtrace) ruby_xfree(bt->backtrace_base);
393  ruby_xfree(bt);
394 }
395 
396 static size_t
397 backtrace_memsize(const void *ptr)
398 {
399  rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
400  return sizeof(rb_backtrace_t) + sizeof(rb_backtrace_location_t) * bt->backtrace_size;
401 }
402 
403 static const rb_data_type_t backtrace_data_type = {
404  "backtrace",
405  {backtrace_mark, backtrace_free, backtrace_memsize,},
406  0, 0, RUBY_TYPED_FREE_IMMEDIATELY
407 };
408 
409 int
411 {
412  return rb_typeddata_is_kind_of(obj, &backtrace_data_type);
413 }
414 
415 static VALUE
416 backtrace_alloc(VALUE klass)
417 {
418  rb_backtrace_t *bt;
419  VALUE obj = TypedData_Make_Struct(klass, rb_backtrace_t, &backtrace_data_type, bt);
420  return obj;
421 }
422 
423 static void
424 backtrace_each(rb_thread_t *th,
425  void (*init)(void *arg, size_t size),
426  void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp),
427  void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid),
428  void *arg)
429 {
430  rb_control_frame_t *last_cfp = th->ec.cfp;
432  rb_control_frame_t *cfp;
433  ptrdiff_t size, i;
434 
435  /* <- start_cfp (end control frame)
436  * top frame (dummy)
437  * top frame (dummy)
438  * top frame <- start_cfp
439  * top frame
440  * ...
441  * 2nd frame <- lev:0
442  * current frame <- th->ec.cfp
443  */
444 
445  start_cfp =
447  RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */
448 
449  if (start_cfp < last_cfp) {
450  size = 0;
451  }
452  else {
453  size = start_cfp - last_cfp + 1;
454  }
455 
456  init(arg, size);
457 
458  /* SDR(); */
459  for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
460  /* fprintf(stderr, "cfp: %d\n", (rb_control_frame_t *)(th->stack + th->stack_size) - cfp); */
461  if (cfp->iseq) {
462  if (cfp->pc) {
463  iter_iseq(arg, cfp);
464  }
465  }
466  else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
468  ID mid = me->def->original_id;
469 
470  iter_cfunc(arg, cfp, mid);
471  }
472  }
473 }
474 
475 struct bt_iter_arg {
479 };
480 
481 static void
482 bt_init(void *ptr, size_t size)
483 {
484  struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
485  arg->btobj = backtrace_alloc(rb_cBacktrace);
487  arg->bt->backtrace_base = arg->bt->backtrace = ruby_xmalloc(sizeof(rb_backtrace_location_t) * size);
488  arg->bt->backtrace_size = 0;
489 }
490 
491 static void
492 bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
493 {
494  const rb_iseq_t *iseq = cfp->iseq;
495  const VALUE *pc = cfp->pc;
496  struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
497  rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
498  loc->type = LOCATION_TYPE_ISEQ;
499  loc->body.iseq.iseq = iseq;
500  loc->body.iseq.lineno.pc = pc;
501  arg->prev_loc = loc;
502 }
503 
504 static void
505 bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
506 {
507  struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
508  rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
509  loc->type = LOCATION_TYPE_CFUNC;
510  loc->body.cfunc.mid = mid;
511  loc->body.cfunc.prev_loc = arg->prev_loc;
512 }
513 
514 VALUE
516 {
517  struct bt_iter_arg arg;
518  arg.prev_loc = 0;
519 
520  backtrace_each(th,
521  bt_init,
522  bt_iter_iseq,
523  bt_iter_cfunc,
524  &arg);
525 
526  return arg.btobj;
527 }
528 
529 static VALUE
530 backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg)
531 {
532  VALUE btary;
533  int i;
534 
535  if (UNLIKELY(lev < 0 || n < 0)) {
536  rb_bug("backtrace_collect: unreachable");
537  }
538 
539  btary = rb_ary_new();
540 
541  for (i=0; i+lev<bt->backtrace_size && i<n; i++) {
542  rb_backtrace_location_t *loc = &bt->backtrace[bt->backtrace_size - 1 - (lev+i)];
543  rb_ary_push(btary, func(loc, arg));
544  }
545 
546  return btary;
547 }
548 
549 static VALUE
550 location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy)
551 {
552  return location_to_str(loc);
553 }
554 
555 static VALUE
556 backtrace_to_str_ary(VALUE self, long lev, long n)
557 {
559  int size;
560  VALUE r;
561 
563  size = bt->backtrace_size;
564 
565  if (n == 0) {
566  n = size;
567  }
568  if (lev > size) {
569  return Qnil;
570  }
571 
572  r = backtrace_collect(bt, lev, n, location_to_str_dmyarg, 0);
573  RB_GC_GUARD(self);
574  return r;
575 }
576 
577 VALUE
579 {
582 
583  if (!bt->strary) {
584  bt->strary = backtrace_to_str_ary(self, 0, bt->backtrace_size);
585  }
586  return bt->strary;
587 }
588 
589 static VALUE
590 location_create(rb_backtrace_location_t *srcloc, void *btobj)
591 {
592  VALUE obj;
593  struct valued_frame_info *vloc;
594  obj = TypedData_Make_Struct(rb_cBacktraceLocation, struct valued_frame_info, &location_data_type, vloc);
595 
596  vloc->loc = srcloc;
597  vloc->btobj = (VALUE)btobj;
598 
599  return obj;
600 }
601 
602 static VALUE
603 backtrace_to_location_ary(VALUE self, long lev, long n)
604 {
605  rb_backtrace_t *bt;
606  int size;
607  VALUE r;
608 
610  size = bt->backtrace_size;
611 
612  if (n == 0) {
613  n = size;
614  }
615  if (lev > size) {
616  return Qnil;
617  }
618 
619  r = backtrace_collect(bt, lev, n, location_create, (void *)self);
620  RB_GC_GUARD(self);
621  return r;
622 }
623 
624 VALUE
626 {
627  rb_backtrace_t *bt;
629 
630  if (!bt->locary) {
631  bt->locary = backtrace_to_location_ary(self, 0, 0);
632  }
633  return bt->locary;
634 }
635 
636 static VALUE
637 backtrace_dump_data(VALUE self)
638 {
639  VALUE str = rb_backtrace_to_str_ary(self);
640  return str;
641 }
642 
643 static VALUE
644 backtrace_load_data(VALUE self, VALUE str)
645 {
646  rb_backtrace_t *bt;
648  bt->strary = str;
649  return self;
650 }
651 
652 VALUE
654 {
655  return backtrace_to_str_ary(rb_threadptr_backtrace_object(th), lev, n);
656 }
657 
658 VALUE
660 {
661  return backtrace_to_location_ary(rb_threadptr_backtrace_object(th), lev, n);
662 }
663 
664 /* make old style backtrace directly */
665 
666 struct oldbt_arg {
668  int lineno;
669  void (*func)(void *data, VALUE file, int lineno, VALUE name);
670  void *data; /* result */
671 };
672 
673 static void
674 oldbt_init(void *ptr, size_t dmy)
675 {
676  struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
677  rb_thread_t *th = GET_THREAD();
678 
679  arg->filename = th->vm->progname;
680  arg->lineno = 0;
681 }
682 
683 static void
684 oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
685 {
686  const rb_iseq_t *iseq = cfp->iseq;
687  const VALUE *pc = cfp->pc;
688  struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
689  VALUE file = arg->filename = rb_iseq_path(iseq);
690  VALUE name = iseq->body->location.label;
691  int lineno = arg->lineno = calc_lineno(iseq, pc);
692 
693  (arg->func)(arg->data, file, lineno, name);
694 }
695 
696 static void
697 oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
698 {
699  struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
700  VALUE file = arg->filename;
701  VALUE name = rb_id2str(mid);
702  int lineno = arg->lineno;
703 
704  (arg->func)(arg->data, file, lineno, name);
705 }
706 
707 static void
708 oldbt_print(void *data, VALUE file, int lineno, VALUE name)
709 {
710  FILE *fp = (FILE *)data;
711 
712  if (NIL_P(name)) {
713  fprintf(fp, "\tfrom %s:%d:in unknown method\n",
714  RSTRING_PTR(file), lineno);
715  }
716  else {
717  fprintf(fp, "\tfrom %s:%d:in `%s'\n",
718  RSTRING_PTR(file), lineno, RSTRING_PTR(name));
719  }
720 }
721 
722 static void
723 vm_backtrace_print(FILE *fp)
724 {
725  struct oldbt_arg arg;
726 
727  arg.func = oldbt_print;
728  arg.data = (void *)fp;
729  backtrace_each(GET_THREAD(),
730  oldbt_init,
731  oldbt_iter_iseq,
732  oldbt_iter_cfunc,
733  &arg);
734 }
735 
736 static void
737 oldbt_bugreport(void *arg, VALUE file, int line, VALUE method)
738 {
739  const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
740  if (!*(int *)arg) {
741  fprintf(stderr, "-- Ruby level backtrace information "
742  "----------------------------------------\n");
743  *(int *)arg = 1;
744  }
745  if (NIL_P(method)) {
746  fprintf(stderr, "%s:%d:in unknown method\n", filename, line);
747  }
748  else {
749  fprintf(stderr, "%s:%d:in `%s'\n", filename, line, RSTRING_PTR(method));
750  }
751 }
752 
753 void
755 {
756  struct oldbt_arg arg;
757  int i = 0;
758 
759  arg.func = oldbt_bugreport;
760  arg.data = (int *)&i;
761 
762  backtrace_each(GET_THREAD(),
763  oldbt_init,
764  oldbt_iter_iseq,
765  oldbt_iter_cfunc,
766  &arg);
767 }
768 
769 void
771 {
772  vm_backtrace_print(stderr);
773 }
774 
775 struct print_to_arg {
776  VALUE (*iter)(VALUE recv, VALUE str);
778 };
779 
780 static void
781 oldbt_print_to(void *data, VALUE file, int lineno, VALUE name)
782 {
783  const struct print_to_arg *arg = data;
784  VALUE str = rb_sprintf("\tfrom %"PRIsVALUE":%d:in ", file, lineno);
785 
786  if (NIL_P(name)) {
787  rb_str_cat2(str, "unknown method\n");
788  }
789  else {
790  rb_str_catf(str, " `%"PRIsVALUE"'\n", name);
791  }
792  (*arg->iter)(arg->output, str);
793 }
794 
795 void
797 {
798  struct oldbt_arg arg;
799  struct print_to_arg parg;
800 
801  parg.iter = iter;
802  parg.output = output;
803  arg.func = oldbt_print_to;
804  arg.data = &parg;
805  backtrace_each(GET_THREAD(),
806  oldbt_init,
807  oldbt_iter_iseq,
808  oldbt_iter_cfunc,
809  &arg);
810 }
811 
812 VALUE
814 {
816 }
817 
818 static VALUE
819 threadptr_backtrace_to_ary(rb_thread_t *th, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
820 {
821  VALUE level, vn;
822  long lev, n;
824  VALUE r;
825  rb_backtrace_t *bt;
826 
828 
829  rb_scan_args(argc, argv, "02", &level, &vn);
830 
831  if (argc == 2 && NIL_P(vn)) argc--;
832 
833  switch (argc) {
834  case 0:
835  lev = lev_default + lev_plus;
836  n = bt->backtrace_size - lev;
837  break;
838  case 1:
839  {
840  long beg, len;
841  switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) {
842  case Qfalse:
843  lev = NUM2LONG(level);
844  if (lev < 0) {
845  rb_raise(rb_eArgError, "negative level (%ld)", lev);
846  }
847  lev += lev_plus;
848  n = bt->backtrace_size - lev;
849  break;
850  case Qnil:
851  return Qnil;
852  default:
853  lev = beg + lev_plus;
854  n = len;
855  break;
856  }
857  break;
858  }
859  case 2:
860  lev = NUM2LONG(level);
861  n = NUM2LONG(vn);
862  if (lev < 0) {
863  rb_raise(rb_eArgError, "negative level (%ld)", lev);
864  }
865  if (n < 0) {
866  rb_raise(rb_eArgError, "negative size (%ld)", n);
867  }
868  lev += lev_plus;
869  break;
870  default:
871  lev = n = 0; /* to avoid warning */
872  break;
873  }
874 
875  if (n == 0) {
876  return rb_ary_new();
877  }
878 
879  if (to_str) {
880  r = backtrace_to_str_ary(btval, lev, n);
881  }
882  else {
883  r = backtrace_to_location_ary(btval, lev, n);
884  }
885  RB_GC_GUARD(btval);
886  return r;
887 }
888 
889 static VALUE
890 thread_backtrace_to_ary(int argc, const VALUE *argv, VALUE thval, int to_str)
891 {
892  rb_thread_t *target_th = rb_thread_ptr(thval);
893 
894  if (target_th->to_kill || target_th->status == THREAD_KILLED)
895  return Qnil;
896 
897  return threadptr_backtrace_to_ary(target_th, argc, argv, 0, 0, to_str);
898 }
899 
900 VALUE
901 rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval)
902 {
903  return thread_backtrace_to_ary(argc, argv, thval, 1);
904 }
905 
906 VALUE
907 rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
908 {
909  return thread_backtrace_to_ary(argc, argv, thval, 0);
910 }
911 
912 /*
913  * call-seq:
914  * caller(start=1, length=nil) -> array or nil
915  * caller(range) -> array or nil
916  *
917  * Returns the current execution stack---an array containing strings in
918  * the form <code>file:line</code> or <code>file:line: in
919  * `method'</code>.
920  *
921  * The optional _start_ parameter determines the number of initial stack
922  * entries to omit from the top of the stack.
923  *
924  * A second optional +length+ parameter can be used to limit how many entries
925  * are returned from the stack.
926  *
927  * Returns +nil+ if _start_ is greater than the size of
928  * current execution stack.
929  *
930  * Optionally you can pass a range, which will return an array containing the
931  * entries within the specified range.
932  *
933  * def a(skip)
934  * caller(skip)
935  * end
936  * def b(skip)
937  * a(skip)
938  * end
939  * def c(skip)
940  * b(skip)
941  * end
942  * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
943  * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
944  * c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
945  * c(3) #=> ["prog:13:in `<main>'"]
946  * c(4) #=> []
947  * c(5) #=> nil
948  */
949 
950 static VALUE
951 rb_f_caller(int argc, VALUE *argv)
952 {
953  return threadptr_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 1);
954 }
955 
956 /*
957  * call-seq:
958  * caller_locations(start=1, length=nil) -> array or nil
959  * caller_locations(range) -> array or nil
960  *
961  * Returns the current execution stack---an array containing
962  * backtrace location objects.
963  *
964  * See Thread::Backtrace::Location for more information.
965  *
966  * The optional _start_ parameter determines the number of initial stack
967  * entries to omit from the top of the stack.
968  *
969  * A second optional +length+ parameter can be used to limit how many entries
970  * are returned from the stack.
971  *
972  * Returns +nil+ if _start_ is greater than the size of
973  * current execution stack.
974  *
975  * Optionally you can pass a range, which will return an array containing the
976  * entries within the specified range.
977  */
978 static VALUE
979 rb_f_caller_locations(int argc, VALUE *argv)
980 {
981  return threadptr_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 0);
982 }
983 
984 /* called from Init_vm() in vm.c */
985 void
987 {
988  /* :nodoc: */
989  rb_cBacktrace = rb_define_class_under(rb_cThread, "Backtrace", rb_cObject);
990  rb_define_alloc_func(rb_cBacktrace, backtrace_alloc);
991  rb_undef_method(CLASS_OF(rb_cBacktrace), "new");
992  rb_marshal_define_compat(rb_cBacktrace, rb_cArray, backtrace_dump_data, backtrace_load_data);
993 
994  /*
995  * An object representation of a stack frame, initialized by
996  * Kernel#caller_locations.
997  *
998  * For example:
999  *
1000  * # caller_locations.rb
1001  * def a(skip)
1002  * caller_locations(skip)
1003  * end
1004  * def b(skip)
1005  * a(skip)
1006  * end
1007  * def c(skip)
1008  * b(skip)
1009  * end
1010  *
1011  * c(0..2).map do |call|
1012  * puts call.to_s
1013  * end
1014  *
1015  * Running <code>ruby caller_locations.rb</code> will produce:
1016  *
1017  * caller_locations.rb:2:in `a'
1018  * caller_locations.rb:5:in `b'
1019  * caller_locations.rb:8:in `c'
1020  *
1021  * Here's another example with a slightly different result:
1022  *
1023  * # foo.rb
1024  * class Foo
1025  * attr_accessor :locations
1026  * def initialize(skip)
1027  * @locations = caller_locations(skip)
1028  * end
1029  * end
1030  *
1031  * Foo.new(0..2).locations.map do |call|
1032  * puts call.to_s
1033  * end
1034  *
1035  * Now run <code>ruby foo.rb</code> and you should see:
1036  *
1037  * init.rb:4:in `initialize'
1038  * init.rb:8:in `new'
1039  * init.rb:8:in `<main>'
1040  */
1041  rb_cBacktraceLocation = rb_define_class_under(rb_cBacktrace, "Location", rb_cObject);
1042  rb_undef_alloc_func(rb_cBacktraceLocation);
1043  rb_undef_method(CLASS_OF(rb_cBacktraceLocation), "new");
1044  rb_define_method(rb_cBacktraceLocation, "lineno", location_lineno_m, 0);
1045  rb_define_method(rb_cBacktraceLocation, "label", location_label_m, 0);
1046  rb_define_method(rb_cBacktraceLocation, "base_label", location_base_label_m, 0);
1047  rb_define_method(rb_cBacktraceLocation, "path", location_path_m, 0);
1048  rb_define_method(rb_cBacktraceLocation, "absolute_path", location_absolute_path_m, 0);
1049  rb_define_method(rb_cBacktraceLocation, "to_s", location_to_str_m, 0);
1050  rb_define_method(rb_cBacktraceLocation, "inspect", location_inspect_m, 0);
1051 
1052  rb_define_global_function("caller", rb_f_caller, -1);
1053  rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
1054 }
1055 
1056 /* debugger API */
1057 
1059 
1061 
1066  VALUE contexts; /* [[klass, binding, iseq, cfp], ...] */
1068 };
1069 
1070 enum {
1076 };
1077 
1080 };
1081 
1082 static void
1083 collect_caller_bindings_init(void *arg, size_t size)
1084 {
1085  /* */
1086 }
1087 
1088 static VALUE
1089 get_klass(const rb_control_frame_t *cfp)
1090 {
1091  VALUE klass;
1092  if (rb_vm_control_frame_id_and_class(cfp, 0, 0, &klass)) {
1093  if (RB_TYPE_P(klass, T_ICLASS)) {
1094  return RBASIC(klass)->klass;
1095  }
1096  else {
1097  return klass;
1098  }
1099  }
1100  else {
1101  return Qnil;
1102  }
1103 }
1104 
1105 static void
1106 collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp)
1107 {
1108  struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1109  VALUE frame = rb_ary_new2(5);
1110 
1111  rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1112  rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1113  rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); /* create later */
1114  rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? (VALUE)cfp->iseq : Qnil);
1116 
1117  rb_ary_push(data->ary, frame);
1118 }
1119 
1120 static void
1121 collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
1122 {
1123  struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1124  VALUE frame = rb_ary_new2(5);
1125 
1126  rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1127  rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1128  rb_ary_store(frame, CALLER_BINDING_BINDING, Qnil); /* not available */
1129  rb_ary_store(frame, CALLER_BINDING_ISEQ, Qnil); /* not available */
1131 
1132  rb_ary_push(data->ary, frame);
1133 }
1134 
1135 static VALUE
1136 collect_caller_bindings(rb_thread_t *th)
1137 {
1138  struct collect_caller_bindings_data data;
1139  VALUE result;
1140  int i;
1141 
1142  data.ary = rb_ary_new();
1143 
1144  backtrace_each(th,
1145  collect_caller_bindings_init,
1146  collect_caller_bindings_iseq,
1147  collect_caller_bindings_cfunc,
1148  &data);
1149 
1150  result = rb_ary_reverse(data.ary);
1151 
1152  /* bindings should be created from top of frame */
1153  for (i=0; i<RARRAY_LEN(result); i++) {
1154  VALUE entry = rb_ary_entry(result, i);
1155  VALUE cfp_val = rb_ary_entry(entry, CALLER_BINDING_BINDING);
1156 
1157  if (!NIL_P(cfp_val)) {
1158  rb_control_frame_t *cfp = GC_GUARDED_PTR_REF(cfp_val);
1160  }
1161  }
1162 
1163  return result;
1164 }
1165 
1166 /*
1167  * Note that the passed `rb_debug_inspector_t' will be disabled
1168  * after `rb_debug_inspector_open'.
1169  */
1170 
1171 VALUE
1173 {
1174  rb_debug_inspector_t dbg_context;
1175  rb_thread_t *th = GET_THREAD();
1176  enum ruby_tag_type state;
1177  volatile VALUE MAYBE_UNUSED(result);
1178 
1179  dbg_context.th = th;
1180  dbg_context.cfp = dbg_context.th->ec.cfp;
1181  dbg_context.backtrace = rb_threadptr_backtrace_location_ary(th, 0, 0);
1182  dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
1183  dbg_context.contexts = collect_caller_bindings(th);
1184 
1185  TH_PUSH_TAG(th);
1186  if ((state = EXEC_TAG()) == TAG_NONE) {
1187  result = (*func)(&dbg_context, data);
1188  }
1189  TH_POP_TAG();
1190 
1191  /* invalidate bindings? */
1192 
1193  if (state) {
1194  TH_JUMP_TAG(th, state);
1195  }
1196 
1197  return result;
1198 }
1199 
1200 static VALUE
1201 frame_get(const rb_debug_inspector_t *dc, long index)
1202 {
1203  if (index < 0 || index >= dc->backtrace_size) {
1204  rb_raise(rb_eArgError, "no such frame");
1205  }
1206  return rb_ary_entry(dc->contexts, index);
1207 }
1208 
1209 VALUE
1211 {
1212  VALUE frame = frame_get(dc, index);
1213  return rb_ary_entry(frame, CALLER_BINDING_SELF);
1214 }
1215 
1216 VALUE
1218 {
1219  VALUE frame = frame_get(dc, index);
1220  return rb_ary_entry(frame, CALLER_BINDING_CLASS);
1221 }
1222 
1223 VALUE
1225 {
1226  VALUE frame = frame_get(dc, index);
1227  return rb_ary_entry(frame, CALLER_BINDING_BINDING);
1228 }
1229 
1230 VALUE
1232 {
1233  VALUE frame = frame_get(dc, index);
1235 
1236  return RTEST(iseq) ? rb_iseqw_new((rb_iseq_t *)iseq) : Qnil;
1237 }
1238 
1239 VALUE
1241 {
1242  return dc->backtrace;
1243 }
1244 
1245 int
1246 rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
1247 {
1248  int i;
1249  rb_thread_t *th = GET_THREAD();
1250  rb_control_frame_t *cfp = th->ec.cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
1251  const rb_callable_method_entry_t *cme;
1252 
1253  for (i=0; i<limit && cfp != end_cfp;) {
1254  if (cfp->iseq && cfp->pc) {
1255  if (start > 0) {
1256  start--;
1257  continue;
1258  }
1259 
1260  /* record frame info */
1261  cme = rb_vm_frame_method_entry(cfp);
1262  if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
1263  buff[i] = (VALUE)cme;
1264  }
1265  else {
1266  buff[i] = (VALUE)cfp->iseq;
1267  }
1268 
1269  if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
1270 
1271  i++;
1272  }
1273  cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1274  }
1275 
1276  return i;
1277 }
1278 
1279 static const rb_iseq_t *
1280 frame2iseq(VALUE frame)
1281 {
1282  if (frame == Qnil) return NULL;
1283 
1284  if (RB_TYPE_P(frame, T_IMEMO)) {
1285  switch (imemo_type(frame)) {
1286  case imemo_iseq:
1287  return (const rb_iseq_t *)frame;
1288  case imemo_ment:
1289  {
1291  switch (cme->def->type) {
1292  case VM_METHOD_TYPE_ISEQ:
1293  return cme->def->body.iseq.iseqptr;
1294  default:
1295  return NULL;
1296  }
1297  }
1298  default:
1299  break;
1300  }
1301  }
1302  rb_bug("frame2iseq: unreachable");
1303 }
1304 
1305 VALUE
1307 {
1308  const rb_iseq_t *iseq = frame2iseq(frame);
1309  return iseq ? rb_iseq_path(iseq) : Qnil;
1310 }
1311 
1312 VALUE
1314 {
1315  const rb_iseq_t *iseq = frame2iseq(frame);
1316  return iseq ? rb_iseq_realpath(iseq) : Qnil;
1317 }
1318 
1319 VALUE
1321 {
1322  const rb_iseq_t *iseq = frame2iseq(frame);
1323  return iseq ? rb_iseq_label(iseq) : Qnil;
1324 }
1325 
1326 VALUE
1328 {
1329  const rb_iseq_t *iseq = frame2iseq(frame);
1330  return iseq ? rb_iseq_base_label(iseq) : Qnil;
1331 }
1332 
1333 VALUE
1335 {
1336  const rb_iseq_t *iseq = frame2iseq(frame);
1337  return iseq ? rb_iseq_first_lineno(iseq) : Qnil;
1338 }
1339 
1340 static VALUE
1341 frame2klass(VALUE frame)
1342 {
1343  if (frame == Qnil) return Qnil;
1344 
1345  if (RB_TYPE_P(frame, T_IMEMO)) {
1347 
1348  if (imemo_type(frame) == imemo_ment) {
1349  return cme->defined_class;
1350  }
1351  }
1352  return Qnil;
1353 }
1354 
1355 VALUE
1357 {
1358  VALUE klass = frame2klass(frame);
1359 
1360  if (klass && !NIL_P(klass)) {
1361  if (RB_TYPE_P(klass, T_ICLASS)) {
1362  klass = RBASIC(klass)->klass;
1363  }
1364  else if (FL_TEST(klass, FL_SINGLETON)) {
1365  klass = rb_ivar_get(klass, id__attached__);
1366  if (!RB_TYPE_P(klass, T_CLASS))
1367  return rb_sprintf("#<%s:%p>", rb_class2name(rb_obj_class(klass)), (void*)klass);
1368  }
1369  return rb_class_path(klass);
1370  }
1371  else {
1372  return Qnil;
1373  }
1374 }
1375 
1376 VALUE
1378 {
1379  VALUE klass = frame2klass(frame);
1380 
1381  if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) {
1382  return Qtrue;
1383  }
1384  else {
1385  return Qfalse;
1386  }
1387 }
1388 
1389 VALUE
1391 {
1392  const rb_iseq_t *iseq = frame2iseq(frame);
1393  return iseq ? rb_iseq_method_name(iseq) : Qnil;
1394 }
1395 
1396 VALUE
1398 {
1399  VALUE method_name = rb_profile_frame_method_name(frame);
1400 
1401  if (method_name != Qnil) {
1402  VALUE classpath = rb_profile_frame_classpath(frame);
1403  VALUE singleton_p = rb_profile_frame_singleton_method_p(frame);
1404 
1405  if (classpath != Qnil) {
1406  return rb_sprintf("%"PRIsVALUE"%s%"PRIsVALUE,
1407  classpath, singleton_p == Qtrue ? "." : "#", method_name);
1408  }
1409  else {
1410  return method_name;
1411  }
1412  }
1413  else {
1414  return Qnil;
1415  }
1416 }
1417 
1418 VALUE
1420 {
1421  VALUE label = rb_profile_frame_label(frame);
1422  VALUE base_label = rb_profile_frame_base_label(frame);
1423  VALUE qualified_method_name = rb_profile_frame_qualified_method_name(frame);
1424 
1425  if (NIL_P(qualified_method_name) || base_label == qualified_method_name) {
1426  return label;
1427  }
1428  else {
1429  long label_length = RSTRING_LEN(label);
1430  long base_label_length = RSTRING_LEN(base_label);
1431  int prefix_len = rb_long2int(label_length - base_label_length);
1432 
1433  return rb_sprintf("%.*s%"PRIsVALUE, prefix_len, RSTRING_PTR(label), qualified_method_name);
1434  }
1435 }
struct rb_backtrace_location_struct::@126::@128 cfunc
VALUE rb_threadptr_backtrace_location_ary(rb_thread_t *th, long lev, long n)
Definition: vm_backtrace.c:659
rb_vm_t * vm
Definition: vm_core.h:788
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
Definition: iseq.c:1263
void rb_bug(const char *fmt,...)
Definition: error.c:521
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define RARRAY_LEN(a)
Definition: ruby.h:1019
VALUE rb_threadptr_backtrace_str_ary(rb_thread_t *th, long lev, long n)
Definition: vm_backtrace.c:653
ruby_tag_type
Definition: vm_core.h:151
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
VALUE rb_threadptr_backtrace_object(rb_thread_t *th)
Definition: vm_backtrace.c:515
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:38
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:410
VALUE rb_profile_frame_classpath(VALUE frame)
VALUE rb_iseq_method_name(const rb_iseq_t *iseq)
Definition: iseq.c:728
rb_control_frame_t * cfp
Definition: vm_core.h:744
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:675
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:1238
#define TAG_NONE
Definition: vm_core.h:164
void rb_backtrace_each(VALUE(*iter)(VALUE recv, VALUE str), VALUE output)
Definition: vm_backtrace.c:796
#define CLASS_OF(v)
Definition: ruby.h:453
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
VALUE progname
Definition: vm_core.h:567
#define Qtrue
Definition: ruby.h:437
struct rb_method_definition_struct *const def
Definition: method.h:62
#define rb_id2str(id)
Definition: vm_backtrace.c:29
const rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
void rb_backtrace(void)
Definition: vm_backtrace.c:770
VALUE rb_make_backtrace(void)
Definition: vm_backtrace.c:813
Ruby method.
Definition: method.h:102
#define TH_JUMP_TAG(th, st)
Definition: eval_intern.h:204
#define UNREACHABLE
Definition: ruby.h:46
#define MAYBE_UNUSED(x)
Definition: internal.h:46
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
#define rb_long2int(n)
Definition: ruby.h:319
VALUE rb_profile_frame_first_lineno(VALUE frame)
VALUE rb_profile_frame_method_name(VALUE frame)
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:962
struct rb_iseq_constant_body * body
Definition: vm_core.h:423
VALUE rb_backtrace_to_location_ary(VALUE self)
Definition: vm_backtrace.c:625
VALUE rb_iseq_label(const rb_iseq_t *iseq)
Definition: iseq.c:710
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
#define RB_GC_GUARD(v)
Definition: ruby.h:552
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4464
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
Definition: range.c:1003
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1745
VALUE rb_profile_frame_singleton_method_p(VALUE frame)
VALUE filename
Definition: vm_backtrace.c:667
#define FL_TEST(x, f)
Definition: ruby.h:1282
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1533
VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
Definition: sprintf.c:1433
#define rb_ary_new2
Definition: intern.h:90
#define GET_THREAD()
Definition: vm_core.h:1583
VALUE rb_eArgError
Definition: error.c:802
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:759
VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
const VALUE * iseq_encoded
Definition: vm_core.h:314
VALUE rb_iseqw_new(const rb_iseq_t *)
Definition: iseq.c:782
#define FL_SINGLETON
Definition: ruby.h:1208
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
Definition: object.c:277
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE(* iter)(VALUE recv, VALUE str)
Definition: vm_backtrace.c:776
#define TH_POP_TAG()
Definition: eval_intern.h:138
#define UNLIKELY(x)
Definition: internal.h:43
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
Definition: vm.c:2048
const rb_iseq_t * iseq
Definition: vm_core.h:665
void * data
Definition: vm_backtrace.c:670
VALUE rb_profile_frame_absolute_path(VALUE frame)
#define EXEC_TAG()
Definition: eval_intern.h:201
#define level
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_profile_frame_full_label(VALUE frame)
VALUE rb_ary_new(void)
Definition: array.c:499
rb_backtrace_location_t * loc
Definition: vm_backtrace.c:72
rb_backtrace_t * bt
Definition: vm_backtrace.c:476
VALUE(* rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *)
Definition: debug.h:43
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq)
Definition: iseq.c:722
#define NIL_P(v)
Definition: ruby.h:451
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:815
#define GetCoreDataFromValue(obj, type, ptr)
Definition: vm_core.h:264
int argc
Definition: ruby.c:187
#define Qfalse
Definition: ruby.h:436
const VALUE defined_class
Definition: method.h:61
Definition: method.h:59
VALUE rb_profile_frame_path(VALUE frame)
VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
#define GC_GUARDED_PTR(p)
Definition: vm_core.h:1007
#define RSTRING_LEN(str)
Definition: ruby.h:971
rb_backtrace_location_t * backtrace
Definition: vm_backtrace.c:368
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
VALUE rb_class_path(VALUE)
Definition: variable.c:295
#define RUBY_SYMBOL_EXPORT_END
Definition: missing.h:49
void ruby_xfree(void *x)
Definition: gc.c:8085
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
void(* func)(void *data, VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:669
#define T_IMEMO
Definition: ruby.h:511
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp)
Definition: vm_core.h:1239
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
struct rb_backtrace_location_struct rb_backtrace_location_t
#define RUBYVM_CFUNC_FRAME_P(cfp)
Definition: vm_core.h:1131
VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp)
Definition: vm.c:895
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
RUBY_EXTERN VALUE rb_cThread
Definition: ruby.h:1930
void rb_backtrace_print_as_bugreport(void)
Definition: vm_backtrace.c:754
int rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
#define RBASIC(obj)
Definition: ruby.h:1197
const char * rb_class2name(VALUE)
Definition: variable.c:450
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition: missing.h:48
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:131
const rb_iseq_t * iseq
Definition: vm_backtrace.c:58
#define RUBY_VM_END_CONTROL_FRAME(th)
Definition: vm_core.h:1240
register unsigned int len
Definition: zonetab.h:51
VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:901
enum rb_thread_status status
Definition: vm_core.h:812
void * ruby_xmalloc(size_t size)
Definition: gc.c:7997
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
Definition: iseq.c:698
VALUE rb_profile_frame_qualified_method_name(VALUE frame)
int size
Definition: encoding.c:57
#define INT2FIX(i)
Definition: ruby.h:232
VALUE rb_backtrace_to_str_ary(VALUE self)
Definition: vm_backtrace.c:578
struct rb_backtrace_location_struct * prev_loc
Definition: vm_backtrace.c:66
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1492
void Init_vm_backtrace(void)
Definition: vm_backtrace.c:986
#define RTEST(v)
Definition: ruby.h:450
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:134
union rb_backtrace_location_struct::@126 body
const VALUE * pc
Definition: vm_core.h:663
VALUE rb_str_cat_cstr(VALUE, const char *)
Definition: string.c:2756
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
VALUE rb_str_inspect(VALUE)
Definition: string.c:5813
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:692
VALUE rb_cArray
Definition: array.c:26
const rb_iseq_t * iseq
Definition: vm_core.h:633
#define T_CLASS
Definition: ruby.h:492
VALUE rb_iseq_base_label(const rb_iseq_t *iseq)
Definition: iseq.c:716
rb_execution_context_t ec
Definition: vm_core.h:790
enum rb_backtrace_location_struct::LOCATION_TYPE type
const char * name
Definition: nkf.c:208
struct rb_backtrace_struct rb_backtrace_t
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2224
imemo_type
Definition: internal.h:838
rb_control_frame_t * cfp
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:1008
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1134
VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:907
rb_backtrace_location_t * backtrace_base
Definition: vm_backtrace.c:369
rb_backtrace_location_t * prev_loc
Definition: vm_backtrace.c:478
#define NULL
Definition: _sdbm.c:102
#define T_ICLASS
Definition: ruby.h:493
VALUE rb_profile_frame_base_label(VALUE frame)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
VALUE rb_profile_frame_label(VALUE frame)
#define NUM2LONG(x)
Definition: ruby.h:648
char ** argv
Definition: ruby.c:188
rb_iseq_location_t location
Definition: vm_core.h:386