# Copyright (C) 2010, 2011 Rocky Bernstein require 'rubygems' require 'require_relative' require_relative 'virtual' class Trepan::CmdProcessor < Trepan::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. def continue @state.proceed 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 # @frame.trace_off = true # No more tracing in this frame # @frame.return_stop = true # don't need to # 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) # @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) # 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 @context.stop_next = 0 # 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['exit'].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 '>' opts[:stop_events] = Set.new(%w(c-call call)) 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 # return true if # !frame || (@next_level < @frame.stack_size && # Thread.current == @next_thread) # new_pos = [@frame.source_container, frame_line, # @stack_size, @current_thread, @event, @frame.pc_offset] # skip_val = @stop_events && !@stop_events.member?(@event) # # 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 == '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