-
Notifications
You must be signed in to change notification settings - Fork 22
/
gdb.rb
75 lines (64 loc) · 1.5 KB
/
gdb.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
# Based on gdb.rb by Jamis Buck, thanks Jamis!
module Hijack
class GDB
def initialize(pid)
@verbose = Hijack.options[:gdb_debug]
exec_path = File.join(Config::CONFIG['bindir'], Config::CONFIG['RUBY_INSTALL_NAME'] + Config::CONFIG['EXEEXT'])
@gdb = IO.popen("gdb -q #{exec_path} #{pid} 2>&1", 'r+')
wait
end
def attached_to_ruby_process?
exec('bt').any? {|line| line =~ /ruby_run/}
end
def eval(cmd)
set_trap_pending
set_breakpoint
continue
clear_breakpoint
call("(void)rb_eval_string(#{cmd.strip.gsub(/"/, '\"').inspect})")
end
def detach
exec('detach')
exec('quit')
@gdb.close
end
protected
def set_trap_pending
exec("set variable (int)rb_trap_pending=1")
end
def set_breakpoint
exec("break rb_trap_exec")
end
def clear_breakpoint
exec("clear rb_trap_exec")
end
def continue
exec('continue')
end
def call(cmd)
exec("call #{cmd}")
end
def exec(str)
puts("(gdb) #{str}") if @verbose
@gdb.puts(str)
wait
end
def wait
lines = []
line = ''
while result = IO.select([@gdb])
next if result.empty?
c = @gdb.read(1)
break if c.nil?
line << c
break if line == "(gdb) " || line == " >"
if line[-1] == ?\n
lines << line
line = ""
end
end
puts lines.map { |l| "> #{l}" } if @verbose
lines
end
end
end