Ruby 2.0.0p353(2013-11-22revision43784)

- 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 };
116
117 static inline rb_backtrace_location_t *
118 location_ptr(VALUE locobj)
119 {
120 struct valued_frame_info *vloc;
121 GetCoreDataFromValue(locobj, struct valued_frame_info, vloc);
122 return vloc->loc;
123 }
124
125 static int
126 location_lineno(rb_backtrace_location_t *loc)
127 {
128 switch (loc->type) {
129 case LOCATION_TYPE_ISEQ:
130 loc->type = LOCATION_TYPE_ISEQ_CALCED;
131 return (loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc));
132 case LOCATION_TYPE_ISEQ_CALCED:
133 return loc->body.iseq.lineno.lineno;
134 case LOCATION_TYPE_CFUNC:
135 if (loc->body.cfunc.prev_loc) {
136 return location_lineno(loc->body.cfunc.prev_loc);
137 }
138 return 0;
139 default:
140 rb_bug("location_lineno: unreachable");
141 UNREACHABLE;
142 }
143 }
144
145 /*
146 * Returns the line number of this frame.
147 *
148 * For example, using +caller_locations.rb+ from Thread::Backtrace::Location
149 *
150 * loc = c(0..1).first
151 * loc.lineno #=> 2
152 */
153 static VALUE
154 location_lineno_m(VALUE self)
155 {
156 return INT2FIX(location_lineno(location_ptr(self)));
157 }
158
159 static VALUE
160 location_label(rb_backtrace_location_t *loc)
161 {
162 switch (loc->type) {
163 case LOCATION_TYPE_ISEQ:
164 case LOCATION_TYPE_ISEQ_CALCED:
165 return loc->body.iseq.iseq->location.label;
166 case LOCATION_TYPE_CFUNC:
167 return rb_id2str(loc->body.cfunc.mid);
168 case LOCATION_TYPE_IFUNC:
169 default:
170 rb_bug("location_label: unreachable");
171 UNREACHABLE;
172 }
173 }
174
175 /*
176 * Returns the label of this frame.
177 *
178 * Usually consists of method, class, module, etc names with decoration.
179 *
180 * Consider the following example:
181 *
182 * def foo
183 * puts caller_locations(0).first.label
184 *
185 * 1.times do
186 * puts caller_locations(0).first.label
187 *
188 * 1.times do
189 * puts caller_locations(0).first.label
190 * end
191 *
192 * end
193 * end
194 *
195 * The result of calling +foo+ is this:
196 *
197 * label: foo
198 * label: block in foo
199 * label: block (2 levels) in foo
200 *
201 */
202 static VALUE
203 location_label_m(VALUE self)
204 {
205 return location_label(location_ptr(self));
206 }
207
208 static VALUE
209 location_base_label(rb_backtrace_location_t *loc)
210 {
211 switch (loc->type) {
212 case LOCATION_TYPE_ISEQ:
213 case LOCATION_TYPE_ISEQ_CALCED:
214 return loc->body.iseq.iseq->location.base_label;
215 case LOCATION_TYPE_CFUNC:
216 return rb_sym_to_s(ID2SYM(loc->body.cfunc.mid));
217 case LOCATION_TYPE_IFUNC:
218 default:
219 rb_bug("location_base_label: unreachable");
220 UNREACHABLE;
221 }
222 }
223
224 /*
225 * Returns the base label of this frame.
226 *
227 * Usually same as #label, without decoration.
228 */
229 static VALUE
230 location_base_label_m(VALUE self)
231 {
232 return location_base_label(location_ptr(self));
233 }
234
235 static VALUE
236 location_path(rb_backtrace_location_t *loc)
237 {
238 switch (loc->type) {
239 case LOCATION_TYPE_ISEQ:
240 case LOCATION_TYPE_ISEQ_CALCED:
241 return loc->body.iseq.iseq->location.path;
242 case LOCATION_TYPE_CFUNC:
243 if (loc->body.cfunc.prev_loc) {
244 return location_path(loc->body.cfunc.prev_loc);
245 }
246 return Qnil;
247 case LOCATION_TYPE_IFUNC:
248 default:
249 rb_bug("location_path: unreachable");
250 UNREACHABLE;
251 }
252 }
253
254 /*
255 * Returns the file name of this frame.
256 *
257 * For example, using +caller_locations.rb+ from Thread::Backtrace::Location
258 *
259 * loc = c(0..1).first
260 * loc.path #=> caller_locations.rb
261 */
262 static VALUE
263 location_path_m(VALUE self)
264 {
265 return location_path(location_ptr(self));
266 }
267
268 static VALUE
269 location_absolute_path(rb_backtrace_location_t *loc)
270 {
271 switch (loc->type) {
272 case LOCATION_TYPE_ISEQ:
273 case LOCATION_TYPE_ISEQ_CALCED:
274 return loc->body.iseq.iseq->location.absolute_path;
275 case LOCATION_TYPE_CFUNC:
276 if (loc->body.cfunc.prev_loc) {
277 return location_absolute_path(loc->body.cfunc.prev_loc);
278 }
279 return Qnil;
280 case LOCATION_TYPE_IFUNC:
281 default:
282 rb_bug("location_absolute_path: unreachable");
283 UNREACHABLE;
284 }
285 }
286
287 /*
288 * Returns the full file path of this frame.
289 *
290 * Same as #path, but includes the absolute path.
291 */
292 static VALUE
293 location_absolute_path_m(VALUE self)
294 {
295 return location_absolute_path(location_ptr(self));
296 }
297
298 static VALUE
299 location_format(VALUE file, int lineno, VALUE name)
300 {
301 if (lineno != 0) {
302 return rb_enc_sprintf(rb_enc_compatible(file, name), "%s:%d:in `%s'",
303 RSTRING_PTR(file), lineno, RSTRING_PTR(name));
304 }
305 else {
306 return rb_enc_sprintf(rb_enc_compatible(file, name), "%s:in `%s'",
307 RSTRING_PTR(file), RSTRING_PTR(name));
308 }
309 }
310
311 static VALUE
312 location_to_str(rb_backtrace_location_t *loc)
313 {
314 VALUE file, name;
315 int lineno;
316
317 switch (loc->type) {
318 case LOCATION_TYPE_ISEQ:
319 file = loc->body.iseq.iseq->location.path;
320 name = loc->body.iseq.iseq->location.label;
321
322 lineno = loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc);
323 loc->type = LOCATION_TYPE_ISEQ_CALCED;
324 break;
325 case LOCATION_TYPE_ISEQ_CALCED:
326 file = loc->body.iseq.iseq->location.path;
327 lineno = loc->body.iseq.lineno.lineno;
328 name = loc->body.iseq.iseq->location.label;
329 break;
330 case LOCATION_TYPE_CFUNC:
331 if (loc->body.cfunc.prev_loc) {
332 file = loc->body.cfunc.prev_loc->body.iseq.iseq->location.path;
333 lineno = location_lineno(loc->body.cfunc.prev_loc);
334 }
335 else {
336 rb_thread_t *th = GET_THREAD();
337 file = th->vm->progname ? th->vm->progname : ruby_engine_name;
338 lineno = INT2FIX(0);
339 }
340 name = rb_id2str(loc->body.cfunc.mid);
341 break;
342 case LOCATION_TYPE_IFUNC:
343 default:
344 rb_bug("location_to_str: unreachable");
345 }
346
347 return location_format(file, lineno, name);
348 }
349
350 /*
351 * Returns a Kernel#caller style string representing this frame.
352 */
353 static VALUE
354 location_to_str_m(VALUE self)
355 {
356 return location_to_str(location_ptr(self));
357 }
358
359 /*
360 * Returns the same as calling +inspect+ on the string representation of
361 * #to_str
362 */
363 static VALUE
364 location_inspect_m(VALUE self)
365 {
366 return rb_str_inspect(location_to_str(location_ptr(self)));
367 }
368
369 typedef struct rb_backtrace_struct {
370 rb_backtrace_location_t *backtrace;
371 rb_backtrace_location_t *backtrace_base;
372 int backtrace_size;
373 VALUE strary;
374 } rb_backtrace_t;
375
376 static void
377 backtrace_mark(void *ptr)
378 {
379 if (ptr) {
380 rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
381 size_t i, s = bt->backtrace_size;
382
383 for (i=0; i<s; i++) {
384 location_mark_entry(&bt->backtrace[i]);
385 rb_gc_mark(bt->strary);
386 }
387 }
388 }
389
390 static void
391 backtrace_free(void *ptr)
392 {
393 if (ptr) {
394 rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
395 if (bt->backtrace) ruby_xfree(bt->backtrace_base);
396 ruby_xfree(bt);
397 }
398 }
399
400 static size_t
401 backtrace_memsize(const void *ptr)
402 {
403 rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
404 return sizeof(rb_backtrace_t) + sizeof(rb_backtrace_location_t) * bt->backtrace_size;
405 }
406
407 static const rb_data_type_t backtrace_data_type = {
408 "backtrace",
409 {backtrace_mark, backtrace_free, backtrace_memsize,},
410 };
411
412 int
413 rb_backtrace_p(VALUE obj)
414 {
415 return rb_typeddata_is_kind_of(obj, &backtrace_data_type);
416 }
417
418 static VALUE
419 backtrace_alloc(VALUE klass)
420 {
421 rb_backtrace_t *bt;
422 VALUE obj = TypedData_Make_Struct(klass, rb_backtrace_t, &backtrace_data_type, bt);
423 return obj;
424 }
425
426 static void
427 backtrace_each(rb_thread_t *th,
428 void (*init)(void *arg, size_t size),
429 void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp),
430 void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid),
431 void *arg)
432 {
433 rb_control_frame_t *last_cfp = th->cfp;
434 rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(th);
435 rb_control_frame_t *cfp;
436 ptrdiff_t size, i;
437
438 /* <- start_cfp (end control frame)
439 * top frame (dummy)
440 * top frame (dummy)
441 * top frame <- start_cfp
442 * top frame
443 * ...
444 * 2nd frame <- lev:0
445 * current frame <- th->cfp
446 */
447
448 start_cfp =
449 RUBY_VM_NEXT_CONTROL_FRAME(
450 RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */
451
452 if (start_cfp < last_cfp) {
453 size = 0;
454 }
455 else {
456 size = start_cfp - last_cfp + 1;
457 }
458
459 init(arg, size);
460
461 /* SDR(); */
462 for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
463 /* fprintf(stderr, "cfp: %d\n", (rb_control_frame_t *)(th->stack + th->stack_size) - cfp); */
464 if (cfp->iseq) {
465 if (cfp->pc) {
466 iter_iseq(arg, cfp);
467 }
468 }
469 else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
470 ID mid = cfp->me->def ? cfp->me->def->original_id : cfp->me->called_id;
471
472 iter_cfunc(arg, cfp, mid);
473 }
474 }
475 }
476
477 struct bt_iter_arg {
478 rb_backtrace_t *bt;
479 VALUE btobj;
480 rb_backtrace_location_t *prev_loc;
481 };
482
483 static void
484 bt_init(void *ptr, size_t size)
485 {
486 struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
487 arg->btobj = backtrace_alloc(rb_cBacktrace);
488 GetCoreDataFromValue(arg->btobj, rb_backtrace_t, arg->bt);
489 arg->bt->backtrace_base = arg->bt->backtrace = ruby_xmalloc(sizeof(rb_backtrace_location_t) * size);
490 arg->bt->backtrace_size = 0;
491 }
492
493 static void
494 bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
495 {
496 const rb_iseq_t *iseq = cfp->iseq;
497 const VALUE *pc = cfp->pc;
498 struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
499 rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
500 loc->type = LOCATION_TYPE_ISEQ;
501 loc->body.iseq.iseq = iseq;
502 loc->body.iseq.lineno.pc = pc;
503 arg->prev_loc = loc;
504 }
505
506 static void
507 bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
508 {
509 struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
510 rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
511 loc->type = LOCATION_TYPE_CFUNC;
512 loc->body.cfunc.mid = mid;
513 loc->body.cfunc.prev_loc = arg->prev_loc;
514 }
515
516 static VALUE
517 backtrace_object(rb_thread_t *th)
518 {
519 struct bt_iter_arg arg;
520 arg.prev_loc = 0;
521
522 backtrace_each(th,
523 bt_init,
524 bt_iter_iseq,
525 bt_iter_cfunc,
526 &arg);
527
528 return arg.btobj;
529 }
530
531 VALUE
532 rb_vm_backtrace_object(void)
533 {
534 return backtrace_object(GET_THREAD());
535 }
536
537 static VALUE
538 backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg)
539 {
540 VALUE btary;
541 int i;
542
543 if (UNLIKELY(lev < 0 || n < 0)) {
544 rb_bug("backtrace_collect: unreachable");
545 }
546
547 btary = rb_ary_new();
548
549 for (i=0; i+lev<bt->backtrace_size && i<n; i++) {
550 rb_backtrace_location_t *loc = &bt->backtrace[bt->backtrace_size - 1 - (lev+i)];
551 rb_ary_push(btary, func(loc, arg));
552 }
553
554 return btary;
555 }
556
557 static VALUE
558 location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy)
559 {
560 return location_to_str(loc);
561 }
562
563 static VALUE
564 backtrace_to_str_ary(VALUE self, long lev, long n)
565 {
566 rb_backtrace_t *bt;
567 int size;
568 VALUE r;
569
570 GetCoreDataFromValue(self, rb_backtrace_t, bt);
571 size = bt->backtrace_size;
572
573 if (n == 0) {
574 n = size;
575 }
576 if (lev > size) {
577 return Qnil;
578 }
579
580 r = backtrace_collect(bt, lev, n, location_to_str_dmyarg, 0);
581 RB_GC_GUARD(self);
582 return r;
583 }
584
585 VALUE
586 rb_backtrace_to_str_ary(VALUE self)
587 {
588 rb_backtrace_t *bt;
589 GetCoreDataFromValue(self, rb_backtrace_t, bt);
590
591 if (!bt->strary) {
592 bt->strary = backtrace_to_str_ary(self, 0, bt->backtrace_size);
593 }
594 return bt->strary;
595 }
596
597 static VALUE
598 location_create(rb_backtrace_location_t *srcloc, void *btobj)
599 {
600 VALUE obj;
601 struct valued_frame_info *vloc;
602 obj = TypedData_Make_Struct(rb_cBacktraceLocation, struct valued_frame_info, &location_data_type, vloc);
603
604 vloc->loc = srcloc;
605 vloc->btobj = (VALUE)btobj;
606
607 return obj;
608 }
609
610 static VALUE
611 backtrace_to_location_ary(VALUE self, long lev, long n)
612 {
613 rb_backtrace_t *bt;
614 int size;
615 VALUE r;
616
617 GetCoreDataFromValue(self, rb_backtrace_t, bt);
618 size = bt->backtrace_size;
619
620 if (n == 0) {
621 n = size;
622 }
623 if (lev > size) {
624 return Qnil;
625 }
626
627 r = backtrace_collect(bt, lev, n, location_create, (void *)self);
628 RB_GC_GUARD(self);
629 return r;
630 }
631
632 static VALUE
633 backtrace_dump_data(VALUE self)
634 {
635 VALUE str = rb_backtrace_to_str_ary(self);
636 return str;
637 }
638
639 static VALUE
640 backtrace_load_data(VALUE self, VALUE str)
641 {
642 rb_backtrace_t *bt;
643 GetCoreDataFromValue(self, rb_backtrace_t, bt);
644 bt->strary = str;
645 return self;
646 }
647
648 VALUE
649 vm_backtrace_str_ary(rb_thread_t *th, long lev, long n)
650 {
651 return backtrace_to_str_ary(backtrace_object(th), lev, n);
652 }
653
654 VALUE
655 vm_backtrace_location_ary(rb_thread_t *th, long lev, long n)
656 {
657 return backtrace_to_location_ary(backtrace_object(th), lev, n);
658 }
659
660 /* make old style backtrace directly */
661
662 struct oldbt_arg {
663 VALUE filename;
664 int lineno;
665 void (*func)(void *data, VALUE file, int lineno, VALUE name);
666 void *data; /* result */
667 };
668
669 static void
670 oldbt_init(void *ptr, size_t dmy)
671 {
672 struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
673 rb_thread_t *th = GET_THREAD();
674
675 arg->filename = th->vm->progname ? th->vm->progname : ruby_engine_name;;
676 arg->lineno = 0;
677 }
678
679 static void
680 oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
681 {
682 const rb_iseq_t *iseq = cfp->iseq;
683 const VALUE *pc = cfp->pc;
684 struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
685 VALUE file = arg->filename = iseq->location.path;
686 VALUE name = iseq->location.label;
687 int lineno = arg->lineno = calc_lineno(iseq, pc);
688
689 (arg->func)(arg->data, file, lineno, name);
690 }
691
692 static void
693 oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
694 {
695 struct oldbt_arg *arg = (struct oldbt_arg *)ptr;
696 VALUE file = arg->filename;
697 VALUE name = rb_id2str(mid);
698 int lineno = arg->lineno;
699
700 (arg->func)(arg->data, file, lineno, name);
701 }
702
703 static void
704 oldbt_print(void *data, VALUE file, int lineno, VALUE name)
705 {
706 FILE *fp = (FILE *)data;
707
708 if (NIL_P(name)) {
709 fprintf(fp, "\tfrom %s:%d:in unknown method\n",
710 RSTRING_PTR(file), lineno);
711 }
712 else {
713 fprintf(fp, "\tfrom %s:%d:in `%s'\n",
714 RSTRING_PTR(file), lineno, RSTRING_PTR(name));
715 }
716 }
717
718 static void
719 vm_backtrace_print(FILE *fp)
720 {
721 struct oldbt_arg arg;
722
723 arg.func = oldbt_print;
724 arg.data = (void *)fp;
725 backtrace_each(GET_THREAD(),
726 oldbt_init,
727 oldbt_iter_iseq,
728 oldbt_iter_cfunc,
729 &arg);
730 }
731
732 static void
733 oldbt_bugreport(void *arg, VALUE file, int line, VALUE method)
734 {
735 const char *filename = NIL_P(file) ? "ruby" : RSTRING_PTR(file);
736 if (!*(int *)arg) {
737 fprintf(stderr, "-- Ruby level backtrace information "
738 "----------------------------------------\n");
739 *(int *)arg = 1;
740 }
741 if (NIL_P(method)) {
742 fprintf(stderr, "%s:%d:in unknown method\n", filename, line);
743 }
744 else {
745 fprintf(stderr, "%s:%d:in `%s'\n", filename, line, RSTRING_PTR(method));
746 }
747 }
748
749 void
750 rb_backtrace_print_as_bugreport(void)
751 {
752 struct oldbt_arg arg;
753 int i;
754
755 arg.func = oldbt_bugreport;
756 arg.data = (int *)&i;
757
758 backtrace_each(GET_THREAD(),
759 oldbt_init,
760 oldbt_iter_iseq,
761 oldbt_iter_cfunc,
762 &arg);
763 }
764
765 void
766 rb_backtrace(void)
767 {
768 vm_backtrace_print(stderr);
769 }
770
771 VALUE
772 rb_make_backtrace(void)
773 {
774 return vm_backtrace_str_ary(GET_THREAD(), 0, 0);
775 }
776
777 static VALUE
778 vm_backtrace_to_ary(rb_thread_t *th, int argc, VALUE *argv, int lev_default, int lev_plus, int to_str)
779 {
780 VALUE level, vn;
781 long lev, n;
782 VALUE btval = backtrace_object(th);
783 VALUE r;
784 rb_backtrace_t *bt;
785
786 GetCoreDataFromValue(btval, rb_backtrace_t, bt);
787
788 rb_scan_args(argc, argv, "02", &level, &vn);
789
790 if (argc == 2 && NIL_P(vn)) argc--;
791
792 switch (argc) {
793 case 0:
794 lev = lev_default + lev_plus;
795 n = bt->backtrace_size - lev;
796 break;
797 case 1:
798 {
799 long beg, len;
800 switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) {
801 case Qfalse:
802 lev = NUM2LONG(level);
803 if (lev < 0) {
804 rb_raise(rb_eArgError, "negative level (%ld)", lev);
805 }
806 lev += lev_plus;
807 n = bt->backtrace_size - lev;
808 break;
809 case Qnil:
810 return Qnil;
811 default:
812 lev = beg + lev_plus;
813 n = len;
814 break;
815 }
816 break;
817 }
818 case 2:
819 lev = NUM2LONG(level);
820 n = NUM2LONG(vn);
821 if (lev < 0) {
822 rb_raise(rb_eArgError, "negative level (%ld)", lev);
823 }
824 if (n < 0) {
825 rb_raise(rb_eArgError, "negative size (%ld)", n);
826 }
827 lev += lev_plus;
828 break;
829 default:
830 lev = n = 0; /* to avoid warning */
831 break;
832 }
833
834 if (n == 0) {
835 return rb_ary_new();
836 }
837
838 if (to_str) {
839 r = backtrace_to_str_ary(btval, lev, n);
840 }
841 else {
842 r = backtrace_to_location_ary(btval, lev, n);
843 }
844 RB_GC_GUARD(btval);
845 return r;
846 }
847
848 static VALUE
849 thread_backtrace_to_ary(int argc, VALUE *argv, VALUE thval, int to_str)
850 {
851 rb_thread_t *th;
852 GetThreadPtr(thval, th);
853
854 if (th->to_kill || th->status == THREAD_KILLED)
855 return Qnil;
856
857 return vm_backtrace_to_ary(th, argc, argv, 0, 0, to_str);
858 }
859
860 VALUE
861 vm_thread_backtrace(int argc, VALUE *argv, VALUE thval)
862 {
863 return thread_backtrace_to_ary(argc, argv, thval, 1);
864 }
865
866 VALUE
867 vm_thread_backtrace_locations(int argc, VALUE *argv, VALUE thval)
868 {
869 return thread_backtrace_to_ary(argc, argv, thval, 0);
870 }
871
872 /*
873 * call-seq:
874 * caller(start=1, length=nil) -> array or nil
875 * caller(range) -> array or nil
876 *
877 * Returns the current execution stack---an array containing strings in
878 * the form <code>file:line</code> or <code>file:line: in
879 * `method'</code>.
880 *
881 * The optional _start_ parameter determines the number of initial stack
882 * entries to omit from the top of the stack.
883 *
884 * A second optional +length+ parameter can be used to limit how many entries
885 * are returned from the stack.
886 *
887 * Returns +nil+ if _start_ is greater than the size of
888 * current execution stack.
889 *
890 * Optionally you can pass a range, which will return an array containing the
891 * entries within the specified range.
892 *
893 * def a(skip)
894 * caller(skip)
895 * end
896 * def b(skip)
897 * a(skip)
898 * end
899 * def c(skip)
900 * b(skip)
901 * end
902 * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10:in `<main>'"]
903 * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11:in `<main>'"]
904 * c(2) #=> ["prog:8:in `c'", "prog:12:in `<main>'"]
905 * c(3) #=> ["prog:13:in `<main>'"]
906 * c(4) #=> []
907 * c(5) #=> nil
908 */
909
910 static VALUE
911 rb_f_caller(int argc, VALUE *argv)
912 {
913 return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 1);
914 }
915
916 /*
917 * call-seq:
918 * caller_locations(start=1, length=nil) -> array or nil
919 * caller_locations(range) -> array or nil
920 *
921 * Returns the current execution stack---an array containing
922 * backtrace location objects.
923 *
924 * See Thread::Backtrace::Location for more information.
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 static VALUE
939 rb_f_caller_locations(int argc, VALUE *argv)
940 {
941 return vm_backtrace_to_ary(GET_THREAD(), argc, argv, 1, 1, 0);
942 }
943
944 /* called from Init_vm() in vm.c */
945 void
946 Init_vm_backtrace(void)
947 {
948 /* :nodoc: */
949 rb_cBacktrace = rb_define_class_under(rb_cThread, "Backtrace", rb_cObject);
950 rb_define_alloc_func(rb_cBacktrace, backtrace_alloc);
951 rb_undef_method(CLASS_OF(rb_cBacktrace), "new");
952 rb_marshal_define_compat(rb_cBacktrace, rb_cArray, backtrace_dump_data, backtrace_load_data);
953
954 /*
955 * An object representation of a stack frame, initialized by
956 * Kernel#caller_locations.
957 *
958 * For example:
959 *
960 * # caller_locations.rb
961 * def a(skip)
962 * caller_locations(skip)
963 * end
964 * def b(skip)
965 * a(skip)
966 * end
967 * def c(skip)
968 * b(skip)
969 * end
970 *
971 * c(0..2).map do |call|
972 * puts call.to_s
973 * end
974 *
975 * Running <code>ruby caller_locations.rb</code> will produce:
976 *
977 * caller_locations.rb:2:in `a'
978 * caller_locations.rb:5:in `b'
979 * caller_locations.rb:8:in `c'
980 *
981 * Here's another example with a slightly different result:
982 *
983 * # foo.rb
984 * class Foo
985 * attr_accessor :locations
986 * def initialize(skip)
987 * @locations = caller_locations(skip)
988 * end
989 * end
990 *
991 * Foo.new(0..2).locations.map do |call|
992 * puts call.to_s
993 * end
994 *
995 * Now run <code>ruby foo.rb</code> and you should see:
996 *
997 * init.rb:4:in `initialize'
998 * init.rb:8:in `new'
999 * init.rb:8:in `<main>'
1000 */
1001 rb_cBacktraceLocation = rb_define_class_under(rb_cBacktrace, "Location", rb_cObject);
1002 rb_undef_alloc_func(rb_cBacktraceLocation);
1003 rb_undef_method(CLASS_OF(rb_cBacktraceLocation), "new");
1004 rb_define_method(rb_cBacktraceLocation, "lineno", location_lineno_m, 0);
1005 rb_define_method(rb_cBacktraceLocation, "label", location_label_m, 0);
1006 rb_define_method(rb_cBacktraceLocation, "base_label", location_base_label_m, 0);
1007 rb_define_method(rb_cBacktraceLocation, "path", location_path_m, 0);
1008 rb_define_method(rb_cBacktraceLocation, "absolute_path", location_absolute_path_m, 0);
1009 rb_define_method(rb_cBacktraceLocation, "to_s", location_to_str_m, 0);
1010 rb_define_method(rb_cBacktraceLocation, "inspect", location_inspect_m, 0);
1011
1012 rb_define_global_function("caller", rb_f_caller, -1);
1013 rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
1014 }
1015
1016 /* debugger API */
1017
1018 #if defined __GNUC__ && __GNUC__ >= 4
1019 #pragma GCC visibility push(default)
1020 #endif
1021
1022 #if defined __GNUC__ && __GNUC__ >= 4
1023 #pragma GCC visibility pop
1024 #endif
1025
1026 struct rb_debug_inspector_struct {
1027 rb_thread_t *th;
1028 rb_control_frame_t *cfp;
1029 VALUE backtrace;
1030 VALUE contexts; /* [[klass, binding, iseq, cfp], ...] */
1031 long backtrace_size;
1032 };
1033
1034 enum {
1035 CALLER_BINDING_SELF,
1036 CALLER_BINDING_CLASS,
1037 CALLER_BINDING_BINDING,
1038 CALLER_BINDING_ISEQ,
1039 CALLER_BINDING_CFP
1040 };
1041
1042 struct collect_caller_bindings_data {
1043 VALUE ary;
1044 };
1045
1046 static void
1047 collect_caller_bindings_init(void *arg, size_t size)
1048 {
1049 /* */
1050 }
1051
1052 static VALUE
1053 get_klass(const rb_control_frame_t *cfp)
1054 {
1055 VALUE klass;
1056 if (rb_vm_control_frame_id_and_class(cfp, 0, &klass)) {
1057 if (RB_TYPE_P(klass, T_ICLASS)) {
1058 return RBASIC(klass)->klass;
1059 }
1060 else {
1061 return klass;
1062 }
1063 }
1064 else {
1065 return Qnil;
1066 }
1067 }
1068
1069 static void
1070 collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp)
1071 {
1072 struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1073 VALUE frame = rb_ary_new2(5);
1074
1075 rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1076 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1077 rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); /* create later */
1078 rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? cfp->iseq->self : Qnil);
1079 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1080
1081 rb_ary_push(data->ary, frame);
1082 }
1083
1084 static void
1085 collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
1086 {
1087 struct collect_caller_bindings_data *data = (struct collect_caller_bindings_data *)arg;
1088 VALUE frame = rb_ary_new2(5);
1089
1090 rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self);
1091 rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp));
1092 rb_ary_store(frame, CALLER_BINDING_BINDING, Qnil); /* not available */
1093 rb_ary_store(frame, CALLER_BINDING_ISEQ, Qnil); /* not available */
1094 rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp));
1095
1096 rb_ary_push(data->ary, frame);
1097 }
1098
1099 static VALUE
1100 collect_caller_bindings(rb_thread_t *th)
1101 {
1102 struct collect_caller_bindings_data data;
1103 VALUE result;
1104 int i;
1105
1106 data.ary = rb_ary_new();
1107
1108 backtrace_each(th,
1109 collect_caller_bindings_init,
1110 collect_caller_bindings_iseq,
1111 collect_caller_bindings_cfunc,
1112 &data);
1113
1114 result = rb_ary_reverse(data.ary);
1115
1116 /* bindings should be created from top of frame */
1117 for (i=0; i<RARRAY_LEN(result); i++) {
1118 VALUE entry = rb_ary_entry(result, i);
1119 VALUE cfp_val = rb_ary_entry(entry, CALLER_BINDING_BINDING);
1120
1121 if (!NIL_P(cfp_val)) {
1122 rb_control_frame_t *cfp = GC_GUARDED_PTR_REF(cfp_val);
1123 rb_ary_store(entry, CALLER_BINDING_BINDING, rb_binding_new_with_cfp(th, cfp));
1124 }
1125 }
1126
1127 return result;
1128 }
1129
1130 /*
1131 * Note that the passed `rb_debug_inspector_t' will be disabled
1132 * after `rb_debug_inspector_open'.
1133 */
1134
1135 VALUE
1136 rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
1137 {
1138 rb_debug_inspector_t dbg_context;
1139 rb_thread_t *th = GET_THREAD();
1140 int state;
1141 volatile VALUE UNINITIALIZED_VAR(result);
1142
1143 dbg_context.th = th;
1144 dbg_context.cfp = dbg_context.th->cfp;
1145 dbg_context.backtrace = vm_backtrace_location_ary(th, 0, 0);
1146 dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
1147 dbg_context.contexts = collect_caller_bindings(th);
1148
1149 TH_PUSH_TAG(th);
1150 if ((state = EXEC_TAG()) == 0) {
1151 result = (*func)(&dbg_context, data);
1152 }
1153 TH_POP_TAG();
1154
1155 /* invalidate bindings? */
1156
1157 if (state) {
1158 JUMP_TAG(state);
1159 }
1160
1161 return result;
1162 }
1163
1164 static VALUE
1165 frame_get(const rb_debug_inspector_t *dc, long index)
1166 {
1167 if (index < 0 || index >= dc->backtrace_size) {
1168 rb_raise(rb_eArgError, "no such frame");
1169 }
1170 return rb_ary_entry(dc->contexts, index);
1171 }
1172
1173 VALUE
1174 rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
1175 {
1176 VALUE frame = frame_get(dc, index);
1177 return rb_ary_entry(frame, CALLER_BINDING_SELF);
1178 }
1179
1180 VALUE
1181 rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
1182 {
1183 VALUE frame = frame_get(dc, index);
1184 return rb_ary_entry(frame, CALLER_BINDING_CLASS);
1185 }
1186
1187 VALUE
1188 rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
1189 {
1190 VALUE frame = frame_get(dc, index);
1191 return rb_ary_entry(frame, CALLER_BINDING_BINDING);
1192 }
1193
1194 VALUE
1195 rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
1196 {
1197 VALUE frame = frame_get(dc, index);
1198 return rb_ary_entry(frame, CALLER_BINDING_ISEQ);
1199 }
1200
1201 VALUE
1202 rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
1203 {
1204 return dc->backtrace;
1205 }
1206
data
VALUE data
Definition: tcltklib.c:3368
location_inspect_m
static VALUE location_inspect_m(VALUE self)
Definition: vm_backtrace.c:364
location_create
static VALUE location_create(rb_backtrace_location_t *srcloc, void *btobj)
Definition: vm_backtrace.c:598
RB_TYPE_P
#define RB_TYPE_P(obj, type)
rb_thread_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:500
bt_iter_arg
Definition: vm_backtrace.c:477
rb_thread_struct::vm
rb_vm_t * vm
Definition: vm_core.h:495
n
ssize_t n
Definition: bigdecimal.c:5655
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:1110
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
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:778
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
vm_backtrace_location_ary
VALUE vm_backtrace_location_ary(rb_thread_t *th, long lev, long n)
Definition: vm_backtrace.c:655
rb_backtrace_print_as_bugreport
void rb_backtrace_print_as_bugreport(void)
Definition: vm_backtrace.c:750
th
static VALUE VALUE th
Definition: tcltklib.c:2948
oldbt_iter_iseq
static void oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:680
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:16944
location_to_str_dmyarg
static VALUE location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy)
Definition: vm_backtrace.c:558
rb_debug_inspector_struct::backtrace_size
long backtrace_size
Definition: vm_backtrace.c:1031
iseq.h
Init_vm_backtrace
void Init_vm_backtrace(void)
Definition: vm_backtrace.c:946
ruby.h
rb_sym_to_s
VALUE rb_sym_to_s(VALUE)
Definition: string.c:7906
RUBY_VM_NORMAL_ISEQ_P
#define RUBY_VM_NORMAL_ISEQ_P(ptr)
Definition: vm_core.h:797
location_ptr
static rb_backtrace_location_t * location_ptr(VALUE locobj)
Definition: vm_backtrace.c:118
rb_vm_struct::progname
VALUE progname
Definition: vm_core.h:381
T_ICLASS
#define T_ICLASS
calc_lineno
static int calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
Definition: vm_backtrace.c:27
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
debug.h
i
ssize_t i
Definition: bigdecimal.c:5655
rb_debug_inspector_func_t
VALUE(* rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *)
Definition: debug.h:31
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:230
bt_iter_arg::btobj
VALUE btobj
Definition: vm_backtrace.c:479
rb_iseq_location_struct::path
VALUE path
Definition: vm_core.h:187
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
CALLER_BINDING_ISEQ
Definition: vm_backtrace.c:1038
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:40
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:1181
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
rb_enc_compatible
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:789
RSTRING_PTR
#define RSTRING_PTR(str)
CLASS_OF
#define CLASS_OF(v)
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
location_label_m
static VALUE location_label_m(VALUE self)
Definition: vm_backtrace.c:203
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:545
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
location_to_str
static VALUE location_to_str(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:312
CALLER_BINDING_SELF
Definition: vm_backtrace.c:1035
bt_iter_iseq
static void bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:494
rb_backtrace
void rb_backtrace(void)
Definition: vm_backtrace.c:766
rb_backtrace_to_str_ary
VALUE rb_backtrace_to_str_ary(VALUE obj)
Definition: vm_backtrace.c:586
index
int index
Definition: tcltklib.c:4478
rb_iseq_location_struct::label
VALUE label
Definition: vm_core.h:190
oldbt_iter_cfunc
static void oldbt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
Definition: vm_backtrace.c:693
rb_debug_inspector_struct
Definition: vm_backtrace.c:1026
collect_caller_bindings
static VALUE collect_caller_bindings(rb_thread_t *th)
Definition: vm_backtrace.c:1100
r
r
Definition: bigdecimal.c:1196
location_lineno
static int location_lineno(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:126
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1526
rb_backtrace_location_struct::LOCATION_TYPE_ISEQ
Definition: vm_backtrace.c:46
state
int state
Definition: tcltklib.c:1462
oldbt_arg::filename
VALUE filename
Definition: vm_backtrace.c:663
CALLER_BINDING_CFP
Definition: vm_backtrace.c:1039
rb_thread_struct
Definition: vm_core.h:493
rb_backtrace_location_struct::lineno
int lineno
Definition: vm_backtrace.c:57
ID2SYM
#define ID2SYM(x)
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1362
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:1251
rb_debug_inspector_struct::th
rb_thread_t * th
Definition: vm_backtrace.c:1027
lineno
gz lineno
Definition: zlib.c:2270
rb_f_caller_locations
static VALUE rb_f_caller_locations(int argc, VALUE *argv)
Definition: vm_backtrace.c:939
__sFILE
Definition: vsnprintf.c:175
vm_thread_backtrace
VALUE vm_thread_backtrace(int argc, VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:861
rb_backtrace_struct
Definition: vm_backtrace.c:369
rb_iseq_struct::iseq
VALUE * iseq
Definition: vm_core.h:215
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:1455
rb_control_frame_struct::self
VALUE self
Definition: vm_core.h:430
TH_POP_TAG
#define TH_POP_TAG()
Definition: eval_intern.h:101
location_absolute_path
static VALUE location_absolute_path(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:269
oldbt_arg::data
void * data
Definition: vm_backtrace.c:666
Qfalse
return Qfalse
Definition: tcltklib.c:6779
EXEC_TAG
#define EXEC_TAG()
Definition: eval_intern.h:113
RARRAY_LEN
#define RARRAY_LEN(a)
rb_cBacktraceLocation
static VALUE rb_cBacktraceLocation
Definition: vm_backtrace.c:22
Qnil
#define Qnil
Definition: tcltklib.c:1896
THREAD_KILLED
Definition: vm_core.h:459
location_path_m
static VALUE location_path_m(VALUE self)
Definition: vm_backtrace.c:263
str
static VALUE char * str
Definition: tcltklib.c:3547
thread_backtrace_to_ary
static VALUE thread_backtrace_to_ary(int argc, VALUE *argv, VALUE thval, int to_str)
Definition: vm_backtrace.c:849
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:473
valued_frame_info::btobj
VALUE btobj
Definition: vm_backtrace.c:69
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:424
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:314
ID
unsigned long ID
Definition: ripper.y:105
bt_iter_arg::bt
rb_backtrace_t * bt
Definition: vm_backtrace.c:478
backtrace_object
static VALUE backtrace_object(rb_thread_t *th)
Definition: vm_backtrace.c:517
rb_backtrace_location_struct::pc
const VALUE * pc
Definition: vm_backtrace.c:56
rb_gc_mark
void rb_gc_mark(VALUE)
Definition: gc.c:2598
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:484
JUMP_TAG
#define JUMP_TAG(st)
Definition: eval_intern.h:120
rb_control_frame_struct::iseq
rb_iseq_t * iseq
Definition: vm_core.h:428
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:115
collect_caller_bindings_iseq
static void collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:1070
oldbt_init
static void oldbt_init(void *ptr, size_t dmy)
Definition: vm_backtrace.c:670
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
INT2FIX
#define INT2FIX(i)
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:719
GetCoreDataFromValue
#define GetCoreDataFromValue(obj, type, ptr)
Definition: vm_core.h:176
collect_caller_bindings_init
static void collect_caller_bindings_init(void *arg, size_t size)
Definition: vm_backtrace.c:1047
ruby_engine_name
VALUE ruby_engine_name
Definition: version.c:67
method
volatile ID method
Definition: tcltklib.c:3599
backtrace_to_location_ary
static VALUE backtrace_to_location_ary(VALUE self, long lev, long n)
Definition: vm_backtrace.c:611
rb_backtrace_location_struct::body
union rb_backtrace_location_struct::@145 body
collect_caller_bindings_cfunc
static void collect_caller_bindings_cfunc(void *arg, const rb_control_frame_t *cfp, ID mid)
Definition: vm_backtrace.c:1085
rb_control_frame_struct
Definition: vm_core.h:425
encoding.h
CALLER_BINDING_BINDING
Definition: vm_backtrace.c:1037
vm_backtrace_str_ary
VALUE vm_backtrace_str_ary(rb_thread_t *th, long lev, long n)
Definition: vm_backtrace.c:649
GC_GUARDED_PTR
#define GC_GUARDED_PTR(p)
Definition: vm_core.h:761
level
gz level
Definition: zlib.c:2264
argv
VALUE * argv
Definition: tcltklib.c:1971
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:1174
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:538
collect_caller_bindings_data
Definition: vm_backtrace.c:1042
result
q result
Definition: tcltklib.c:7070
rb_backtrace_struct::backtrace
rb_backtrace_location_t * backtrace
Definition: vm_backtrace.c:370
location_format
static VALUE location_format(VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:299
s
register char * s
Definition: os2.c:56
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:3651
void
VP_EXPORT void
Definition: bigdecimal.c:5083
backtrace_to_str_ary
static VALUE backtrace_to_str_ary(VALUE self, long lev, long n)
Definition: vm_backtrace.c:564
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
RUBY_VM_NEXT_CONTROL_FRAME
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp)
Definition: vm_core.h:788
internal.h
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:743
rb_str_inspect
VALUE rb_str_inspect(VALUE)
Definition: string.c:4508
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:427
RB_GC_GUARD
#define RB_GC_GUARD(v)
vm_core.h
vm_thread_backtrace_locations
VALUE vm_thread_backtrace_locations(int argc, VALUE *argv, VALUE thval)
Definition: vm_backtrace.c:867
rb_iseq_struct::iseq_encoded
VALUE * iseq_encoded
Definition: vm_core.h:216
argc
int argc
Definition: tcltklib.c:1970
rb_thread_struct::to_kill
int to_kill
Definition: vm_core.h:532
rb_debug_inspector_struct::contexts
VALUE contexts
Definition: vm_backtrace.c:1030
UNINITIALIZED_VAR
#define UNINITIALIZED_VAR(x)
Definition: vm_core.h:121
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:482
vm_backtrace_print
static void vm_backtrace_print(FILE *fp)
Definition: vm_backtrace.c:719
rb_iseq_struct::location
rb_iseq_location_t location
Definition: vm_core.h:213
TH_PUSH_TAG
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:94
rb_f_caller
static VALUE rb_f_caller(int argc, VALUE *argv)
Definition: vm_backtrace.c:911
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:154
ptr
return ptr
Definition: tcltklib.c:784
RUBY_VM_END_CONTROL_FRAME
#define RUBY_VM_END_CONTROL_FRAME(th)
Definition: vm_core.h:789
rb_marshal_define_compat
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:113
rb_thread_struct::status
enum rb_thread_status status
Definition: vm_core.h:531
ruby_xmalloc
void * ruby_xmalloc(size_t size)
Definition: gc.c:3594
arg
arg
Definition: ripper.y:1315
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:640
size
int size
Definition: encoding.c:52
rb_backtrace_struct::backtrace_size
int backtrace_size
Definition: vm_backtrace.c:372
NUM2LONG
#define NUM2LONG(x)
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:1188
rb_backtrace_struct::strary
VALUE strary
Definition: vm_backtrace.c:373
oldbt_bugreport
static void oldbt_bugreport(void *arg, VALUE file, int line, VALUE method)
Definition: vm_backtrace.c:733
rb_control_frame_struct::pc
VALUE * pc
Definition: vm_core.h:426
location_path
static VALUE location_path(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:236
oldbt_arg::lineno
int lineno
Definition: vm_backtrace.c:664
location_to_str_m
static VALUE location_to_str_m(VALUE self)
Definition: vm_backtrace.c:354
rb_data_type_struct
Definition: ripper.y:960
CALLER_BINDING_CLASS
Definition: vm_backtrace.c:1036
rb_backtrace_location_struct::prev_loc
struct rb_backtrace_location_struct * prev_loc
Definition: vm_backtrace.c:62
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
RBASIC
#define RBASIC(obj)
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:665
collect_caller_bindings_data::ary
VALUE ary
Definition: vm_backtrace.c:1043
klass
klass
Definition: tcltklib.c:3504
rb_make_backtrace
VALUE rb_make_backtrace(void)
Definition: vm_backtrace.c:772
rb_backtrace_location_struct
Definition: vm_backtrace.c:44
backtrace_free
static void backtrace_free(void *ptr)
Definition: vm_backtrace.c:391
bt_iter_cfunc
static void bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
Definition: vm_backtrace.c:507
rb_cArray
VALUE rb_cArray
Definition: array.c:29
GetThreadPtr
#define GetThreadPtr(obj, ptr)
Definition: vm_core.h:452
location_base_label
static VALUE location_base_label(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:209
rb_ary_new2
VALUE rb_ary_new2(long capa)
Definition: array.c:417
rb_backtrace_p
int rb_backtrace_p(VALUE obj)
Definition: vm_backtrace.c:413
rb_backtrace_location_struct::type
enum rb_backtrace_location_struct::LOCATION_TYPE type
rb_range_beg_len
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
Definition: range.c:987
rb_iseq_struct::self
VALUE self
Definition: vm_core.h:292
rb_iseq_struct
Definition: vm_core.h:196
backtrace_alloc
static VALUE backtrace_alloc(VALUE klass)
Definition: vm_backtrace.c:419
rb_backtrace_t
struct rb_backtrace_struct rb_backtrace_t
rb_ary_reverse
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2043
location_absolute_path_m
static VALUE location_absolute_path_m(VALUE self)
Definition: vm_backtrace.c:293
rb_debug_inspector_backtrace_locations
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
Definition: vm_backtrace.c:1202
rb_debug_inspector_struct::cfp
rb_control_frame_t * cfp
Definition: vm_backtrace.c:1028
oldbt_print
static void oldbt_print(void *data, VALUE file, int lineno, VALUE name)
Definition: vm_backtrace.c:704
VALUE
unsigned long VALUE
Definition: ripper.y:104
GC_GUARDED_PTR_REF
#define GC_GUARDED_PTR_REF(p)
Definition: vm_core.h:762
frame_get
static VALUE frame_get(const rb_debug_inspector_t *dc, long index)
Definition: vm_backtrace.c:1165
get_klass
static VALUE get_klass(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:1053
rb_backtrace_struct::backtrace_base
rb_backtrace_location_t * backtrace_base
Definition: vm_backtrace.c:371
rb_debug_inspector_open
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
Definition: vm_backtrace.c:1136
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:480
location_free
static void location_free(void *ptr)
Definition: vm_backtrace.c:97
rb_vm_backtrace_object
VALUE rb_vm_backtrace_object()
Definition: vm_backtrace.c:532
backtrace_data_type
static const rb_data_type_t backtrace_data_type
Definition: vm_backtrace.c:407
backtrace_dump_data
static VALUE backtrace_dump_data(VALUE self)
Definition: vm_backtrace.c:633
rb_backtrace_location_struct::cfunc
struct rb_backtrace_location_struct::@145::@147 cfunc
name
const char * name
Definition: nkf.c:208
location_label
static VALUE location_label(rb_backtrace_location_t *loc)
Definition: vm_backtrace.c:160
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
rb_cBacktrace
static VALUE rb_cBacktrace
Definition: vm_backtrace.c:21
rb_debug_inspector_struct::backtrace
VALUE backtrace
Definition: vm_backtrace.c:1029
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
rb_cThread
RUBY_EXTERN VALUE rb_cThread
Definition: ripper.y:1459
rb_backtrace_location_struct::LOCATION_TYPE
LOCATION_TYPE
Definition: vm_backtrace.c:45
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:1195
oldbt_arg
Definition: vm_backtrace.c:662
backtrace_memsize
static size_t backtrace_memsize(const void *ptr)
Definition: vm_backtrace.c:401
len
size_t len
Definition: tcltklib.c:3568
backtrace_mark
static void backtrace_mark(void *ptr)
Definition: vm_backtrace.c:377