debase 0.2.2 → 0.2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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