class Metasm::GdbRemoteDebugger

this class implements a high-level API using the gdb-server network debugging protocol

Attributes

check_target_timeout[RW]
gdb[RW]
gdb_bpx[RW]

set to true to use the gdb msg to handle bpx, false to set 0xcc manually ourself

realmode[RW]
reg_val_cache[RW]

Public Class Methods

new(url, cpu='Ia32') click to toggle source
Calls superclass method Metasm::Debugger.new
# File metasm/os/gdbremote.rb, line 424
def initialize(url, cpu='Ia32')
        super()
        @tid_stuff_list << :reg_val_cache << :regs_dirty
        @gdb = GdbClient.new(url, cpu)
        @gdb.logger = self
        # when checking target, if no message seen since this much seconds, send a 'status' query
        @check_target_timeout = 1
        set_context(28, 28)
end

Public Instance Methods

break() click to toggle source
# File metasm/os/gdbremote.rb, line 557
def break
        @gdb.break
end
check_pid(pid) click to toggle source
# File metasm/os/gdbremote.rb, line 434
def check_pid(pid)
        # return nil if pid == nil
        pid
end
check_pre_run(*a) click to toggle source
Calls superclass method Metasm::Debugger#check_pre_run
# File metasm/os/gdbremote.rb, line 604
def check_pre_run(*a)
        if ret = super(*a)
                sync_regs
                ret
        end
end
check_tid(tid) click to toggle source
# File metasm/os/gdbremote.rb, line 438
def check_tid(tid)
        tid
end
detach() click to toggle source
# File metasm/os/gdbremote.rb, line 567
def detach
        del_all_breakpoints
        del_pid
end
do_check_target() click to toggle source
# File metasm/os/gdbremote.rb, line 508
def do_check_target
        return if @state == :dead

        # keep-alive on the connexion
        t = Time.now
        @last_check_target ||= t
        if @state == :running and t - @last_check_target > @check_target_timeout
                @gdb.io.write '$?#' << @gdb.gdb_csum('?')
                @last_check_target = t
        end

        return unless i = @gdb.check_target(0.01)
        update_state(i)
        true
end
do_continue(*a) click to toggle source
# File metasm/os/gdbremote.rb, line 545
def do_continue(*a)
        @state = :running
        @gdb.continue
        @last_check_target = Time.now
end
do_disable_bp(b) click to toggle source
# File metasm/os/gdbremote.rb, line 589
def do_disable_bp(b)
        case b.type
        when :bpm
                do_disable_bpm(b)
        when :bpx
                if gdb_bpx
                        @gdb.unset_hwbp('s', b.address, 1)
                else
                        @cpu.dbg_disable_bp(self, b)
                end
        when :hwbp
                @gdb.unset_hwbp(b.internal[:type], b.address, b.internal[:len])
        end
end
do_enable_bp(b) click to toggle source
# File metasm/os/gdbremote.rb, line 574
def do_enable_bp(b)
        case b.type
        when :bpm
                do_enable_bpm(b)
        when :bpx
                if gdb_bpx
                        @gdb.set_hwbp('s', b.address, 1)
                else
                        @cpu.dbg_enable_bp(self, b)
                end
        when :hwbp
                @gdb.set_hwbp(b.internal[:type], b.address, b.internal[:len])
        end
end
do_singlestep(*a) click to toggle source
# File metasm/os/gdbremote.rb, line 551
def do_singlestep(*a)
        @state = :running
        @gdb.singlestep
        @last_check_target = Time.now
end
do_wait_target() click to toggle source
# File metasm/os/gdbremote.rb, line 524
def do_wait_target
        return unless i = @gdb.check_target(nil)
        update_state(i)
end
get_reg_value(r) click to toggle source
# File metasm/os/gdbremote.rb, line 480
def get_reg_value(r)
        r = r.to_sym
        return @reg_val_cache[r] || 0 if @state != :stopped
        sync_regs
        @reg_val_cache = @gdb.read_regs || {} if @reg_val_cache.empty?
        if realmode
                case r
                when :eip; seg = :cs
                when :esp; seg = :ss
                else seg = :ds
                end
                # XXX seg override
                return @reg_val_cache[seg].to_i*16 + @reg_val_cache[r].to_i
        end
        @reg_val_cache[r] || 0
end
initialize_cpu() click to toggle source
# File metasm/os/gdbremote.rb, line 465
def initialize_cpu
        @cpu = @gdb.cpu
        @realmode = true if @cpu and @cpu.shortname =~ /^ia32_16/
end
initialize_memory() click to toggle source
# File metasm/os/gdbremote.rb, line 470
def initialize_memory
        @memory = GdbRemoteString.new(@gdb)
end
initialize_newtid() click to toggle source
Calls superclass method Metasm::Debugger#initialize_newtid
# File metasm/os/gdbremote.rb, line 458
def initialize_newtid
        super()
        @reg_val_cache = {}
        @regs_dirty = false
end
invalidate() click to toggle source
Calls superclass method Metasm::Debugger#invalidate
# File metasm/os/gdbremote.rb, line 474
def invalidate
        sync_regs
        @reg_val_cache.clear
        super()
end
kill(sig=nil) click to toggle source
# File metasm/os/gdbremote.rb, line 561
def kill(sig=nil)
        # TODO signal nr
        @state = :dead
        @gdb.kill
end
list_processes() click to toggle source
# File metasm/os/gdbremote.rb, line 442
def list_processes
        [@pid].compact
end
list_threads() click to toggle source
# File metasm/os/gdbremote.rb, line 445
def list_threads
        [@tid].compact
end
loadallsyms() click to toggle source
# File metasm/os/gdbremote.rb, line 611
def loadallsyms
        puts 'loadallsyms unsupported'
end
mappings() click to toggle source
# File metasm/os/gdbremote.rb, line 449
def mappings
        []
end
modules() click to toggle source
# File metasm/os/gdbremote.rb, line 453
def modules
        []
end
set_reg_value(r, v) click to toggle source
# File metasm/os/gdbremote.rb, line 496
def set_reg_value(r, v)
        r = r.to_sym
        # XXX realmode
        @reg_val_cache[r] = v
        @regs_dirty = true
end
sync_regs() click to toggle source
# File metasm/os/gdbremote.rb, line 503
def sync_regs
        @gdb.send_regs(@reg_val_cache) if @regs_dirty and not @reg_val_cache.empty?
        @regs_dirty = false
end
ui_command_setup(ui) click to toggle source
# File metasm/os/gdbremote.rb, line 615
def ui_command_setup(ui)
        ui.new_command('monitor', 'send a remote command to run on the target') { |arg| @gdb.rcmd(arg) }
end
update_state(i) click to toggle source
# File metasm/os/gdbremote.rb, line 529
def update_state(i)
        @info = (i[:info] if i[:info] !~ /TRAP/)
        if i[:state] == :stopped and @state != :stopped
                invalidate
                @state = i[:state]
                case @run_method
                when :singlestep
                        evt_singlestep
                else
                        evt_bpx     # XXX evt_hwbp?
                end
        else
                @state = i[:state]
        end
end