/
running.rb
187 lines (162 loc) · 6.88 KB
/
running.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# Copyright (C) 2010-2011, 2015 Rocky Bernstein <rockyb@rubyforge.net>
require_relative 'virtual'
class Trepan
class CmdProcessor < VirtualCmdProcessor
attr_accessor :stop_condition # String or nil. When not nil
# this has to eval non-nil
# in order to stop.
attr_accessor :stop_events # Set or nil. If not nil, only
# events in this set will be
# considered for stopping. This is
# like core.step_events (which
# could be used instead), but it is
# a set of event names rather than
# a bitmask and it is intended to
# be more temporarily changed via
# "step>" or "step!" commands.
attr_accessor :to_method
# Does whatever needs to be done to set to continue program
# execution.
# FIXME: turn line_number into a condition.
def continue
# FIXME: with the ruby-supported stepping, we might not
# need the below any more.
# I'm guessing the stack size can't ever reach this
@next_level = 32000
@next_thread = nil
if @settings[:traceprint]
@core.step_count = 1 # traceprint will avoid stopping
else
@core.step_count = -1 # No more event stepping
end
@leave_cmd_loop = true # Break out of the processor command loop.
end
# Does whatever setup needs to be done to set to ignore stepping
# to the finish of the current method.
def finish(level_count=0, opts={})
step(0, opts)
# @next_level = @frame.stack_size - level_count
# @next_thread = Thread.current
# @stop_events = Set.new(%w(return leave yield))
# Try high-speed (run-time-assisted) method
# FIXME: if frame is not the top frame, then we should to do more...
@frame.step_out
end
# Does whatever needs to be done to set to do "step over" or ignore
# stepping into methods called from this stack but step into any in
# the same level. We do this by keeping track of the number of
# stack frames and the current thread. Elsewhere in "skipping_step?"
# we do the checking.
def next(step_count=1, opts={})
step(step_count, opts)
# FIXME: if frame is not the top frame, then we should to do more...
# Try high-speed (run-time-assisted) method
@frame.step_over
# @next_level = @top_frame.stack_size
# @next_thread = Thread.current
end
# Does whatever needs to be done to set to step program
# execution.
def step(step_count=1, opts={}, condition=nil)
@frame.step_in if @frame
continue
@core.step_count = step_count
@different_pos = opts[:different_pos] if
opts.keys.member?(:different_pos)
@stop_condition = condition
@stop_events = opts[:stop_events] if
opts.keys.member?(:stop_events)
@to_method = opts[:to_method]
end
def quit(cmd='quit')
@next_level = 32000 # I'm guessing the stack size can't
# ever reach this
@next_thread = nil
@core.step_count = -1 # No more event stepping
@leave_cmd_loop = true # Break out of the processor command loop.
@settings[:autoirb] = false
@cmdloop_prehooks.delete_by_name('autoirb')
@commands['quit'].run([cmd])
end
def parse_next_step_suffix(step_cmd)
opts = {}
case step_cmd[-1..-1]
when '-'
opts[:different_pos] = false
when '+'
opts[:different_pos] = 'nostack'
when '='
opts[:different_pos] = true
when '!'
opts[:stop_events] = Set.new(%w(raise))
when '<'
opts[:stop_events] = Set.new(%w(c_return return))
when '>'
if step_cmd.size > 1 && step_cmd[-2..-2] == '<'
opts[:stop_events] = Set.new(%w(c_call c_return call return))
else
opts[:stop_events] = Set.new(%w(c_call call))
end
end
return opts
end
def running_initialize
@stop_condition = nil
@stop_events = nil
@to_method = nil
end
def stepping_skip?
return true if @core.step_count < 0
if @settings[:'debugskip']
msg "diff: #{@different_pos}, event : #{@event}, #{@stop_events.inspect}"
msg "step_count : #{@core.step_count}"
msg "next_level : #{@next_level}, ssize : #{@stack_size}"
msg "next_thread : #{@next_thread}, thread: #{Thread.current}"
end
# FIXME: with the ruby-supported stepping, we might not
# need @next_level an the below test.
return true if
!frame || (@next_level < @frame.stack_size &&
Thread.current == @next_thread && @event.to_s != 'raise')
new_pos = [@frame.source_container, frame_line,
@stack_size, @current_thread, @event, @frame.pc_offset]
skip_val = @stop_events && !@stop_events.member?(@event.to_s)
# If the last stop was a breakpoint, don't stop again if we are at
# the same location with a line event.
skip_val ||= (@last_pos[4] == 'brkpt' &&
@event.to_s == 'line' &&
@frame.pc_offset == @last_pos[5])
if @settings[:'debugskip']
puts "skip: #{skip_val.inspect}, last: #{@last_pos}, new: #{new_pos}"
end
@last_pos[2] = new_pos[2] if 'nostack' == @different_pos
unless skip_val
condition_met =
if @stop_condition
puts 'stop_cond' if @settings[:'debugskip']
debug_eval_no_errmsg(@stop_condition)
elsif @to_method
puts "method #{@frame.method} #{@to_method}" if
@settings[:'debugskip']
@frame.method == @to_method
else
puts 'uncond' if @settings[:'debugskip']
true
end
msg("condition_met: #{condition_met}, last: #{@last_pos}, " +
"new: #{new_pos}, different #{@different_pos.inspect}") if
@settings[:'debugskip']
skip_val = ((@last_pos[0..3] == new_pos[0..3] && @different_pos) ||
!condition_met)
end
@last_pos = new_pos if !@stop_events || @stop_events.member?(@event)
unless skip_val
# Set up the default values for the
# next time we consider skipping.
@different_pos = @settings[:different]
@stop_events = nil
end
return skip_val
end
end
end