From 85493d75a76b75bc3fb79d1569e5128903d15d42 Mon Sep 17 00:00:00 2001 From: ViugiNick Date: Mon, 18 Jun 2018 19:31:06 +0300 Subject: [PATCH] monkeypatch load_iseq for debugger to work along with bootsnap (#61) * monkey patch InstructionSequence#load_iseq to set tracing flags * workaround for ruby versions older than 2.5.0 --- ext/attach/extconf.rb | 8 +++++++- ext/debase_internals.c | 31 +++++++++++++++++++++++++++++++ ext/debase_internals.h | 7 ++++++- ext/extconf.rb | 9 +++++++-- lib/debase.rb | 31 ++++++++++++++++++++++++++++++- lib/debase/version.rb | 2 +- 6 files changed, 82 insertions(+), 6 deletions(-) diff --git a/ext/attach/extconf.rb b/ext/attach/extconf.rb index 9a22e55..fc91000 100644 --- a/ext/attach/extconf.rb +++ b/ext/attach/extconf.rb @@ -28,7 +28,13 @@ require "debase/ruby_core_source" hdrs = proc { - have_header("vm_core.h") + have_header("vm_core.h") and + have_header("iseq.h") and + have_header("version.h") and + have_header("vm_core.h") and + have_header("vm_insnhelper.h") and + have_header("vm_core.h") and + have_header("method.h") } # Allow use customization of compile options. For example, the diff --git a/ext/debase_internals.c b/ext/debase_internals.c index 20670d9..7dc3cf6 100644 --- a/ext/debase_internals.c +++ b/ext/debase_internals.c @@ -637,6 +637,36 @@ Debase_enable_file_filtering(VALUE self, VALUE value) return value; } +#if RUBY_API_VERSION_CODE >= 20500 + static const rb_iseq_t * + my_iseqw_check(VALUE iseqw) + { + rb_iseq_t *iseq = DATA_PTR(iseqw); + + if (!iseq->body) { + ibf_load_iseq_complete(iseq); + } + + if (!iseq->body->location.label) { + rb_raise(rb_eTypeError, "uninitialized InstructionSequence"); + } + return iseq; + } + + static void + Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) + { + if (!SPECIAL_CONST_P(rb_iseq) && RBASIC_CLASS(rb_iseq) == rb_cISeq) { + rb_iseq_t *iseq = my_iseqw_check(rb_iseq); + rb_iseq_trace_set(iseq, RUBY_EVENT_TRACEPOINT_ALL); + } + } +#else + static void + Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) { + } +#endif + static VALUE Debase_init_variables() { @@ -680,6 +710,7 @@ Init_debase_internals() rb_define_module_function(mDebase, "enable_trace_points", Debase_enable_trace_points, 0); rb_define_module_function(mDebase, "prepare_context", Debase_prepare_context, 0); rb_define_module_function(mDebase, "init_variables", Debase_init_variables, 0); + rb_define_module_function(mDebase, "set_trace_flag_to_iseq", Debase_set_trace_flag_to_iseq, 1); idAlive = rb_intern("alive?"); idAtLine = rb_intern("at_line"); diff --git a/ext/debase_internals.h b/ext/debase_internals.h index 3caf07a..d6fc480 100644 --- a/ext/debase_internals.h +++ b/ext/debase_internals.h @@ -1,7 +1,12 @@ #ifndef DEBASE_INTERNALS #define DEBASE_INTERNALS -#include +#include "ruby.h" +#include "vm_core.h" +#include "version.h" +#include "iseq.h" +#include "vm_insnhelper.h" +#include "method.h" #include typedef struct rb_trace_arg_struct rb_trace_point_t; diff --git a/ext/extconf.rb b/ext/extconf.rb index 31a1752..3c41372 100644 --- a/ext/extconf.rb +++ b/ext/extconf.rb @@ -28,8 +28,13 @@ require "debase/ruby_core_source" hdrs = proc { - have_header("vm_core.h") - have_header("version.h") + have_header("vm_core.h") and + have_header("iseq.h") and + have_header("version.h") and + have_header("vm_core.h") and + have_header("vm_insnhelper.h") and + have_header("vm_core.h") and + have_header("method.h") } # Allow use customization of compile options. For example, the diff --git a/lib/debase.rb b/lib/debase.rb index 4fbff96..d28bf1f 100644 --- a/lib/debase.rb +++ b/lib/debase.rb @@ -20,7 +20,21 @@ def start(options={}, &block) Debugger.const_set('ARGV', ARGV.clone) unless defined? Debugger::ARGV Debugger.const_set('PROG_SCRIPT', $0) unless defined? Debugger::PROG_SCRIPT Debugger.const_set('INITIAL_DIR', Dir.pwd) unless defined? Debugger::INITIAL_DIR - return Debugger.started? ? block && block.call(self) : Debugger.start_(&block) + + monkey_patch_prepend + + Debugger.started? ? block && block.call(self) : Debugger.start_(&block) + end + + def monkey_patch_prepend + class << RubyVM::InstructionSequence + def self.prepend(mod, *smth) + super + if mod.to_s.include? 'Bootsnap' + prepend InstructionSequenceMixin + end + end + end end # @param [String] file @@ -81,6 +95,21 @@ def last_context def file_filter @file_filter ||= FileFilter.new end + + module InstructionSequenceMixin + def load_iseq(path) + iseq = super(path) + + do_set_flags(iseq) + + iseq + end + + def do_set_flags(iseq) + Debugger.set_trace_flag_to_iseq(iseq) + iseq.each_child{|child_iseq| do_set_flags(child_iseq)} + end + end end class FileFilter diff --git a/lib/debase/version.rb b/lib/debase/version.rb index bf217a5..86243af 100644 --- a/lib/debase/version.rb +++ b/lib/debase/version.rb @@ -1,3 +1,3 @@ module Debase - VERSION = "0.2.3.beta1" unless defined? VERSION + VERSION = "0.2.3.beta2" unless defined? VERSION end