Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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