debase 0.2.2 → 0.2.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d9fb180b5086361e7572b01988d7b09a02cab4f3
4
- data.tar.gz: ad2bed6b9d52476544c9d2bc9683c954ef7907ec
2
+ SHA256:
3
+ metadata.gz: 107e62228760d4c312c185830e9b6c152814c02b2f85d94a094c44e6687402b8
4
+ data.tar.gz: 740ccb46f3bb6e97d60afd38e90c6d9cb3be58f0a29c66efc44f0e06d18acec8
5
5
  SHA512:
6
- metadata.gz: b4bbb5c1d47aa70a2cbda6428e5a8720d128a476a259b462db72b668090c0b75b34b84f5bd0daa16459a68e4a42126e29aafb465ab4cc35248d758d876f8c9d9
7
- data.tar.gz: 287b789b0fb345c5db12a719c9839208aeb851741cb0d8a72319e460c547b002377b38807e43adacc49f530a8bb8db73570282ec7109961309d3b9bf4baf65e2
6
+ metadata.gz: 6ade635981299fee6a15e4e353c66db86f6afe14ae5c1a3e6f364a7936cec11f21f32ce4527d249d89738a573106a80be861b63ff334d591ef29adf6bdbcc5f0
7
+ data.tar.gz: a9c840b6868a842f94f4402a4161115b703522c9a29ff5bb3b09ab2025fcff451b3bb912858d413bfb673eb2a994c989498fe08cef062cd04db44c68f4d5ad54
@@ -10,7 +10,8 @@ rvm:
10
10
  - 2.2
11
11
  - 2.3
12
12
  - 2.4.2
13
- - 2.5.0
13
+ - 2.5.3
14
+ - 2.6.0
14
15
  - ruby-head
15
16
 
16
17
  matrix:
@@ -28,7 +28,13 @@ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
28
28
  require "debase/ruby_core_source"
29
29
 
30
30
  hdrs = proc {
31
- have_header("vm_core.h")
31
+ have_header("vm_core.h") and
32
+ have_header("iseq.h") and
33
+ have_header("version.h") and
34
+ have_header("vm_core.h") and
35
+ have_header("vm_insnhelper.h") and
36
+ have_header("vm_core.h") and
37
+ have_header("method.h")
32
38
  }
33
39
 
34
40
  # Allow use customization of compile options. For example, the
@@ -135,7 +135,6 @@ Context_mark(debug_context_t *context)
135
135
 
136
136
  static void
137
137
  Context_free(debug_context_t *context) {
138
- xfree(context->init_stack_files);
139
138
  xfree(context);
140
139
  }
141
140
 
