%PDF- %PDF-
Direktori : /opt/plesk/ruby/3.1.4/lib64/ruby/gems/3.1.0/gems/debug-1.6.3/ext/debug/ |
Current File : //opt/plesk/ruby/3.1.4/lib64/ruby/gems/3.1.0/gems/debug-1.6.3/ext/debug/debug.c |
#include "ruby/ruby.h" #include "ruby/debug.h" #include "ruby/encoding.h" #include "debug_version.h" // static VALUE rb_mDebugger; // iseq typedef struct rb_iseq_struct rb_iseq_t; VALUE rb_iseq_realpath(const rb_iseq_t *iseq); static VALUE iseq_realpath(VALUE iseqw) { rb_iseq_t *iseq = DATA_PTR(iseqw); return rb_iseq_realpath(iseq); } static VALUE rb_cFrameInfo; static VALUE di_entry(VALUE loc, VALUE self, VALUE binding, VALUE iseq, VALUE klass, VALUE depth) { return rb_struct_new(rb_cFrameInfo, // :location, :self, :binding, :iseq, :class, :frame_depth, loc, self, binding, iseq, klass, depth, // :has_return_value, :return_value, Qnil, Qnil, // :has_raised_exception, :raised_exception, Qnil, Qnil, // :show_line, :local_variables Qnil, // :_local_variables, :_callee # for recorder Qnil, Qnil, // :dupped_binding Qnil ); } static int str_start_with(VALUE str, VALUE prefix) { StringValue(prefix); rb_enc_check(str, prefix); if (RSTRING_LEN(str) >= RSTRING_LEN(prefix) && memcmp(RSTRING_PTR(str), RSTRING_PTR(prefix), RSTRING_LEN(prefix)) == 0) { return 1; } else { return 0; } } static VALUE di_body(const rb_debug_inspector_t *dc, void *ptr) { VALUE skip_path_prefix = (VALUE)ptr; VALUE locs = rb_debug_inspector_backtrace_locations(dc); VALUE ary = rb_ary_new(); long len = RARRAY_LEN(locs); long i; for (i=1; i<len; i++) { VALUE loc, e; VALUE iseq = rb_debug_inspector_frame_iseq_get(dc, i); if (!NIL_P(iseq)) { VALUE path = iseq_realpath(iseq); if (!NIL_P(path) && !NIL_P(skip_path_prefix) && str_start_with(path, skip_path_prefix)) continue; } loc = RARRAY_AREF(locs, i); e = di_entry(loc, rb_debug_inspector_frame_self_get(dc, i), rb_debug_inspector_frame_binding_get(dc, i), iseq, rb_debug_inspector_frame_class_get(dc, i), INT2FIX(len - i)); rb_ary_push(ary, e); } return ary; } static VALUE capture_frames(VALUE self, VALUE skip_path_prefix) { return rb_debug_inspector_open(di_body, (void *)skip_path_prefix); } static VALUE frame_depth(VALUE self) { // TODO: more efficient API VALUE bt = rb_make_backtrace(); return INT2FIX(RARRAY_LEN(bt)); } // iseq const struct rb_iseq *rb_iseqw_to_iseq(VALUE iseqw); #ifdef HAVE_RB_ISEQ_TYPE VALUE rb_iseq_type(const struct rb_iseq *); static VALUE iseq_type(VALUE iseqw) { const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw); return rb_iseq_type(iseq); } #endif #ifdef HAVE_RB_ISEQ_PARAMETERS VALUE rb_iseq_parameters(const struct rb_iseq *, int is_proc); static VALUE iseq_parameters_symbols(VALUE iseqw) { const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw); VALUE params = rb_iseq_parameters(iseq, 0); VALUE ary = rb_ary_new(); static VALUE sym_ast, sym_astast, sym_amp; if (sym_ast == 0) { sym_ast = ID2SYM(rb_intern("*")); sym_astast = ID2SYM(rb_intern("**")); sym_amp = ID2SYM(rb_intern("&")); } for (long i=0; i<RARRAY_LEN(params); i++) { VALUE e = RARRAY_AREF(params, i); if (RARRAY_LEN(e) == 2) { VALUE sym = RARRAY_AREF(e, 1); if (sym != sym_ast && sym != sym_astast && sym != sym_amp) rb_ary_push(ary, RARRAY_AREF(e, 1)); } } return ary; } #endif #ifdef HAVE_RB_ISEQ_CODE_LOCATION void rb_iseq_code_location(const struct rb_iseq *, int *first_lineno, int *first_column, int *last_lineno, int *last_column); static VALUE iseq_first_line(VALUE iseqw) { const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw); int line; rb_iseq_code_location(iseq, &line, NULL, NULL, NULL); return INT2NUM(line); } static VALUE iseq_last_line(VALUE iseqw) { const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw); int line; rb_iseq_code_location(iseq, NULL, NULL, &line, NULL); return INT2NUM(line); } #endif void Init_iseq_collector(void); void Init_debug(void) { VALUE rb_mRubyVM = rb_const_get(rb_cObject, rb_intern("RubyVM")); VALUE rb_cISeq = rb_const_get(rb_mRubyVM, rb_intern("InstructionSequence")); rb_mDebugger = rb_const_get(rb_cObject, rb_intern("DEBUGGER__")); rb_cFrameInfo = rb_const_get(rb_mDebugger, rb_intern("FrameInfo")); // Debugger and FrameInfo were defined in Ruby. We need to register them // as mark objects so they are automatically pinned. rb_gc_register_mark_object(rb_mDebugger); rb_gc_register_mark_object(rb_cFrameInfo); rb_define_singleton_method(rb_mDebugger, "capture_frames", capture_frames, 1); rb_define_singleton_method(rb_mDebugger, "frame_depth", frame_depth, 0); rb_define_const(rb_mDebugger, "SO_VERSION", rb_str_new2(RUBY_DEBUG_VERSION)); // iseq #ifdef HAVE_RB_ISEQ_TYPE rb_define_method(rb_cISeq, "type", iseq_type, 0); #endif #ifdef HAVE_RB_ISEQ_PARAMETERS rb_define_method(rb_cISeq, "parameters_symbols", iseq_parameters_symbols, 0); #endif #ifdef HAVE_RB_ISEQ_CODE_LOCATION rb_define_method(rb_cISeq, "first_line", iseq_first_line, 0); rb_define_method(rb_cISeq, "last_line", iseq_last_line, 0); #endif Init_iseq_collector(); }