Class: Ptrace::Target
- Inherits:
-
Object
- Object
- Ptrace::Target
- Defined in:
- lib/Ptrace.rb
Overview
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
Instance Attribute Summary collapse
-
#data ⇒ Object
Data segment for process.
-
#fpregs ⇒ Object
extended FPU registers for process.
-
#options ⇒ Object
Ptrace options.
-
#pid ⇒ Object
PID of target process.
-
#regs ⇒ Object
General (CPU) registers for process.
-
#text ⇒ Object
Text (code) segment for process.
-
#user ⇒ Object
Target ‘user’ (task) area.
Class Method Summary collapse
-
.attach(pid) ⇒ Object
PT_ATTACH : Attach to running process ‘pid’ and return a Ptrace::Target object.
-
.launch(cmd) ⇒ Object
PT_TRACE_ME : Launch command ‘cmd’ and return a Ptrace::Target object for controlling it.
Instance Method Summary collapse
-
#cont ⇒ Object
PT_CONTINUE: Continue execution of target.
-
#detach ⇒ Object
PT_DETACH : Detach from the process.
- #event_msg ⇒ Object
-
#initialize(pid) ⇒ Target
constructor
Create a Ptrace::Target object for process ‘pid’.
-
#kill ⇒ Object
PT_KILL : Terminate the process.
- #signal(sig = nil) ⇒ Object
-
#step ⇒ Object
PT_STEP : Step a single instruction.
-
#syscall ⇒ Object
PT_SYSCALL : Execute until the start or end of the next system call.
-
#syscall_state ⇒ Object
Wrapper for recording syscalls.
-
#sysemu ⇒ Object
PT_SYSEMU.
-
#sysemu_step ⇒ Object
PT_SYSEMU_SINGLESTEP.
Constructor Details
#initialize(pid) ⇒ Target
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.
379 380 381 382 383 384 385 386 387 388 389 |
# 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 |
Instance Attribute Details
#data ⇒ Object
Data segment for process.
364 365 366 |
# File 'lib/Ptrace.rb', line 364 def data @data end |
#fpregs ⇒ Object
extended FPU registers for process.
352 353 354 |
# File 'lib/Ptrace.rb', line 352 def fpregs @fpregs end |
#options ⇒ Object
Ptrace options.
372 373 374 |
# File 'lib/Ptrace.rb', line 372 def @options end |
#pid ⇒ Object
PID of target process.
344 345 346 |
# File 'lib/Ptrace.rb', line 344 def pid @pid end |
#regs ⇒ Object
General (CPU) registers for process.
348 349 350 |
# File 'lib/Ptrace.rb', line 348 def regs @regs end |
#text ⇒ Object
Text (code) segment for process.
360 361 362 |
# File 'lib/Ptrace.rb', line 360 def text @text end |
#user ⇒ Object
Target ‘user’ (task) area.
368 369 370 |
# File 'lib/Ptrace.rb', line 368 def user @user end |
Class Method Details
.attach(pid) ⇒ Object
PT_ATTACH : Attach to running process ‘pid’ and return a Ptrace::Target object. Raises an exception if the attach fails.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
# 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. when 'PTRACE: Operation not permitted' raise OperationNotPermittedError.new(e.) when 'PTRACE: No such process' raise InvalidProcessError.new(e.) else raise end end return tgt end |
.launch(cmd) ⇒ Object
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.
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# 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. when 'PTRACE: Operation not permitted' raise OperationNotPermittedError.new(e.) when 'PTRACE: No such process' raise InvalidProcessError.new(e.) else raise end end elsif pid == -1 return nil else Process.waitpid(pid) tgt = Target.new(pid) return tgt end end |
Instance Method Details
#cont ⇒ Object
PT_CONTINUE: Continue execution of target.
529 530 531 532 |
# File 'lib/Ptrace.rb', line 529 def cont ptrace_send( :cont ) Process.waitpid(@pid) end |
#detach ⇒ Object
PT_DETACH : Detach from the process. Note: This makes the Ptrace::Target object invalid.
477 478 479 480 481 |
# File 'lib/Ptrace.rb', line 477 def detach ptrace_send( :detach ) Process.waitpid(@pid) @valid = false end |
#event_msg ⇒ Object
457 458 459 460 461 |
# 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 |
#kill ⇒ Object
PT_KILL : Terminate the process. Note: This makes the Ptrace::Target object invalid.
467 468 469 470 471 |
# File 'lib/Ptrace.rb', line 467 def kill ptrace_send( :kill ) Process.waitpid(@pid) @valid = false end |
#signal(sig = nil) ⇒ Object
449 450 451 452 453 |
# File 'lib/Ptrace.rb', line 449 def signal(sig=nil) # if sig, send # else: Signal.read(pid) end |
#step ⇒ Object
PT_STEP : Step a single instruction.
486 487 488 489 |
# File 'lib/Ptrace.rb', line 486 def step ptrace_send( :singlestep ) Process.waitpid(@pid) end |
#syscall ⇒ Object
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
500 501 502 503 |
# File 'lib/Ptrace.rb', line 500 def syscall ptrace_send( :syscall ) Process.waitpid(@pid) end |
#syscall_state ⇒ Object
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.
512 513 514 515 516 517 518 519 520 521 522 523 524 |
# 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 |
#sysemu ⇒ Object
PT_SYSEMU
537 538 539 |
# File 'lib/Ptrace.rb', line 537 def sysemu ptrace_send( :sysemu ) end |
#sysemu_step ⇒ Object
PT_SYSEMU_SINGLESTEP
544 545 546 |
# File 'lib/Ptrace.rb', line 544 def sysemu_step ptrace_send( :sysemu_singlestep ) end |