Ruby  2.4.2p198(2017-09-14revision59899)
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 
21 
22 static VALUE
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
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 
106  "frame_info",
109 };
110 
111 static inline rb_backtrace_location_t *
113 {
114  struct valued_frame_info *vloc;
115  GetCoreDataFromValue(locobj, struct valued_frame_info, vloc);
116  return vloc->loc;
117 }
118 
119 static int
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
149 {
150  return INT2FIX(location_lineno(location_ptr(self)));
151 }
152 
153 static VALUE
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
198 {
199  return location_label(location_ptr(self));
200 }
201 
202 static VALUE
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
225 {
226  return location_base_label(location_ptr(self));
227 }
228 
229 static VALUE
231 {
232  switch (loc->type) {
233  case LOCATION_TYPE_ISEQ:
235  return loc->body.iseq.iseq->body->location.path;
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
258 {
259  return location_path(location_ptr(self));
260 }
261 
262 static VALUE
264 {
265  switch (loc->type) {
266  case LOCATION_TYPE_ISEQ:
268  return loc->body.iseq.iseq->body->location.absolute_path;
269  case LOCATION_TYPE_CFUNC:
270  if (loc->body.cfunc.prev_loc) {
271  return location_absolute_path(loc->body.cfunc.prev_loc);
272  }
273  return Qnil;
274  case LOCATION_TYPE_IFUNC:
275  default:
276  rb_bug("location_absolute_path: 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
288 {
289  return location_absolute_path(location_ptr(self));
290 }
291 
292 static VALUE
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
311 {
312  VALUE file, name;
313  int lineno;
314 
315  switch (loc->type) {
316  case LOCATION_TYPE_ISEQ:
317  file = loc->body.iseq.iseq->body->location.path;
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 = loc->body.iseq.iseq->body->location.path;
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 = loc->body.cfunc.prev_loc->body.iseq.iseq->body->location.path;
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
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
363 {
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++) {
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 
404  "backtrace",
407 };
408 
409 int
411 {
412  return rb_typeddata_is_kind_of(obj, &backtrace_data_type);
413 }
414 
415 static VALUE
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
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->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->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;
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 static 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,
524  &arg);
525 
526  return arg.btobj;
527 }
528 
529 VALUE
531 {
532  return backtrace_object(GET_THREAD());
533 }
534 
535 static VALUE
536 backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg)
537 {
538  VALUE btary;
539  int i;
540 
541  if (UNLIKELY(lev < 0 || n < 0)) {
542  rb_bug("backtrace_collect: unreachable");
543  }
544 
545  btary = rb_ary_new();
546 
547  for (i=0; i+lev<bt->backtrace_size && i<n; i++) {
548  rb_backtrace_location_t *loc = &bt->backtrace[bt->backtrace_size - 1 - (lev+i)];
549  rb_ary_push(btary, func(loc, arg));
550  }
551 
552  return btary;
553 }
554 
555 static VALUE
557 {
558  return location_to_str(loc);
559 }
560 
561 static VALUE
562 backtrace_to_str_ary(VALUE self, long lev, long n)
563 {
565  int size;
566  VALUE r;
567 
569  size = bt->backtrace_size;
570 
571  if (n == 0) {
572  n = size;
573  }
574  if (lev > size) {
575  return Qnil;
576  }
577 
578  r = backtrace_collect(bt, lev, n, location_to_str_dmyarg, 0);
579  RB_GC_GUARD(self);
580  return r;
581 }
582 
583 VALUE
585 {
588 
589  if (!bt->strary) {
590  bt->strary = backtrace_to_str_ary(self, 0, bt->backtrace_size);
591  }
592  return bt->strary;
593 }
594 
595 static VALUE
597 {
598  VALUE obj;
599  struct valued_frame_info *vloc;
600  obj = TypedData_Make_Struct(rb_cBacktraceLocation, struct valued_frame_info, &location_data_type, vloc);
601 
602  vloc->loc = srcloc;
603  vloc->btobj = (VALUE)btobj;
604 
605  return obj;
606 }
607 
608 static VALUE
609 backtrace_to_location_ary(VALUE self, long lev, long n)
610 {
611  rb_backtrace_t *bt;
612  int size;
613  VALUE r;
614 
616  size = bt->backtrace_size;
617 
618  if (n == 0) {
619  n = size;
620  }
621  if (lev > size) {
622  return Qnil;
623  }
624 
625  r = backtrace_collect(bt, lev, n, location_create, (void *)self);
626  RB_GC_GUARD(self);
627  return r;
628 }
629 
630 VALUE
632 {
633  rb_backtrace_t *bt;
635 
636  if (!bt->locary) {
637  bt->locary = backtrace_to_location_ary(self, 0, 0);
638  }
639  return bt->locary;
640 }
641 
642 static VALUE
644 {
645  VALUE str = rb_backtrace_to_str_ary(self);
646  return str;
647 }
648 
649 static VALUE
651 {
652  rb_backtrace_t *bt;
654  bt->strary = str;
655  return self;
656 }
657 
658 VALUE
659 rb_vm_backtrace_str_ary(rb_thread_t *th, long lev, long n)
660 {
661  return backtrace_to_str_ary(backtrace_object(th), lev, n);
662 }
663 
664 VALUE
666 {
667  return backtrace_to_location_ary(backtrace_object(th), lev, n);
668 }
669 
670 /* make old style backtrace directly */
671 
672 struct oldbt_arg {
674  int lineno;
675  void (*func)(void *data, VALUE file, int lineno, VALUE name);
676  void *data; /* result */
677 };
678 
679 static void
680 oldbt_init(void *ptr, size_t dmy)
681 {
682  struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
683  rb_thread_t *th = GET_THREAD();
684 
685  arg->filename = th->vm->progname;
686  arg->lineno = 0;
687 }
688 
689 static void
690 oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
691 {
692  const rb_iseq_t *iseq = cfp->iseq;
693  const VALUE *pc = cfp->pc;
694  struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
695  VALUE file = arg->filename = iseq->body->location.path;
696  VALUE name = iseq->body->location.label;
697  int lineno = arg->lineno = calc_lineno(iseq, pc);
698 
699  (arg->func)(arg->data, file, lineno, name);
700 }
701 
702 static void
703 oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
704 {
705  struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
706  VALUE file = arg->filename;
707  VALUE name = rb_id2str(mid);
708  int lineno = arg->lineno;
709 
710  (arg->func)(arg->data, file, lineno, name);
711 }
712 
713 static void
714 oldbt_print(void *data, VALUE file, int lineno, VALUE name)
715 {
716  FILE *fp = (FILE *)data;
717 
718  if (NIL_P(name)) {
719  fprintf(fp, "\tfrom %s:%d:in unknown method\n",
720  RSTRING_PTR(file), lineno);
721  }
722  else {
723  fprintf(fp, "\tfrom %s:%d:in `%s'\n",
724  RSTRING_PTR(file), lineno, RSTRING_PTR(name));
725  }
726 }
727 
728 static void
730 {
731  struct oldbt_arg arg;
732 
733  arg.func = oldbt_print;
734  arg.data = (void *)fp;
736  oldbt_init,
739  &arg);
740 }
741 
742 static void
743 oldbt_bugreport(void *arg, VALUE file, int line, VALUE method)
744 {
745  const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
746  if (!*(int *)arg) {
747  fprintf(stderr, "-- Ruby level backtrace information "
748  "----------------------------------------\n");
749  *(int *)arg = 1;
750  }
751  if (NIL_P(method)) {
752  fprintf(stderr, "%s:%d:in unknown method\n", filename, line);
753  }
754  else {
755  fprintf(stderr, "%s:%d:in `%s'\n", filename, line, RSTRING_PTR(method));
756  }
757 }
758 
759 void
761 {
762  struct oldbt_arg arg;
763  int i = 0;
764 
765  arg.func = oldbt_bugreport;
766  arg.data = (int *)&i;
767 
769  oldbt_init,
772  &arg);
773 }
774 
775 void
777 {
778  vm_backtrace_print(stderr);
779 }
780 
781 static void
783 {
784  VALUE output = (VALUE)data;
785  VALUE str = rb_sprintf("\tfrom %"PRIsVALUE":%d:in ", file, lineno);
786 
787  if (NIL_P(name)) {
788  rb_str_cat2(str, "unknown method\n");
789  }
790  else {
791  rb_str_catf(str, " `%"PRIsVALUE"'\n", name);
792  }
793  rb_io_write(output, str);
794 }
795 
796 void
798 {
799  struct oldbt_arg arg;
800 
801  arg.func = oldbt_print_to;
802  arg.data = (void *)output;
804  oldbt_init,
807  &arg);
808 }
809 
810 VALUE
812 {
813  return rb_vm_backtrace_str_ary(GET_THREAD(), 0, 0);
814 }
815 
816 static VALUE
817 vm_backtrace_to_ary(rb_thread_t *th, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
818 {
819  VALUE level, vn;
820  long lev, n;
821  VALUE btval = backtrace_object(th);
822  VALUE r;
823  rb_backtrace_t *bt;
824 
826 
827  rb_scan_args(argc, argv, "02", &level, &vn);
828 
829  if (argc == 2 && NIL_P(vn)) argc--;
830 
831  switch (argc) {
832  case 0:
833  lev = lev_default + lev_plus;
834  n = bt->backtrace_size - lev;
835  break;
836  case 1:
837  {
838  long beg, len;
839  switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) {
840  case Qfalse:
841  lev = NUM2LONG(level);
842  if (lev < 0) {
843  rb_raise(rb_eArgError, "negative level (%ld)", lev);
844  }
845  lev += lev_plus;
846  n = bt->backtrace_size - lev;
847  break;
848  case Qnil:
849  return Qnil;
850  default:
851  lev = beg + lev_plus;
852  n = len;
853  break;
854  }
855  break;
856  }
857  case 2:
858  lev = NUM2LONG(level);
859  n = NUM2LONG(vn);
860  if (lev < 0) {
861  rb_raise(rb_eArgError, "negative level (%ld)", lev);
862  }
863  if (n < 0) {
864  rb_raise(rb_eArgError, "negative size (%ld)", n);
865  }
866  lev += lev_plus;
867  break;
868  default:
869  lev = n = 0; /* to avoid warning */
870  break;
871  }
872 
873  if (n == 0) {
874  return rb_ary_new();
875  }
876 
877  if (to_str) {
878  r = backtrace_to_str_ary(btval, lev, n);
879  }
880  else {
881  r = backtrace_to_location_ary(btval, lev, n);
882  }
883  RB_GC_GUARD(btval);
884  return r;
885 }
886 
887 static VALUE
888 thread_backtrace_to_ary(int argc, const VALUE *argv, VALUE thval, int to_str)
889 {
890  rb_thread_t *th;
891  GetThreadPtr(thval, th);
892 
893  if (th->to_kill || th->status == THREAD_KILLED)
894  return Qnil;
895 
896  return vm_backtrace_to_ary(th, argc, argv, 0, 0, to_str);
897 }
898 
899 VALUE
901 {
902  return thread_backtrace_to_ary(argc, argv, thval, 1);
903 }
904 
905 VALUE
907 {
908  return thread_backtrace_to_ary(argc, argv, thval, 0);
909 }
910 
911 /*
912  * call-seq:
913  * caller(start=1, length=nil) -> array or nil
914  * caller(range) -> array or nil
915  *
916  * Returns the current execution stack---an array containing strings in
917  * the form <code>file:line</code> or <code>file:line: in
918  * `method'</code>.
919  *
920  * The optional _start_ parameter determines the number of initial stack
921  * entries to omit from the top of the stack.
922  *
923  * A second optional +length+ parameter can be used to limit how many entries
924  * are returned from the stack.
925  *
926  * Returns +nil+ if _start_ is greater than the size of
927  * current execution stack.
928  *
929  * Optionally you can pass a range, which will return an array containing the
930  * entries within the specified range.
931  *
932  * def a(skip)
933  * caller(skip)
934  * end
935  * def b(skip)
936  * a(skip)
937  * end
938  * def c(skip)
939  * b(skip)
940  * end
941  * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
942  * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
943  * c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
944  * c(3) #=> ["prog:13:in `<main>'"]
945  * c(4) #=> []
946  * c(5) #=> nil
947  */
948 
949 static VALUE
951 {
952  return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 1);
953 }
954 
955 /*
956  * call-seq:
957  * caller_locations(start=1, length=nil) -> array or nil
958  * caller_locations(range) -> array or nil
959  *
960  * Returns the current execution stack---an array containing
961  * backtrace location objects.
962  *
963  * See Thread::Backtrace::Location for more information.
964  *
965  * The optional _start_ parameter determines the number of initial stack
966  * entries to omit from the top of the stack.
967  *
968  * A second optional +length+ parameter can be used to limit how many entries
969  * are returned from the stack.
970  *
971  * Returns +nil+ if _start_ is greater than the size of
972  * current execution stack.
973  *
974  * Optionally you can pass a range, which will return an array containing the
975  * entries within the specified range.
976  */
977 static VALUE
979 {
980  return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 0);
981 }
982 
983 /* called from Init_vm() in vm.c */
984 void
986 {
987  /* :nodoc: */
992 
993  /*
994  * An object representation of a stack frame, initialized by
995  * Kernel#caller_locations.
996  *
997  * For example:
998  *
999  * # caller_locations.rb
1000  * def a(skip)
1001  * caller_locations(skip)
1002  * end
1003  * def b(skip)
1004  * a(skip)
1005  * end
1006  * def c(skip)
1007  * b(skip)
1008  * end
1009  *
1010  * c(0..2).map do |call|
1011  * puts call.to_s
1012  * end
1013  *
1014  * Running <code>ruby caller_locations.rb</code> will produce:
1015  *
1016  * caller_locations.rb:2:in `a'
1017  * caller_locations.rb:5:in `b'
1018  * caller_locations.rb:8:in `c'
1019  *
1020  * Here's another example with a slightly different result:
1021  *
1022  * # foo.rb
1023  * class Foo
1024  * attr_accessor :locations
1025  * def initialize(skip)
1026  * @locations = caller_locations(skip)
1027  * end
1028  * end
1029  *
1030  * Foo.new(0..2).locations.map do |call|
1031  * puts call.to_s
1032  * end
1033  *
1034  * Now run <code>ruby foo.rb</code> and you should see:
1035  *
1036  * init.rb:4:in `initialize'
1037  * init.rb:8:in `new'
1038  * init.rb:8:in `<main>'
1039  */
1050 
1051  rb_define_global_function("caller", rb_f_caller, -1);
1052  rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
1053 }
1054 
1055 /* debugger API */
1056 
1058 
1060 
1065  VALUE contexts; /* [[klass, binding, iseq, cfp], ...] */
1067 };
1068 
1069 enum {
1075 };
1076 
1079 };
1080 
1081 static void
1082 collect_caller_bindings_init(void *arg, size_t size)
1083 {
1084  /* */
1085 }
1086 
1087 static VALUE
1089 {
1090  VALUE klass;
1091  if (rb_vm_control_frame_id_and_class(cfp, 0, 0, &klass)) {
1092  if (RB_TYPE_P(klass, T_ICLASS)) {
1093  return RBASIC(klass)->klass;
1094  }
1095  else {
1096  return klass;
1097  }
1098  }
1099  else {
1100  return Qnil;
1101  }
1102 }
1103 
1104 static void
1106 {
1107  struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1108  VALUE frame = rb_ary_new2(5);
1109 
1110  rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1112  rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); /* create later */
1113  rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? (VALUE)cfp->iseq : Qnil);
1115 
1116  rb_ary_push(data->ary, frame);
1117 }
1118 
1119 static void
1121 {
1122  struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1123  VALUE frame = rb_ary_new2(5);
1124 
1125  rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1127  rb_ary_store(frame, CALLER_BINDING_BINDING, Qnil); /* not available */
1128  rb_ary_store(frame, CALLER_BINDING_ISEQ, Qnil); /* not available */
1130 
1131  rb_ary_push(data->ary, frame);
1132 }
1133 
1134 static VALUE
1136 {
1137  struct collect_caller_bindings_data data;
1138  VALUE result;
1139  int i;
1140 
1141  data.ary = rb_ary_new();
1142 
1143  backtrace_each(th,
1147  &data);
1148 
1149  result = rb_ary_reverse(data.ary);
1150 
1151  /* bindings should be created from top of frame */
1152  for (i=0; i<RARRAY_LEN(result); i++) {
1153  VALUE entry = rb_ary_entry(result, i);
1154  VALUE cfp_val = rb_ary_entry(entry, CALLER_BINDING_BINDING);
1155 
1156  if (!NIL_P(cfp_val)) {
1157  rb_control_frame_t *cfp = GC_GUARDED_PTR_REF(cfp_val);
1159  }
1160  }
1161 
1162  return result;
1163 }
1164 
1165 /*
1166  * Note that the passed `rb_debug_inspector_t' will be disabled
1167  * after `rb_debug_inspector_open'.
1168  */
1169 
1170 VALUE
1172 {
1173  rb_debug_inspector_t dbg_context;
1174  rb_thread_t *th = GET_THREAD();
1175  int state;
1176  volatile VALUE MAYBE_UNUSED(result);
1177 
1178  dbg_context.th = th;
1179  dbg_context.cfp = dbg_context.th->cfp;
1180  dbg_context.backtrace = rb_vm_backtrace_location_ary(th, 0, 0);
1181  dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
1182  dbg_context.contexts = collect_caller_bindings(th);
1183 
1184  TH_PUSH_TAG(th);
1185  if ((state = EXEC_TAG()) == 0) {
1186  result = (*func)(&dbg_context, data);
1187  }
1188  TH_POP_TAG();
1189 
1190  /* invalidate bindings? */
1191 
1192  if (state) {
1193  TH_JUMP_TAG(th, state);
1194  }
1195 
1196  return result;
1197 }
1198 
1199 static VALUE
1200 frame_get(const rb_debug_inspector_t *dc, long index)
1201 {
1202  if (index < 0 || index >= dc->backtrace_size) {
1203  rb_raise(rb_eArgError, "no such frame");
1204  }
1205  return rb_ary_entry(dc->contexts, index);
1206 }
1207 
1208 VALUE
1210 {
1211  VALUE frame = frame_get(dc, index);
1212  return rb_ary_entry(frame, CALLER_BINDING_SELF);
1213 }
1214 
1215 VALUE
1217 {
1218  VALUE frame = frame_get(dc, index);
1219  return rb_ary_entry(frame, CALLER_BINDING_CLASS);
1220 }
1221 
1222 VALUE
1224 {
1225  VALUE frame = frame_get(dc, index);
1226  return rb_ary_entry(frame, CALLER_BINDING_BINDING);
1227 }
1228 
1229 VALUE
1231 {
1232  VALUE frame = frame_get(dc, index);
1234 
1235  return RTEST(iseq) ? rb_iseqw_new((rb_iseq_t *)iseq) : Qnil;
1236 }
1237 
1238 VALUE
1240 {
1241  return dc->backtrace;
1242 }
1243 
1244 int
1245 rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
1246 {
1247  int i;
1248  rb_thread_t *th = GET_THREAD();
1249  rb_control_frame_t *cfp = th->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
1250  const rb_callable_method_entry_t *cme;
1251 
1252  for (i=0; i<limit && cfp != end_cfp;) {
1253  if (cfp->iseq && cfp->pc) {
1254  if (start > 0) {
1255  start--;
1256  continue;
1257  }
1258 
1259  /* record frame info */
1260  cme = rb_vm_frame_method_entry(cfp);
1261  if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
1262  buff[i] = (VALUE)cme;
1263  }
1264  else {
1265  buff[i] = (VALUE)cfp->iseq;
1266  }
1267 
1268  if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
1269 
1270  i++;
1271  }
1272  cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1273  }
1274 
1275  return i;
1276 }
1277 
1278 static const rb_iseq_t *
1280 {
1281  if (frame == Qnil) return NULL;
1282 
1283  if (RB_TYPE_P(frame, T_IMEMO)) {
1284  switch (imemo_type(frame)) {
1285  case imemo_iseq:
1286  return (const rb_iseq_t *)frame;
1287  case imemo_ment:
1288  {
1290  switch (cme->def->type) {
1291  case VM_METHOD_TYPE_ISEQ:
1292  return cme->def->body.iseq.iseqptr;
1293  default:
1294  return NULL;
1295  }
1296  }
1297  default:
1298  break;
1299  }
1300  }
1301  rb_bug("frame2iseq: unreachable");
1302 }
1303 
1304 VALUE
1306 {
1307  const rb_iseq_t *iseq = frame2iseq(frame);
1308  return iseq ? rb_iseq_path(iseq) : Qnil;
1309 }
1310 
1311 VALUE
1313 {
1314  const rb_iseq_t *iseq = frame2iseq(frame);
1315  return iseq ? rb_iseq_absolute_path(iseq) : Qnil;
1316 }
1317 
1318 VALUE
1320 {
1321  const rb_iseq_t *iseq = frame2iseq(frame);
1322  return iseq ? rb_iseq_label(iseq) : Qnil;
1323 }
1324 
1325 VALUE
1327 {
1328  const rb_iseq_t *iseq = frame2iseq(frame);
1329  return iseq ? rb_iseq_base_label(iseq) : Qnil;
1330 }
1331 
1332 VALUE
1334 {
1335  const rb_iseq_t *iseq = frame2iseq(frame);
1336  return iseq ? rb_iseq_first_lineno(iseq) : Qnil;
1337 }
1338 
1339 static VALUE
1341 {
1342  if (frame == Qnil) return Qnil;
1343 
1344  if (RB_TYPE_P(frame, T_IMEMO)) {
1346 
1347  if (imemo_type(frame) == imemo_ment) {
1348  return cme->defined_class;
1349  }
1350  }
1351  return Qnil;
1352 }
1353 
1354 VALUE
1356 {
1357  VALUE klass = frame2klass(frame);
1358 
1359  if (klass && !NIL_P(klass)) {
1360  if (RB_TYPE_P(klass, T_ICLASS)) {
1361  klass = RBASIC(klass)->klass;
1362  }
1363  else if (FL_TEST(klass, FL_SINGLETON)) {
1364  klass = rb_ivar_get(klass, id__attached__);
1365  if (!RB_TYPE_P(klass, T_CLASS))
1366  return rb_sprintf("#<%s:%p>", rb_class2name(rb_obj_class(klass)), (void*)klass);
1367  }
1368  return rb_class_path(klass);
1369  }
1370  else {
1371  return Qnil;
1372  }
1373 }
1374 
1375 VALUE
1377 {
1378  VALUE klass = frame2klass(frame);
1379 
1380  if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) {
1381  return Qtrue;
1382  }
1383  else {
1384  return Qfalse;
1385  }
1386 }
1387 
1388 VALUE
1390 {
1391  const rb_iseq_t *iseq = frame2iseq(frame);
1392  return iseq ? rb_iseq_method_name(iseq) : Qnil;
1393 }
1394 
1395 VALUE
1397 {
1399 
1400  if (method_name != Qnil) {
1402  VALUE singleton_p = rb_profile_frame_singleton_method_p(frame);
1403 
1404  if (classpath != Qnil) {
1405  return rb_sprintf("%"PRIsVALUE"%s%"PRIsVALUE,
1406  classpath, singleton_p == Qtrue ? "." : "#", method_name);
1407  }
1408  else {
1409  return method_name;
1410  }
1411  }
1412  else {
1413  return Qnil;
1414  }
1415 }
1416 
1417 VALUE
1419 {
1420  VALUE label = rb_profile_frame_label(frame);
1421  VALUE base_label = rb_profile_frame_base_label(frame);
1422  VALUE qualified_method_name = rb_profile_frame_qualified_method_name(frame);
1423 
1424  if (NIL_P(qualified_method_name) || base_label == qualified_method_name) {
1425  return label;
1426  }
1427  else {
1428  long label_length = RSTRING_LEN(label);
1429  long base_label_length = RSTRING_LEN(base_label);
1430  int prefix_len = rb_long2int(label_length - base_label_length);
1431 
1432  return rb_sprintf("%.*s%"PRIsVALUE, prefix_len, RSTRING_PTR(label), qualified_method_name);
1433  }
1434 }
static VALUE location_inspect_m(VALUE self)
Definition: vm_backtrace.c:362
static VALUE thread_backtrace_to_ary(int argc, const VALUE *argv, VALUE thval, int to_str)
Definition: vm_backtrace.c:888
static VALUE location_create(rb_backtrace_location_t *srcloc, void *btobj)
Definition: vm_backtrace.c:596
static VALUE method_name(VALUE obj)
Definition: proc.c:1609
rb_control_frame_t * cfp
Definition: vm_core.h:708
rb_vm_t * vm
Definition: vm_core.h:703
void rb_backtrace_print_to(VALUE output)
Definition: vm_backtrace.c:797
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
Definition: iseq.c:1234
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1196
#define RARRAY_LEN(a)
Definition: ruby.h:1026
void rb_bug(const char *fmt,...)
Definition: error.c:482
rb_method_type_t type
Definition: method.h:148
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
static void oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:690
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:38
static VALUE location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy)
Definition: vm_backtrace.c:556
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:700
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:681
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:1172
static rb_backtrace_location_t * location_ptr(VALUE locobj)
Definition: vm_backtrace.c:112
#define CLASS_OF(v)
Definition: ruby.h:453
VALUE rb_iseqw_new(const rb_iseq_t *)
Definition: iseq.c:754
VALUE progname
Definition: vm_core.h:537
static int calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
Definition: vm_backtrace.c:32
#define Qtrue
Definition: ruby.h:437
struct rb_method_definition_struct *const def
Definition: method.h:61
#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:776
static VALUE location_base_label_m(VALUE self)
Definition: vm_backtrace.c:224
VALUE rb_make_backtrace(void)
Definition: vm_backtrace.c:811
#define TH_JUMP_TAG(th, st)
Definition: eval_intern.h:186
#define UNREACHABLE
Definition: ruby.h:46
struct rb_backtrace_location_struct::@187::@189 cfunc
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:905
#define rb_long2int(n)
Definition: ruby.h:319
VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq)
Definition: iseq.c:676
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:54
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:395
VALUE rb_backtrace_to_location_ary(VALUE self)
Definition: vm_backtrace.c:631
static VALUE location_label_m(VALUE self)
Definition: vm_backtrace.c:197
VALUE rb_iseq_label(const rb_iseq_t *iseq)
Definition: iseq.c:682
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2207
static VALUE location_to_str(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:310
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1260
static void bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:492
#define RB_GC_GUARD(v)
Definition: ruby.h:552
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
static void oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
Definition: vm_backtrace.c:703
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4394
static VALUE collect_caller_bindings(rb_thread_t *th)
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
Definition: range.c:1019
static int location_lineno(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:120
static VALUE id2str(ID id)
Definition: vm_backtrace.c:23
VALUE rb_io_write(VALUE, VALUE)
Definition: io.c:1508
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:673
static int VM_FRAME_RUBYFRAME_P(const rb_control_frame_t *cfp)
Definition: vm_core.h:1061
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:1421
#define rb_ary_new2
Definition: intern.h:90
static VALUE rb_f_caller_locations(int argc, VALUE *argv)
Definition: vm_backtrace.c:978
rb_method_iseq_t iseq
Definition: method.h:153
#define GET_THREAD()
Definition: vm_core.h:1513
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:286
static unsigned char * output
Definition: nkf.c:32
#define FL_SINGLETON
Definition: ruby.h:1215
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define TH_POP_TAG()
Definition: eval_intern.h:137
static VALUE location_absolute_path(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:263
#define FL_TEST(x, f)
Definition: ruby.h:1284
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
Definition: vm.c:2025
const rb_iseq_t * iseq
Definition: vm_core.h:634
void * data
Definition: vm_backtrace.c:676
VALUE rb_profile_frame_absolute_path(VALUE frame)
#define EXEC_TAG()
Definition: eval_intern.h:183
static VALUE rb_cBacktraceLocation
Definition: vm_backtrace.c:20
#define level
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1872
VALUE rb_vm_backtrace_location_ary(rb_thread_t *th, long lev, long n)
Definition: vm_backtrace.c:665
static VALUE location_path_m(VALUE self)
Definition: vm_backtrace.c:257
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:720
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_profile_frame_full_label(VALUE frame)
VALUE rb_ary_new(void)
Definition: array.c:493
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
static VALUE backtrace_object(rb_thread_t *th)
Definition: vm_backtrace.c:515
static void bt_init(void *ptr, size_t size)
Definition: vm_backtrace.c:482
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq)
Definition: iseq.c:694
#define NIL_P(v)
Definition: ruby.h:451
static const rb_data_type_t location_data_type
Definition: vm_backtrace.c:105
static void collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp)
static void oldbt_init(void *ptr, size_t dmy)
Definition: vm_backtrace.c:680
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:799
#define GetCoreDataFromValue(obj, type, ptr)
Definition: vm_core.h:262
static void collect_caller_bindings_init(void *arg, size_t size)
int argc
Definition: ruby.c:183
#define Qfalse
Definition: ruby.h:436
static VALUE backtrace_to_location_ary(VALUE self, long lev, long n)
Definition: vm_backtrace.c:609
const VALUE defined_class
Definition: method.h:60
Definition: method.h:58
static void collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
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:947
#define RSTRING_LEN(str)
Definition: ruby.h:978
static VALUE backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE(*func)(rb_backtrace_location_t *, void *arg), void *arg)
Definition: vm_backtrace.c:536
union rb_method_definition_struct::@144 body
rb_backtrace_location_t * backtrace
Definition: vm_backtrace.c:368
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1440
static VALUE location_format(VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:293
VALUE rb_class_path(VALUE)
Definition: variable.c:294
#define RUBY_SYMBOL_EXPORT_END
Definition: missing.h:49
void ruby_xfree(void *x)
Definition: gc.c:8017
static VALUE backtrace_to_str_ary(VALUE self, long lev, long n)
Definition: vm_backtrace.c:562
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1919
void(* func)(void *data, VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:675
#define T_IMEMO
Definition: ruby.h:511
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp)
Definition: vm_core.h:1173
#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:1066
VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp)
Definition: vm.c:889
#define Qnil
Definition: ruby.h:438
static void backtrace_each(rb_thread_t *th, void(*init)(void *arg, size_t size), void(*iter_iseq)(void *arg, const rb_control_frame_t *cfp), void(*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid), void *arg)
Definition: vm_backtrace.c:424
unsigned long VALUE
Definition: ruby.h:85
static VALUE result
Definition: nkf.c:40
RUBY_EXTERN VALUE rb_cThread
Definition: ruby.h:1909
void rb_backtrace_print_as_bugreport(void)
Definition: vm_backtrace.c:760
int rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
#define RBASIC(obj)
Definition: ruby.h:1204
const char * rb_class2name(VALUE)
Definition: variable.c:449
#define RUBY_SYMBOL_EXPORT_BEGIN
Definition: missing.h:48
static void vm_backtrace_print(FILE *fp)
Definition: vm_backtrace.c:729
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:131
static VALUE rb_f_caller(int argc, VALUE *argv)
Definition: vm_backtrace.c:950
const rb_iseq_t * iseq
Definition: vm_backtrace.c:58
#define MAYBE_UNUSED
Definition: ffi_common.h:32
static VALUE location_lineno_m(VALUE self)
Definition: vm_backtrace.c:148
#define RUBY_VM_END_CONTROL_FRAME(th)
Definition: vm_core.h:1174
register unsigned int len
Definition: zonetab.h:51
VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:900
enum rb_thread_status status
Definition: vm_core.h:738
void * ruby_xmalloc(size_t size)
Definition: gc.c:7931
#define RSTRING_PTR(str)
Definition: ruby.h:982
VALUE rb_profile_frame_qualified_method_name(VALUE frame)
static void location_mark(void *ptr)
Definition: vm_backtrace.c:77
static VALUE backtrace_load_data(VALUE self, VALUE str)
Definition: vm_backtrace.c:650
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:584
static void oldbt_bugreport(void *arg, VALUE file, int line, VALUE method)
Definition: vm_backtrace.c:743
static VALUE location_path(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:230
static VALUE location_to_str_m(VALUE self)
Definition: vm_backtrace.c:352
VALUE rb_vm_backtrace_str_ary(rb_thread_t *th, long lev, long n)
Definition: vm_backtrace.c:659
struct rb_backtrace_location_struct * prev_loc
Definition: vm_backtrace.c:66
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1480
void Init_vm_backtrace(void)
Definition: vm_backtrace.c:985
static void location_mark_entry(rb_backtrace_location_t *fi)
Definition: vm_backtrace.c:84
#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
const VALUE * pc
Definition: vm_core.h:632
VALUE rb_str_cat_cstr(VALUE, const char *)
Definition: string.c:2674
static ID classpath
Definition: variable.c:24
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1182
static void backtrace_free(void *ptr)
Definition: vm_backtrace.c:389
VALUE rb_str_inspect(VALUE)
Definition: string.c:5664
VALUE rb_iseq_path(const rb_iseq_t *iseq)
Definition: iseq.c:670
static void bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
Definition: vm_backtrace.c:505
#define UNLIKELY(x)
Definition: ffi_common.h:126
VALUE rb_cArray
Definition: array.c:25
#define GetThreadPtr(obj, ptr)
Definition: vm_core.h:646
static VALUE location_base_label(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:203
const rb_iseq_t * iseq
Definition: vm_core.h:602
VALUE rb_vm_backtrace_object(void)
Definition: vm_backtrace.c:530
#define T_CLASS
Definition: ruby.h:492
VALUE rb_iseq_base_label(const rb_iseq_t *iseq)
Definition: iseq.c:688
enum rb_backtrace_location_struct::LOCATION_TYPE type
const char * name
Definition: nkf.c:208
static VALUE backtrace_alloc(VALUE klass)
Definition: vm_backtrace.c:416
struct rb_backtrace_struct rb_backtrace_t
static const rb_iseq_t * frame2iseq(VALUE frame)
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2216
static VALUE location_absolute_path_m(VALUE self)
Definition: vm_backtrace.c:287
imemo_type
Definition: internal.h:737
rb_control_frame_t * cfp
static void oldbt_print(void *data, VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:714
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:948
static VALUE frame_get(const rb_debug_inspector_t *dc, long index)
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1141
const rb_iseq_t *const iseqptr
Definition: method.h:123
VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:906
static VALUE get_klass(const rb_control_frame_t *cfp)
rb_backtrace_location_t * backtrace_base
Definition: vm_backtrace.c:369
static VALUE vm_backtrace_to_ary(rb_thread_t *th, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
Definition: vm_backtrace.c:817
static size_t location_memsize(const void *ptr)
Definition: vm_backtrace.c:99
rb_backtrace_location_t * prev_loc
Definition: vm_backtrace.c:478
static const rb_data_type_t backtrace_data_type
Definition: vm_backtrace.c:403
static VALUE backtrace_dump_data(VALUE self)
Definition: vm_backtrace.c:643
#define NULL
Definition: _sdbm.c:102
#define T_ICLASS
Definition: ruby.h:493
VALUE rb_profile_frame_base_label(VALUE frame)
static VALUE location_label(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:154
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
static VALUE rb_cBacktrace
Definition: vm_backtrace.c:19
static VALUE frame2klass(VALUE frame)
VALUE rb_profile_frame_label(VALUE frame)
VALUE rb_eArgError
Definition: error.c:763
#define NUM2LONG(x)
Definition: ruby.h:648
union rb_backtrace_location_struct::@187 body
char ** argv
Definition: ruby.c:184
static void oldbt_print_to(void *data, VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:782
rb_iseq_location_t location
Definition: vm_core.h:358
VALUE rb_obj_class(VALUE)
Definition: object.c:229
static size_t backtrace_memsize(const void *ptr)
Definition: vm_backtrace.c:397
static void backtrace_mark(void *ptr)
Definition: vm_backtrace.c:376