class Ptrace::Target
# ———————————————————————– A target process managed by ptrace.
Usage:
tgt = Target.attach(pid) loop do begin tgt.step puts tgt.regs.read.inspect rescue Ptrace::InvalidProcessError break end end tgt = Target.launch(cmd) loop do begin state = tgt.syscall_state puts state.inspect rescue Ptrace::InvalidProcessError break end end
Attributes
Data segment for process.
FPU registers for process.
Ptrace
options.
PID of target process.
General (CPU) registers for process.
Text (code) segment for process.
Target
'user' (task) area.
Public Class Methods
PT_ATTACH : Attach to running process 'pid' and return a Ptrace::Target
object. Raises an exception if the attach fails.
# File lib/Ptrace.rb, line 395 def self.attach(pid) tgt = Target.new(pid) begin Ptrace::Debugger.send_cmd( Ptrace::Debugger.commands[:attach], pid, nil) Process.waitpid(pid) rescue RuntimeError => e case e.message when 'PTRACE: Operation not permitted' raise OperationNotPermittedError.new(e.message) when 'PTRACE: No such process' raise InvalidProcessError.new(e.message) else raise end end return tgt end
PT_TRACE_ME : Launch command 'cmd' and return a Ptrace::Target
object for controlling it. Raises an exception if the command cannot be launched; returns nil if the command cannot be traced.
# File lib/Ptrace.rb, line 419 def self.launch(cmd) pid = fork if ! pid begin Ptrace::Debugger.send_cmd(Ptrace::Debugger.commands[:traceme], nil, nil) exec(cmd) rescue RuntimeError => e case e.message when 'PTRACE: Operation not permitted' raise OperationNotPermittedError.new(e.message) when 'PTRACE: No such process' raise InvalidProcessError.new(e.message) else raise end end elsif pid == -1 return nil else Process.waitpid(pid) tgt = Target.new(pid) return tgt end end
Create a Ptrace::Target
object for process 'pid'. The process is assumed to have been launched or attached to by ptrace, e.g. using Target.launch
or Target.attach
.
# File lib/Ptrace.rb, line 379 def initialize(pid) @pid = pid @text = MemArea.new(MemArea::MEM_TEXT, pid) @data = MemArea.new(MemArea::MEM_DATA, pid) @user = MemArea.new(MemArea::MEM_USER, pid) @regs = RegSet.new(RegSet::GEN, pid) @fpregs = RegSet.new(RegSet::FP, pid) @fpxregs = RegSet.new(RegSet::Ext, pid) @options = Options.new(pid) @valid = true end
Public Instance Methods
PT_CONTINUE: Continue execution of target.
# File lib/Ptrace.rb, line 529 def cont ptrace_send( :cont ) Process.waitpid(@pid) end
PT_DETACH : Detach from the process. Note: This makes the Ptrace::Target
object invalid.
# File lib/Ptrace.rb, line 477 def detach ptrace_send( :detach ) Process.waitpid(@pid) @valid = false end
# File lib/Ptrace.rb, line 457 def event_msg # send signal # For PTRACE_EVENT_EXIT this is the child's exit status. For PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK and PTRACE_EVENT_CLONE this is the PID of the new process. # Debugger.event_msg end
PT_KILL : Terminate the process. Note: This makes the Ptrace::Target
object invalid.
# File lib/Ptrace.rb, line 467 def kill ptrace_send( :kill ) Process.waitpid(@pid) @valid = false end
# File lib/Ptrace.rb, line 551 def options= # TODO # ptrace_send_data( :setoptions, ) end
# File lib/Ptrace.rb, line 449 def signal(sig=nil) # if sig, send # else: Signal.read(pid) end
PT_STEP : Step a single instruction.
# File lib/Ptrace.rb, line 486 def step ptrace_send( :singlestep ) Process.waitpid(@pid) end
PT_SYSCALL : Execute until the start or end of the next system call.
Usage:
tgt.syscall in_regs = tgt.regs.read tgt.syscall out_regs = tgt.regs.read
# File lib/Ptrace.rb, line 500 def syscall ptrace_send( :syscall ) Process.waitpid(@pid) end
Wrapper for recording syscalls. This issues a PT_SYSCALL to stop the target at the next syscall, records the 'in' register set, issues a PT_SYSCALL to stop the target after the syscall returns, records the 'out' register set, and returns a Hash { :in, :out } of the register sets. The target is stopped on return from this syscall.
# File lib/Ptrace.rb, line 512 def syscall_state begin state = {} syscall state[:in] = @regs.read syscall state[:out] = @regs.read state rescue InvalidProcessError # Program exited without a syscall return state end end
PT_SYSEMU
# File lib/Ptrace.rb, line 537 def sysemu ptrace_send( :sysemu ) end
PT_SYSEMU_SINGLESTEP
# File lib/Ptrace.rb, line 544 def sysemu_step ptrace_send( :sysemu_singlestep ) end
Private Instance Methods
# File lib/Ptrace.rb, line 558 def ptrace_send( cmd, arg=nil ) begin raise OperationNotSupportedError if (not PTRACE_COMMANDS.include? cmd) raise OperationNotPermittedError if (not @valid) Debugger.send_cmd( PTRACE_COMMANDS[cmd], @pid, arg ) rescue RuntimeError => e case e.message when 'PTRACE: Operation not permitted' raise OperationNotPermittedError.new(e.message) when 'PTRACE: No such process' raise InvalidProcessError.new(e.message) else raise end end end