20static VALUE rb_cBacktrace;
21static VALUE rb_cBacktraceLocation;
30#define rb_id2str(id) id2str(id)
32#define BACKTRACE_START 0
33#define ALL_BACKTRACE_LINES -1
59#if VMDEBUG && defined(HAVE_BUILTIN___BUILTIN_TRAP)
73 if (VM_FRAME_RUBYFRAME_P(cfp) && cfp->
iseq) {
75 int line = calc_lineno(iseq, cfp->
pc);
116location_mark(
void *
ptr)
126 case LOCATION_TYPE_ISEQ:
127 case LOCATION_TYPE_ISEQ_CALCED:
130 case LOCATION_TYPE_CFUNC:
137location_memsize(
const void *
ptr)
150location_ptr(
VALUE locobj)
161 case LOCATION_TYPE_ISEQ:
162 loc->
type = LOCATION_TYPE_ISEQ_CALCED;
164 case LOCATION_TYPE_ISEQ_CALCED:
166 case LOCATION_TYPE_CFUNC:
172 rb_bug(
"location_lineno: unreachable");
186location_lineno_m(
VALUE self)
188 return INT2FIX(location_lineno(location_ptr(self)));
195 case LOCATION_TYPE_ISEQ:
196 case LOCATION_TYPE_ISEQ_CALCED:
198 case LOCATION_TYPE_CFUNC:
201 rb_bug(
"location_label: unreachable");
234location_label_m(
VALUE self)
236 return location_label(location_ptr(self));
243 case LOCATION_TYPE_ISEQ:
244 case LOCATION_TYPE_ISEQ_CALCED:
246 case LOCATION_TYPE_CFUNC:
249 rb_bug(
"location_base_label: unreachable");
260location_base_label_m(
VALUE self)
262 return location_base_label(location_ptr(self));
269 case LOCATION_TYPE_ISEQ:
270 case LOCATION_TYPE_ISEQ_CALCED:
272 case LOCATION_TYPE_CFUNC:
278 rb_bug(
"location_path: unreachable");
294location_path_m(
VALUE self)
296 return location_path(location_ptr(self));
303 case LOCATION_TYPE_ISEQ:
304 case LOCATION_TYPE_ISEQ_CALCED:
306 case LOCATION_TYPE_CFUNC:
312 rb_bug(
"location_realpath: unreachable");
324location_absolute_path_m(
VALUE self)
326 return location_realpath(location_ptr(self));
353 case LOCATION_TYPE_ISEQ:
358 loc->
type = LOCATION_TYPE_ISEQ_CALCED;
360 case LOCATION_TYPE_ISEQ_CALCED:
365 case LOCATION_TYPE_CFUNC:
371 file = GET_VM()->progname;
377 rb_bug(
"location_to_str: unreachable");
380 return location_format(
file, lineno,
name);
387location_to_str_m(
VALUE self)
389 return location_to_str(location_ptr(self));
397location_inspect_m(
VALUE self)
410backtrace_mark(
void *
ptr)
415 for (i=0; i<s; i++) {
423backtrace_free(
void *
ptr)
434 case LOCATION_TYPE_ISEQ:
435 case LOCATION_TYPE_ISEQ_CALCED:
438 case LOCATION_TYPE_CFUNC:
445backtrace_update(
void *
ptr)
450 for (i=0; i<s; i++) {
451 location_update_entry(&bt->
backtrace[i]);
458backtrace_memsize(
const void *
ptr)
466 {backtrace_mark, backtrace_free, backtrace_memsize, backtrace_update},
477backtrace_alloc(
VALUE klass)
490 if (start_cfp ==
NULL) {
498 if (start_cfp < last_cfp) {
502 return start_cfp - last_cfp + 1;
512 void (*init)(
void *arg,
size_t size),
521 ptrdiff_t
size, real_size, i, j,
last, start = 0;
525 if (start_cfp ==
NULL) {
544 if (start_cfp < last_cfp) {
549 for(; from_last > 0 && start_cfp >= last_cfp; from_last--) {
550 if (last_cfp->
iseq && !last_cfp->
pc) {
556 real_size =
size = start_cfp - last_cfp + 1;
558 if (from_last >
size) {
562 else if (num_frames >= 0 && num_frames <
size) {
563 if (from_last + num_frames >
size) {
568 start =
size - from_last - num_frames;
591 if (start > 0 && num_frames >= 0 && num_frames < real_size) {
592 int found_frames = 0, total_frames = 0;
593 bool last_frame_cfunc =
FALSE;
603 if (iter_skip && (last_frame_cfunc || iter_skip == bt_iter_skip_skip_internal)) {
605 if (cfp->
iseq && cfp->
pc && (iter_skip != bt_iter_skip_skip_internal || !is_internal_location(cfp))) {
613 real_size = total_frames;
615 start_cfp = new_start_cfp;
638 iter_cfunc(arg, cfp, mid);
656 static const char prefix[] =
"<internal:";
657 const size_t prefix_len =
sizeof(
prefix) - 1;
666 arg->
btobj = backtrace_alloc(rb_cBacktrace);
681 loc->
type = LOCATION_TYPE_ISEQ;
693 if (!is_internal_location(cfp)) {
694 loc->
type = LOCATION_TYPE_ISEQ;
699 loc->
type = LOCATION_TYPE_ISEQ;
704 rb_bug(
"No non-internal backtrace entry before an <internal: backtrace entry");
713 loc->
type = LOCATION_TYPE_CFUNC;
733 if (cfp->
iseq && cfp->
pc) {
741 if (cfp->
iseq && cfp->
pc) {
742 if (!is_internal_location(cfp)) {
749rb_ec_partial_backtrace_object(
const rb_execution_context_t *ec,
long lev,
long n,
int* level_too_large,
bool skip_internal)
755 too_large = backtrace_each(ec,
759 skip_internal ? bt_iter_iseq_skip_internal : bt_iter_iseq,
761 skip_internal ? bt_iter_skip_skip_internal : bt_iter_skip,
764 if (level_too_large) *level_too_large = too_large;
794 return location_to_str(loc);
798backtrace_to_str_ary(
VALUE self)
803 r = backtrace_collect(
bt, location_to_str_dmyarg, 0);
815 bt->
strary = backtrace_to_str_ary(self);
836 loc->
type = LOCATION_TYPE_ISEQ_CALCED;
853backtrace_to_location_ary(
VALUE self)
858 r = backtrace_collect(bt, location_create, (
void *)self);
870 bt->
locary = backtrace_to_location_ary(self);
876backtrace_dump_data(
VALUE self)
894 return backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n,
NULL,
FALSE));
900 return backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n,
NULL, skip_internal));
913oldbt_init(
void *
ptr,
size_t dmy)
950 fprintf(fp,
"\tfrom %s:%d:in unknown method\n",
954 fprintf(fp,
"\tfrom %s:%d:in `%s'\n",
960vm_backtrace_print(
FILE *fp)
964 arg.
func = oldbt_print;
965 arg.
data = (
void *)fp;
966 backtrace_each(GET_EC(),
981 fprintf(stderr,
"-- Ruby level backtrace information "
982 "----------------------------------------\n");
986 fprintf(stderr,
"%s:%d:in unknown method\n",
filename, line);
999 arg.
func = oldbt_bugreport;
1000 arg.
data = (
int *)&i;
1002 backtrace_each(GET_EC(),
1015 vm_backtrace_print(stderr);
1046 arg.
func = oldbt_print_to;
1048 backtrace_each(GET_EC(),
1079 lev = lev_default + lev_plus;
1084 long beg,
len, bt_size = backtrace_size(ec);
1097 lev = beg + lev_plus;
1123 btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large,
FALSE);
1130 r = backtrace_to_str_ary(btval);
1133 r = backtrace_to_location_ary(btval);
1147 return ec_backtrace_to_ary(target_th->
ec,
argc,
argv, 0, 0, to_str);
1153 return thread_backtrace_to_ary(
argc,
argv, thval, 1);
1159 return thread_backtrace_to_ary(
argc,
argv, thval, 0);
1164 return ec_backtrace_to_ary(ec,
argc,
argv, 0, 0, 1);
1169 return ec_backtrace_to_ary(ec,
argc,
argv, 0, 0, 0);
1213 return ec_backtrace_to_ary(GET_EC(),
argc,
argv, 1, 1, 1);
1241 return ec_backtrace_to_ary(GET_EC(),
argc,
argv, 1, 1, 0);
1306 rb_define_method(rb_cBacktraceLocation,
"base_label", location_base_label_m, 0);
1308 rb_define_method(rb_cBacktraceLocation,
"absolute_path", location_absolute_path_m, 0);
1318RUBY_SYMBOL_EXPORT_BEGIN
1320RUBY_SYMBOL_EXPORT_END
1343collect_caller_bindings_init(
void *arg,
size_t size)
1354 return RBASIC(klass)->klass;
1407 collect_caller_bindings_init,
1408 collect_caller_bindings_iseq,
1409 collect_caller_bindings_cfunc,
1420 if (!
NIL_P(cfp_val)) {
1445 dbg_context.
ec = ec;
1446 dbg_context.
cfp = dbg_context.
ec->
cfp;
1449 dbg_context.
contexts = collect_caller_bindings(ec);
1453 result = (*func)(&dbg_context, data);
1478 VALUE frame = frame_get(dc, index);
1485 VALUE frame = frame_get(dc, index);
1492 VALUE frame = frame_get(dc, index);
1499 VALUE frame = frame_get(dc, index);
1519 for (i=0; i<limit && cfp != end_cfp;) {
1520 if (VM_FRAME_RUBYFRAME_P(cfp)) {
1529 buff[i] = (
VALUE)cme;
1535 if (lines) lines[i] = calc_lineno(cfp->
iseq, cfp->
pc);
1542 buff[i] = (
VALUE)cme;
1543 if (lines) lines[i] = 0;
1554frame2iseq(
VALUE frame)
1558 if (RB_TYPE_P(frame,
T_IMEMO)) {
1565 switch (cme->
def->type) {
1576 rb_bug(
"frame2iseq: unreachable");
1582 const rb_iseq_t *iseq = frame2iseq(frame);
1591 if (RB_TYPE_P(frame,
T_IMEMO)) {
1596 switch (cme->
def->type) {
1614 if (cframe(frame)) {
1622 const rb_iseq_t *iseq = frame2iseq(frame);
1629 const rb_iseq_t *iseq = frame2iseq(frame);
1636 const rb_iseq_t *iseq = frame2iseq(frame);
1643 const rb_iseq_t *iseq = frame2iseq(frame);
1648frame2klass(
VALUE frame)
1652 if (RB_TYPE_P(frame,
T_IMEMO)) {
1665 VALUE klass = frame2klass(frame);
1667 if (klass && !
NIL_P(klass)) {
1669 klass =
RBASIC(klass)->klass;
1686 VALUE klass = frame2klass(frame);
1704 const rb_iseq_t *iseq = frame2iseq(frame);
1709qualified_method_name(
VALUE frame,
VALUE method_name)
1711 if (method_name !=
Qnil) {
1715 if (classpath !=
Qnil) {
1717 classpath, singleton_p ==
Qtrue ?
"." :
"#", method_name);
1733 return qualified_method_name(frame, method_name);
1742 VALUE method_name = id2str(mid);
1743 return qualified_method_name(frame, method_name);
1750 if (
NIL_P(qualified_method_name) || base_label == qualified_method_name) {
1756 int prefix_len =
rb_long2int(label_length - base_label_length);
void rb_ary_store(VALUE ary, long idx, VALUE val)
VALUE rb_ary_reverse(VALUE ary)
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_ary_entry(VALUE ary, long offset)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
VALUE(* rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *)
#define MJIT_FUNC_EXPORTED
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
char str[HTML_ESCAPE_MAX_LEN+1]
#define EC_JUMP_TAG(ec, st)
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void ruby_xfree(void *x)
Deallocates a storage instance.
VALUE rb_gc_location(VALUE value)
void rb_gc_mark_movable(VALUE ptr)
void rb_gc_mark(VALUE ptr)
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_undef_method(VALUE klass, const char *name)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
void rb_raise(VALUE exc, const char *fmt,...)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
void rb_bug(const char *fmt,...)
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal)
VALUE rb_iseqw_new(const rb_iseq_t *)
VALUE rb_cObject
Object class.
VALUE rb_obj_class(VALUE)
unsigned short prefix[65536]
VALUE rb_enc_sprintf(rb_encoding *, const char *,...)
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
#define rb_str_new_literal(str)
VALUE rb_str_inspect(VALUE)
#define rb_str_cat_cstr(buf, str)
VALUE rb_ivar_get(VALUE, ID)
VALUE rb_class_path(VALUE)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void rb_undef_alloc_func(VALUE)
Internal header for RubyVM.
void rb_print_backtrace(void)
VALUE rb_iseq_path(const rb_iseq_t *iseq)
unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
VALUE rb_iseq_label(const rb_iseq_t *iseq)
VALUE rb_iseq_base_label(const rb_iseq_t *iseq)
VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq)
VALUE rb_iseq_method_name(const rb_iseq_t *iseq)
VALUE rb_iseq_realpath(const rb_iseq_t *iseq)
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
@ VM_METHOD_TYPE_ISEQ
Ruby method.
@ VM_METHOD_TYPE_CFUNC
C method.
#define RUBY_TYPED_DEFAULT_FREE
@ RUBY_TYPED_FREE_IMMEDIATELY
#define TypedData_Make_Struct(klass, type, data_type, sval)
const char * rb_class2name(VALUE)
VALUE rb_str_catf(VALUE, const char *,...)
VALUE rb_sprintf(const char *,...)
rb_backtrace_location_t * init_loc
const rb_control_frame_t * prev_cfp
rb_backtrace_location_t * prev_loc
void(* func)(void *data, VALUE file, int lineno, VALUE name)
VALUE(* iter)(VALUE recv, VALUE str)
@ LOCATION_TYPE_ISEQ_CALCED
struct rb_backtrace_location_struct * prev_loc
struct rb_backtrace_location_struct::@180::@182 cfunc
enum rb_backtrace_location_struct::LOCATION_TYPE type
union rb_backtrace_location_struct::@180 body
rb_backtrace_location_t * backtrace
const VALUE defined_class
struct rb_method_definition_struct *const def
rb_execution_context_t * ec
enum rb_iseq_constant_body::iseq_type type
unsigned int local_table_size
rb_iseq_location_t location
struct rb_iseq_constant_body * body
union rb_method_definition_struct::@123 body
rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
rb_execution_context_t * ec
rb_backtrace_location_t * loc
void rb_vm_stack_to_heap(rb_execution_context_t *ec)
VALUE rb_vm_make_binding(const rb_execution_context_t *ec, const rb_control_frame_t *src_cfp)
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp)
int rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
VALUE rb_profile_frame_full_label(VALUE frame)
VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index)
void rb_backtrace_each(VALUE(*iter)(VALUE recv, VALUE str), VALUE output)
VALUE rb_vm_backtrace_locations(int argc, const VALUE *argv, struct rb_execution_context_struct *ec)
struct rb_backtrace_location_struct rb_backtrace_location_t
struct rb_backtrace_struct rb_backtrace_t
VALUE rb_profile_frame_method_name(VALUE frame)
VALUE rb_vm_backtrace(int argc, const VALUE *argv, struct rb_execution_context_struct *ec)
VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec)
VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n)
VALUE rb_profile_frame_qualified_method_name(VALUE frame)
VALUE rb_profile_frame_label(VALUE frame)
void rb_backtrace_print_as_bugreport(void)
void Init_vm_backtrace(void)
VALUE rb_profile_frame_singleton_method_p(VALUE frame)
VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
VALUE rb_profile_frame_absolute_path(VALUE frame)
VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
int rb_backtrace_p(VALUE obj)
VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval)
VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index)
#define ALL_BACKTRACE_LINES
void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self)
VALUE rb_backtrace_to_location_ary(VALUE self)
VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index)
VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index)
VALUE rb_profile_frame_classpath(VALUE frame)
VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
VALUE rb_profile_frame_path(VALUE frame)
VALUE rb_profile_frame_first_lineno(VALUE frame)
VALUE rb_make_backtrace(void)
VALUE rb_backtrace_to_str_ary(VALUE self)
VALUE rb_profile_frame_base_label(VALUE frame)
const rb_callable_method_entry_t * rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
#define GC_GUARDED_PTR_REF(p)
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp)
#define GC_GUARDED_PTR(p)
#define GetCoreDataFromValue(obj, type, ptr)
#define RUBYVM_CFUNC_FRAME_P(cfp)
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)