1
1
import pexpect , re , signal , sys , time
2
2
3
- __all__ = [ 'expect_gdb' , 'send_gdb' ,'expect_rr' , 'expect_list' ,
4
- 'restart_replay' , 'interrupt_gdb' , 'ok' ,
5
- 'failed' , 'iterlines_both' , 'last_match' , 'get_exe_arch' ,
6
- 'get_gdb_version' , 'set_breakpoint' , 'set_watchpoint' ]
3
+ __all__ = [ 'expect_rr' , 'expect_list' , 'expect_debugger' ,
4
+ 'restart_replay' , 'interrupt_gdb' , 'expect_gdb' , 'send_gdb' ,
5
+ 'ok' , 'failed' , 'iterlines_both' , 'last_match' , 'get_exe_arch' ,
6
+ 'get_gdb_version' , 'breakpoint_at_function' ,
7
+ 'watchpoint_at_address' , 'cont' , 'backtrace' ,
8
+ 'expect_breakpoint_stop' , 'expect_watchpoint_stop' ]
7
9
8
10
# Don't use python timeout. Use test-monitor timeout instead.
9
11
TIMEOUT_SEC = 10000
10
12
# The debugger and rr are part of the same process tree, so they share
11
13
# stdin/stdout.
12
14
child = None
15
+ debugger_type = 'GDB'
13
16
14
17
# Public API
15
- def expect_gdb (what ):
18
+ def expect_debugger (what ):
16
19
expect (child , what )
17
20
18
21
def expect_list (pats ):
@@ -28,31 +31,35 @@ def failed(why, e=None):
28
31
clean_up ()
29
32
sys .exit (1 )
30
33
31
- def interrupt_gdb ():
34
+ def interrupt_debugger ():
32
35
try :
33
36
child .kill (signal .SIGINT )
34
37
except Exception as e :
35
- failed ('interrupting gdb ' , e )
38
+ failed ('interrupting debugger ' , e )
36
39
expect_gdb ('stopped.' )
37
40
38
- def set_breakpoint (args ):
39
- send_gdb (f'b { args } ' )
40
- expect_gdb (r'Breakpoint ([0-9]+)[^0-9]' )
41
- global child
42
- return child .match .group (1 )
43
-
44
- def set_watchpoint (args ):
45
- send_gdb (f'watch { args } ' )
46
- expect_gdb (r'atchpoint ([0-9]+)[^0-9]' )
47
- global child
48
- return child .match .group (1 )
49
-
50
41
def iterlines_both ():
51
42
return child
52
43
53
44
def last_match ():
54
45
return child .match
55
46
47
+ def expect_gdb (what ):
48
+ assert debugger_type == 'GDB'
49
+ expect_debugger (what )
50
+
51
+ def interrupt_gdb ():
52
+ assert debugger_type == 'GDB'
53
+ interrupt_debugger ()
54
+
55
+ def send_gdb (what ):
56
+ assert debugger_type == 'GDB'
57
+ send (child , "%s\n " % what )
58
+
59
+ def send_lldb (what ):
60
+ assert debugger_type == 'LLDB'
61
+ send (child , "%s\n " % what )
62
+
56
63
# Restarts and continues execution
57
64
def restart_replay (event = 0 ):
58
65
if event :
@@ -68,14 +75,61 @@ def restart_replay(event=0):
68
75
expect_rr ('stopped' )
69
76
send_gdb ('c' )
70
77
71
- def send_gdb (what ):
72
- send (child , "%s\n " % what )
78
+ def breakpoint_at_function (function ):
79
+ send_debugger (f'break { function } ' , f'breakpoint set --name { function } ' )
80
+ expect_debugger (r'Breakpoint (\d+)' )
81
+ return int (last_match ().group (1 ))
82
+
83
+ size_to_type = {1 : 'char' , 2 :'short' , 4 :'int' , 8 :'long long' }
84
+
85
+ def watchpoint_at_address (address , size ):
86
+ send_debugger (f'watch -l *({ size_to_type [size ]} *){ address } ' ,
87
+ f'watchpoint set expression -s { size } -- { address } ' )
88
+ expect_debugger (r'atchpoint (\d+)' )
89
+ return int (last_match ().group (1 ))
90
+
91
+ def cont ():
92
+ send_debugger ('continue' , 'continue' )
93
+
94
+ def backtrace ():
95
+ send_debugger ('bt' , 'thread backtrace' )
96
+
97
+ def expect_breakpoint_stop (number ):
98
+ if debugger_type == 'GDB' :
99
+ expect_debugger ("Breakpoint %d" % number )
100
+ else :
101
+ expect_debugger ("stop reason = breakpoint %d" % number )
102
+
103
+ def expect_watchpoint_stop (number ):
104
+ if debugger_type == 'GDB' :
105
+ expect_debugger ("atchpoint %d" % number )
106
+ else :
107
+ expect_debugger ("stop reason = watchpoint %d" % number )
108
+
109
+ def send_debugger (gdb_cmd , lldb_cmd ):
110
+ if debugger_type == 'GDB' :
111
+ send_gdb (gdb_cmd )
112
+ else :
113
+ send_lldb (lldb_cmd )
73
114
74
115
def ok ():
75
- send_gdb ( 'q ' )
76
- send_gdb ( 'y' )
116
+ send_debugger ( 'quit' , 'quit ' )
117
+ send_debugger ( 'y' , 'y' )
77
118
clean_up ()
78
119
120
+ def get_exe_arch ():
121
+ send_gdb ('show architecture' )
122
+ expect_gdb (r'The target architecture is set (automatically|to "auto") \(currently "?([0-9a-z:-]+)"?\)\.?' )
123
+ global child
124
+ return child .match .group (2 )
125
+
126
+ def get_gdb_version ():
127
+ '''Return the gdb version'''
128
+ send_gdb ('python print(gdb.VERSION)' )
129
+ expect_gdb (r'(\d+.\d+)' )
130
+ global child
131
+ return float (child .match .group (1 ))
132
+
79
133
# Internal helpers
80
134
def clean_up ():
81
135
global child
@@ -100,25 +154,6 @@ def expect(prog, what):
100
154
except Exception as e :
101
155
failed ('expecting "%s"' % (what ), e )
102
156
103
- def get_exe_arch ():
104
- send_gdb ('show architecture' )
105
- expect_gdb (r'The target architecture is set (automatically|to "auto") \(currently "?([0-9a-z:-]+)"?\)\.?' )
106
- global child
107
- return child .match .group (2 )
108
-
109
- def get_rr_cmd ():
110
- '''Return the command that should be used to invoke rr, as the tuple
111
- (executable, array-of-args)'''
112
- rrargs = sys .argv [1 :]
113
- return (rrargs [0 ], rrargs [1 :])
114
-
115
- def get_gdb_version ():
116
- '''Return the gdb version'''
117
- send_gdb ('python print(gdb.VERSION)' )
118
- expect_gdb (r'(\d+.\d+)' )
119
- global child
120
- return float (child .match .group (1 ))
121
-
122
157
def send (prog , what ):
123
158
try :
124
159
prog .send (what )
@@ -127,11 +162,19 @@ def send(prog, what):
127
162
128
163
def set_up ():
129
164
global child
165
+ global debugger_type
166
+ args = sys .argv [1 :]
167
+ log_file = 'gdb_rr.log'
168
+ if args [0 ] == '--lldb' :
169
+ debugger_type = 'LLDB'
170
+ args = args [1 :] + ['-d' , 'lldb' , '-o' , '--no-use-colors' ]
171
+ log_file = 'lldb_rr.log'
130
172
try :
131
- child = pexpect .spawn (* get_rr_cmd (), codec_errors = 'ignore' , timeout = TIMEOUT_SEC , encoding = 'utf-8' , logfile = open ('gdb_rr.log' , 'w' ))
173
+ child = pexpect .spawn (args [0 ], args [1 :], codec_errors = 'ignore' ,
174
+ timeout = TIMEOUT_SEC , encoding = 'utf-8' , logfile = open (log_file , 'w' ))
132
175
child .delaybeforesend = 0
133
- expect_gdb (r'\(rr\)' )
176
+ expect_debugger (r'\(rr\)' )
134
177
except Exception as e :
135
- failed ('initializing rr and gdb ' , e )
178
+ failed ('initializing rr and debugger ' , e )
136
179
137
180
set_up ()
0 commit comments