@@ -143,25 +142,12 @@ extern VALUE
143
142
  context_create(VALUE thread, VALUE cDebugThread) {
144
143
  debug_context_t *context;
145
144
  VALUE locations;
146
- VALUE location;
147
- VALUE path;
148
- VALUE lineno;
149
145
 
150
146
  context = ALLOC(debug_context_t);
151
147
  context->stack_size = 0;
152
148
  locations = rb_funcall(thread, rb_intern("backtrace_locations"), 1, INT2FIX(1));
153
- context->init_stack_size = context->calced_stack_size = locations != Qnil ? RARRAY_LENINT(locations) : 0;
154
-
155
- context->init_stack_files = ruby_xmalloc2((context->init_stack_size),sizeof(char*));
156
-
157
- int i;
158
- for (i = 0; i < context->init_stack_size; i++) {
159
- location = rb_ary_entry(locations, i);
160
- path = rb_funcall(location, rb_intern("path"), 0);
161
- lineno = rb_funcall(location, rb_intern("lineno"), 0);
162
- context->init_stack_files[i] = path != Qnil ? RSTRING_PTR(path) : "";
163
- }
164
-
149
+ context->calced_stack_size = locations != Qnil ? RARRAY_LENINT(locations) : 0;
150
+ context->init_stack_size = -1;
165
151
 
166
152
  context->stack = NULL;
167
153
  context->thnum = ++thnum_current;
@@ -169,6 +155,8 @@ context_create(VALUE thread, VALUE cDebugThread) {
169
155
  context->flags = 0;
170
156
  context->last_file = NULL;
171
157
  context->last_line = -1;
158
+ context->hit_user_code = 0;
159
+ context->script_finished = 0;
172
160
  context->stop_frame = -1;
173
161
  context->thread_pause = 0;
174
162
  context->stop_reason = CTX_STOP_NONE;
@@ -303,6 +303,8 @@ remove_pause_flag(VALUE thread, VALUE context_object, VALUE ignored)
303
303
  static void
304
304
  call_at_line(debug_context_t *context, char *file, int line, VALUE context_object)
305
305
  {
306
+ context->hit_user_code = 1;
307
+
306
308
  rb_hash_foreach(contexts, remove_pause_flag, 0);
307
309
  CTX_FL_UNSET(context, CTX_FL_STEPPED);
308
310
  CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
@@ -311,6 +313,35 @@ call_at_line(debug_context_t *context, char *file, int line, VALUE context_objec
311
313
  rb_funcall(context_object, idAtLine, 2, rb_str_new2(file), INT2FIX(line));
312
314
  }
313
315
 
316
+ int count_stack_size() {
317
+ rb_thread_t *thread = ruby_current_thread;
318
+ rb_control_frame_t *last_cfp = TH_CFP(thread);
319
+ rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(TH_INFO(thread));
320
+ rb_control_frame_t *cfp;
321
+
322
+ ptrdiff_t size, i;
323
+
324
+ start_cfp =
325
+ RUBY_VM_NEXT_CONTROL_FRAME(
326
+ RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */
327
+
328
+ if (start_cfp < last_cfp) {
329
+ size = 0;
330
+ }
331
+ else {
332
+ size = start_cfp - last_cfp + 1;
333
+ }
334
+
335
+ int stack_size = 0;
336
+ for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
337
+ if (cfp->iseq && cfp->pc) {
338
+ stack_size++;
339
+ }
340
+ }
341
+
342
+ return stack_size;
343
+ }
344
+
314
345
  static void
315
346
  process_line_event(VALUE trace_point, void *data)
316
347
  {
@@ -323,7 +354,6 @@ process_line_event(VALUE trace_point, void *data)
323
354
  char *file;
324
355
  int line;
325
356
  int moved;
326
- int not_user_code = 0;
327
357
 
328
358
  context_object = Debase_current_context(mDebase);
329
359
  Data_Get_Struct(context_object, debug_context_t, context);
@@ -338,19 +368,14 @@ process_line_event(VALUE trace_point, void *data)
338
368
  file = RSTRING_PTR(path);
339
369
  line = FIX2INT(lineno);
340
370
 
341
- int i;
342
- if(context->calced_stack_size < context->init_stack_size) {
343
- for(i = 0; i < context->init_stack_size; i++)
344
- {
345
- if(strcmp(file, context->init_stack_files[i]) == 0) {
346
- not_user_code = 1;
347
- }
348
- }
349
- }
350
-
351
371
  update_stack_size(context);
352
372
  print_event(tp, context);
353
373
 
374
+ if(context->init_stack_size == -1) {
375
+ context->stack_size = count_stack_size();
376
+ context->init_stack_size = context->stack_size;
377
+ }
378
+
354
379
  if (context->thread_pause) {
355
380
  context->stop_next = 1;
356
381
  context->dest_frame = -1;
@@ -384,15 +409,20 @@ process_line_event(VALUE trace_point, void *data)
384
409
  }
385
410
 
386
411
  breakpoint = breakpoint_find(breakpoints, path, lineno, trace_point);
387
- if (not_user_code == 0 && (context->stop_next == 0 || context->stop_line == 0 || breakpoint != Qnil)) {
412
+ if (context->stop_next == 0 || context->stop_line == 0 || breakpoint != Qnil) {
388
413
  rb_ensure(start_inspector, context_object, stop_inspector, Qnil);
389
- context->stop_reason = CTX_STOP_STEP;
390
- if (breakpoint != Qnil) {
391
- context->stop_reason = CTX_STOP_BREAKPOINT;
392
- rb_funcall(context_object, idAtBreakpoint, 1, breakpoint);
414
+ if(context->stack_size <= context->init_stack_size && context->hit_user_code) {
415
+ context->script_finished = 1;
416
+ }
417
+ if(!context->script_finished) {
418
+ context->stop_reason = CTX_STOP_STEP;
419
+ if (breakpoint != Qnil) {
420
+ context->stop_reason = CTX_STOP_BREAKPOINT;
421
+ rb_funcall(context_object, idAtBreakpoint, 1, breakpoint);
422
+ }
423
+ reset_stepping_stop_points(context);
424
+ call_at_line(context, file, line, context_object);
393
425
  }
394
- reset_stepping_stop_points(context);
395
- call_at_line(context, file, line, context_object);
396
426
  }
397
427
  }
398
428
  cleanup(context);
@@ -648,6 +678,50 @@ Debase_enable_file_filtering(VALUE self, VALUE value)
648
678
  return value;
649
679
  }
650
680
 
681
+ #if RUBY_API_VERSION_CODE >= 20500 && RUBY_API_VERSION_CODE < 20600 && !(RUBY_RELEASE_YEAR == 2017 && RUBY_RELEASE_MONTH == 10 && RUBY_RELEASE_DAY == 10)
682
+ static const rb_iseq_t *
683
+ my_iseqw_check(VALUE iseqw)
684
+ {
685
+ rb_iseq_t *iseq = DATA_PTR(iseqw);
686
+
687
+ if (!iseq->body) {
688
+ return NULL;
689
+ }
690
+
691
+ return iseq;
692
+ }
693
+
694
+ static void
695
+ Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) {
696
+ if (!SPECIAL_CONST_P(rb_iseq) && RBASIC_CLASS(rb_iseq) == rb_cISeq) {
697
+ rb_iseq_t *iseq = my_iseqw_check(rb_iseq);
698
+
699
+ if(iseq) {
700
+ rb_iseq_trace_set(iseq, RUBY_EVENT_TRACEPOINT_ALL);
701
+ }
702
+ }
703
+ }
704
+
705
+ static void
706
+ Debase_unset_trace_flags(VALUE self, VALUE rb_iseq) {
707
+ if (!SPECIAL_CONST_P(rb_iseq) && RBASIC_CLASS(rb_iseq) == rb_cISeq) {
708
+ rb_iseq_t *iseq = my_iseqw_check(rb_iseq);
709
+
710
+ if(iseq) {
711
+ rb_iseq_trace_set(iseq, RUBY_EVENT_NONE);
712
+ }
713
+ }
714
+ }
715
+ #else
716
+ static void
717
+ Debase_set_trace_flag_to_iseq(VALUE self, VALUE rb_iseq) {
718
+ }
719
+
720
+ static void
721
+ Debase_unset_trace_flags(VALUE self, VALUE rb_iseq) {
722
+ }
723
+ #endif
724
+
651
725
  static VALUE
652
726
  Debase_init_variables()
653
727
  {
@@ -691,6 +765,10 @@ Init_debase_internals()
691
765
  rb_define_module_function(mDebase, "enable_trace_points", Debase_enable_trace_points, 0);
692
766
  rb_define_module_function(mDebase, "prepare_context", Debase_prepare_context, 0);
693
767
  rb_define_module_function(mDebase, "init_variables", Debase_init_variables, 0);
768
+ rb_define_module_function(mDebase, "set_trace_flag_to_iseq", Debase_set_trace_flag_to_iseq, 1);
769
+
770
+ //use only for tests
771
+ rb_define_module_function(mDebase, "unset_iseq_flags", Debase_unset_trace_flags, 1);
694
772
 
695
773
  idAlive = rb_intern("alive?");
696
774
  idAtLine = rb_intern("at_line");
@@ -1,8 +1,8 @@
1
1
  #ifndef DEBASE_INTERNALS
2
2
  #define DEBASE_INTERNALS
3
3
 
4
- #include <ruby.h>
5
- #include <ruby/debug.h>
4
+ #include "ruby.h"
5
+ #include "ruby/debug.h"
6
6
 
7
7
  typedef struct rb_trace_arg_struct rb_trace_point_t;
8
8
 
@@ -57,12 +57,12 @@ typedef struct debug_context {
57
57
  /* dest_frame uses calced_stack_size for stepping */
58
58
  int dest_frame;
59
59
  int calced_stack_size;
60
- int init_stack_size;
61
-
62
- char **init_stack_files;
63
60
 
64
61
  char *last_file;
65
62
  int last_line;
63
+ int init_stack_size;
64
+ int script_finished;
65
+ int hit_user_code;
66
66
  } debug_context_t;
67
67
 
68
68
  typedef struct
@@ -28,8 +28,13 @@ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
28
28
  require "debase/ruby_core_source"
29
29
 
30
30
  hdrs = proc {
31
- have_header("vm_core.h")
32
- have_header("version.h")
31
+ have_header("vm_core.h") and
32
+ have_header("iseq.h") and
33
+ have_header("version.h") and
34
+ have_header("vm_core.h") and
35
+ have_header("vm_insnhelper.h") and
36
+ have_header("vm_core.h") and
37
+ have_header("method.h")
33
38
  }
34
39
 
35
40
  # Allow use customization of compile options. For example, the
@@ -20,7 +20,21 @@ module Debase
20
20
  Debugger.const_set('ARGV', ARGV.clone) unless defined? Debugger::ARGV
21
21
  Debugger.const_set('PROG_SCRIPT', $0) unless defined? Debugger::PROG_SCRIPT
22
22
  Debugger.const_set('INITIAL_DIR', Dir.pwd) unless defined? Debugger::INITIAL_DIR
23
- return Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
23
+
24
+ monkey_patch_prepend
25
+
26
+ Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
27
+ end
28
+
29
+ def monkey_patch_prepend
30
+ class << RubyVM::InstructionSequence
31
+ def self.prepend(mod, *smth)
32
+ super
33
+ if mod.to_s.include?('Bootsnap') && RUBY_VERSION >= '2.5' && RUBY_VERSION < '2.6'
34
+ prepend InstructionSequenceMixin
35
+ end
36
+ end
37
+ end
24
38
  end
25
39
 
26
40
  # @param [String] file
@@ -81,6 +95,21 @@ module Debase
81
95
  def file_filter
82
96
  @file_filter ||= FileFilter.new
83
97
  end
98
+
99
+ module InstructionSequenceMixin
100
+ def load_iseq(path)
101
+ iseq = super(path)
102
+
103
+ do_set_flags(iseq)
104
+
105
+ iseq
106
+ end
107
+
108
+ def do_set_flags(iseq)
109
+ Debugger.set_trace_flag_to_iseq(iseq)
110
+ iseq.each_child { |child_iseq| do_set_flags(child_iseq) } if iseq.respond_to? :each_child
111
+ end
112
+ end
84
113
  end
85
114
 
86
115
  class FileFilter
@@ -1,3 +1,3 @@
1
1
  module Debase
2
- VERSION = "0.2.2" unless defined? VERSION
2
+ VERSION = "0.2.4.1" unless defined? VERSION
3
3
  end
@@ -0,0 +1,5 @@
1
+ class A
2
+ def foo(a)
3
+ puts a
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ require_relative 'a.rb'
2
+
3
+ A.new.foo('hi')
@@ -3,6 +3,9 @@ require File.expand_path("helper", File.dirname(__FILE__))
3
3
 
4
4
  # Test of Debugger.debug_load in C extension ruby_debug.so
5
5
  class TestDebugLoad < Test::Unit::TestCase
6
+
7
+ self.test_order = :defined
8
+
6
9
  class << self
7
10
  def at_line(file, line)
8
11
  @@at_line = [File.basename(file), line]
@@ -41,4 +44,35 @@ class TestDebugLoad < Test::Unit::TestCase
41
44
  ensure
42
45
  Debugger.stop if Debugger.started?
43
46
  end
47
+
48
+ module MyBootsnap
49
+ def load_iseq(path)
50
+ iseq = RubyVM::InstructionSequence.compile_file(path)
51
+
52
+ Debugger.unset_iseq_flags(iseq)
53
+ iseq
54
+ end
55
+ end
56
+
57
+ def test_bootsnap
58
+ @@at_line = nil
59
+ src_dir = File.dirname(__FILE__)
60
+ prog_script = File.join(src_dir, 'example', 'bootsnap', 'bootsnap.rb')
61
+
62
+ class << RubyVM::InstructionSequence
63
+ prepend MyBootsnap
64
+ end
65
+ bt = Debugger.debug_load(prog_script, true)
66
+ assert_equal(nil, bt)
67
+ assert_not_nil(@@at_line)
68
+ if RUBY_VERSION >= '2.5' && RUBY_VERSION < '2.6'
69
+ assert_equal(['debase.rb', 101], @@at_line)
70
+ end
71
+
72
+ assert(Debugger.started?)
73
+ Debugger.stop
74
+
75
+ class << RubyVM::InstructionSequence; self end.class_eval { undef_method :load_iseq }
76
+
77
+ end
44
78
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: debase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Ushakov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-01 00:00:00.000000000 Z
11
+ date: 2019-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: debase-ruby_core_source
@@ -94,6 +94,8 @@ files:
94
94
  - test/example/a/example.rb
95
95
  - test/example/at-exit.rb
96
96
  - test/example/b/example.rb
97
+ - test/example/bootsnap/a.rb
98
+ - test/example/bootsnap/bootsnap.rb
97
99
  - test/example/bp_loop_issue.rb
98
100
  - test/example/breakpoints-basename.rb
99
101
  - test/example/brkpt-class-bug.rb
@@ -134,8 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
136
  - !ruby/object:Gem::Version
135
137
  version: '0'
136
138
  requirements: []
137
- rubyforge_project: debase
138
- rubygems_version: 2.6.10
139
+ rubygems_version: 3.0.3
139
140
  signing_key:
140
141
  specification_version: 4
141
142
  summary: debase is a fast implementation of the standard Ruby debugger debug.rb for