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