1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # gdb-frontend is a easy, flexible and extensionable gui debugger
4
+ #
5
+ # https://github.com/rohanrhu/gdb-frontend
6
+ # https://oguzhaneroglu.com/projects/gdb-frontend/
7
+ #
8
+ # Licensed under GNU/GPLv3
9
+ # Copyright (C) 2019, Oğuzhan Eroğlu (https://oguzhaneroglu.com/) <[email protected] >
10
+
11
+ import importlib
12
+ import json
13
+ import time
14
+ import traceback
15
+
16
+ import config
17
+ config .init ()
18
+ import plugin
19
+ import util
20
+ import api .debug
21
+ import api .collabration
22
+ import api .flags
23
+ import api .globalvars
24
+ import api .collabration
25
+ import websocket
26
+ import terminal_daemon
27
+
28
+ gdb = importlib .import_module ("gdb" )
29
+
30
+ api .globalvars .init ()
31
+ plugin .init ()
32
+ api .collabration .init ()
33
+
34
+ class GDBFrontendDebugEventsHandler :
35
+ cont_time = False
36
+
37
+ def __init__ (self ):
38
+ self .connectGDBEvents ()
39
+
40
+ def connectGDBEvents (self ):
41
+ gdb .events .new_objfile .connect (self .gdb_on_new_objfile )
42
+ gdb .events .clear_objfiles .connect (self .gdb_on_clear_objfiles )
43
+ gdb .events .breakpoint_created .connect (self .gdb_on_breakpoint_created )
44
+ gdb .events .breakpoint_modified .connect (self .gdb_on_breakpoint_modified )
45
+ gdb .events .breakpoint_deleted .connect (self .gdb_on_breakpoint_deleted )
46
+ gdb .events .stop .connect (self .gdb_on_stop )
47
+ gdb .events .new_thread .connect (self .gdb_on_new_thread )
48
+ gdb .events .cont .connect (self .gdb_on_cont )
49
+ gdb .events .exited .connect (self .gdb_on_exited )
50
+ gdb .events .inferior_deleted .connect (self .gdb_on_inferior_deleted )
51
+ gdb .events .new_inferior .connect (self .gdb_on_new_inferior )
52
+
53
+ def disconnectGDBEvents (self ):
54
+ gdb .events .new_objfile .disconnect (self .gdb_on_new_objfile )
55
+ gdb .events .clear_objfiles .disconnect (self .gdb_on_clear_objfiles )
56
+ gdb .events .breakpoint_created .disconnect (self .gdb_on_breakpoint_created )
57
+ gdb .events .breakpoint_modified .disconnect (self .gdb_on_breakpoint_modified )
58
+ gdb .events .breakpoint_deleted .disconnect (self .gdb_on_breakpoint_deleted )
59
+ gdb .events .stop .disconnect (self .gdb_on_stop )
60
+ gdb .events .new_thread .disconnect (self .gdb_on_new_thread )
61
+ gdb .events .cont .disconnect (self .gdb_on_cont )
62
+ gdb .events .exited .disconnect (self .gdb_on_exited )
63
+ gdb .events .inferior_deleted .disconnect (self .gdb_on_inferior_deleted )
64
+ gdb .events .new_inferior .disconnect (self .gdb_on_new_inferior )
65
+
66
+ def gdb_on_new_objfile (self , event ):
67
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_new_objfile()" )
68
+
69
+ api .globalvars .inferior_run_times [gdb .selected_inferior ().num ] = int (time .time ())
70
+
71
+ def _mt ():
72
+ self .gdb_on_new_objfile__mT (event )
73
+
74
+ gdb .post_event (_mt )
75
+
76
+ def gdb_on_new_objfile__mT (self , event ):
77
+ pass
78
+
79
+ def gdb_on_clear_objfiles (self , event ):
80
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_clear_objfiles()" )
81
+
82
+ if api .globalvars .dont_emit_until_stop_or_exit : return
83
+
84
+ gdb .post_event (self .gdb_on_clear_objfiles__mT )
85
+
86
+ def gdb_on_clear_objfiles__mT (self ):
87
+ pass
88
+
89
+ def gdb_on_breakpoint_created (self , event ):
90
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_breakpoint_created()" )
91
+
92
+ gdb .post_event (self .gdb_on_breakpoint_created__mT )
93
+
94
+ def gdb_on_breakpoint_created__mT (self ):
95
+ interrupted = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_ADD )
96
+
97
+ def gdb_on_breakpoint_modified (self , event ):
98
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_breakpoint_modified()" )
99
+
100
+ gdb .post_event (self .gdb_on_breakpoint_modified__mT )
101
+
102
+ def gdb_on_breakpoint_modified__mT (self ):
103
+ interrupted = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_MOD )
104
+ interrupted = interrupted or api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_SET )
105
+
106
+ def gdb_on_breakpoint_deleted (self , event ):
107
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_breakpoint_deleted()" )
108
+
109
+ if api .globalvars .dont_emit_until_stop_or_exit : return
110
+
111
+ gdb .post_event (self .gdb_on_breakpoint_deleted__mT )
112
+
113
+ def gdb_on_breakpoint_deleted__mT (self ):
114
+ interrupted = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_DEL )
115
+
116
+ def gdb_on_stop (self , event ):
117
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_stop()" )
118
+
119
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_RUNNING , False )
120
+
121
+ api .globalvars .dont_emit_until_stop_or_exit = False
122
+ api .globalvars .step_time = time .time () * 1000 - self .cont_time
123
+
124
+ gdb .post_event (self .gdb_on_stop__mT )
125
+
126
+ def gdb_on_stop__mT (self ):
127
+ interrupted_for_thread_safety = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_THREAD_SAFETY )
128
+ interrupted_for_terminate = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_TERMINATE )
129
+ interrupted_for_signal = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_SIGNAL )
130
+ interrupted_for_breakpoint_add = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_ADD )
131
+ interrupted_for_breakpoint_del = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_DEL )
132
+ interrupted_for_breakpoint_mod = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_MOD )
133
+ interrupted_for_breakpoint_set = api .globalvars .debugFlags .get (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_SET )
134
+
135
+ if interrupted_for_thread_safety :
136
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_THREAD_SAFETY , False )
137
+
138
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Continuing for interrupt: THREAD_SAFETY." )
139
+
140
+ try :
141
+ gdb .execute ("c" )
142
+ except Exception as e :
143
+ print ("[Error] (GDBFrontendSocket.gdb_on_stop__mT)" , e )
144
+ elif interrupted_for_terminate :
145
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Terminating for interrupt: TERMINATE." )
146
+
147
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_TERMINATE , False )
148
+
149
+ try :
150
+ gdb .execute ("kill" )
151
+ except Exception as e :
152
+ print ("[Error] (GDBFrontendSocket.gdb_on_stop__mT)" , e )
153
+ elif interrupted_for_signal :
154
+ try :
155
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Continuing for interrupt: SIGNAL." )
156
+ gdb .execute ("c" )
157
+ except Exception as e :
158
+ print ("[Error] (GDBFrontendSocket().gdb_on_stop__mT)" , e )
159
+ elif interrupted_for_breakpoint_add :
160
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Continuing for interrupt: BREAKPOINT_ADD." )
161
+
162
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_ADD , False )
163
+
164
+ if "address" in interrupted_for_breakpoint_add :
165
+ bp = api .debug .Breakpoint (
166
+ address = interrupted_for_breakpoint_add ["address" ]
167
+ )
168
+ else :
169
+ bp = api .debug .Breakpoint (
170
+ source = interrupted_for_breakpoint_add ["file" ],
171
+ line = interrupted_for_breakpoint_add ["line" ]
172
+ )
173
+
174
+ try :
175
+ gdb .execute ("c" )
176
+ except Exception as e :
177
+ print ("[Error] (GDBFrontendSocket().gdb_on_stop__mT)" , e )
178
+ elif interrupted_for_breakpoint_del :
179
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Continuing for interrupt: BREAKPOINT_DEL." )
180
+
181
+ interrupted_for_breakpoint_del .delete ()
182
+
183
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_DEL , False )
184
+
185
+ try :
186
+ gdb .execute ("c" )
187
+ except Exception as e :
188
+ print ("[Error] (GDBFrontendSocket().gdb_on_stop__mT)" , e )
189
+ elif interrupted_for_breakpoint_mod :
190
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Continuing for interrupt: BREAKPOINT_MOD." )
191
+
192
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_MOD , False )
193
+
194
+ interrupted_for_breakpoint_mod ["breakpoint" ].condition = interrupted_for_breakpoint_mod ["condition" ]
195
+
196
+ try :
197
+ gdb .execute ("c" )
198
+ except Exception as e :
199
+ print ("[Error] (GDBFrontendSocket().gdb_on_stop__mT)" , e )
200
+ elif interrupted_for_breakpoint_set :
201
+ util .verbose ("GDBFrontendDebugEventsHandler" , "Continuing for interrupt: BREAKPOINT_SET." )
202
+
203
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_INTERRUPTED_FOR_BREAKPOINT_SET , False )
204
+
205
+ interrupted_for_breakpoint_set ["breakpoint" ].enabled = interrupted_for_breakpoint_set ["is_enabled" ]
206
+
207
+ try :
208
+ gdb .execute ("c" )
209
+ except Exception as e :
210
+ print ("[Error] (GDBFrontendSocket().gdb_on_stop__mT)" , e )
211
+
212
+ def gdb_on_new_thread (self , event ):
213
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_new_thread()" )
214
+
215
+ def _mt ():
216
+ self .gdb_on_new_thread__mT (event )
217
+
218
+ gdb .post_event (_mt )
219
+
220
+ def gdb_on_new_thread__mT (self , event ):
221
+ inferior_thread = event .inferior_thread
222
+
223
+ if isinstance (inferior_thread , gdb .InferiorThread ):
224
+ api .globalvars .inferior_run_times [event .inferior_thread .inferior .num ] = int (time .time ())
225
+ elif isinstance (inferior_thread , gdb .Inferior ):
226
+ api .globalvars .inferior_run_times [event .inferior_thread .num ] = int (time .time ())
227
+
228
+ def gdb_on_cont (self , event ):
229
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_cont()" )
230
+
231
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_RUNNING , True )
232
+
233
+ self .cont_time = time .time () * 1000
234
+
235
+ if api .globalvars .dont_emit_until_stop_or_exit : return
236
+
237
+ gdb .post_event (self .gdb_on_cont__mT )
238
+
239
+ def gdb_on_cont__mT (self ):
240
+ pass
241
+
242
+ def gdb_on_exited (self , event ):
243
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_exited()" )
244
+
245
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .IS_RUNNING , False )
246
+
247
+ api .globalvars .dont_emit_until_stop_or_exit = False
248
+ api .globalvars .step_time = False
249
+
250
+ def _mt ():
251
+ self .gdb_on_exited__mT (event )
252
+
253
+ gdb .post_event (_mt )
254
+
255
+ def gdb_on_exited__mT (self , event ):
256
+ response = {}
257
+
258
+ try :
259
+ del api .globalvars .inferior_run_times [event .inferior .num ]
260
+ except Exception as e :
261
+ util .verbose ("GDBFrontendDebugEventsHandler" , e , traceback .format_exc ())
262
+
263
+ api .globalvars .debugFlags .set (api .flags .AtomicDebugFlags .SELECTED_FRAMES , {})
264
+
265
+ def gdb_on_new_inferior (self , event ):
266
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_new_inferior()" )
267
+
268
+ api .globalvars .inferior_run_times [event .inferior .num ] = int (time .time ())
269
+
270
+ if api .globalvars .dont_emit_until_stop_or_exit : return
271
+
272
+ def _mt ():
273
+ self .gdb_on_new_inferior__mT (event )
274
+
275
+ gdb .post_event (_mt )
276
+
277
+ def gdb_on_new_inferior__mT (self , event ):
278
+ pass
279
+
280
+ def gdb_on_inferior_deleted (self , event ):
281
+ util .verbose ("GDBFrontendDebugEventsHandler" , "gdb_on_inferior_deleted()" )
282
+
283
+ def _mt ():
284
+ self .gdb_on_inferior_deleted__mT (event )
285
+
286
+ gdb .post_event (_mt )
287
+
288
+ def gdb_on_inferior_deleted__mT (self , event ):
289
+ response = {}
290
+
291
+ del api .globalvars .inferior_run_times [event .inferior .num ]
292
+
293
+ if api .globalvars .dont_emit_until_stop_or_exit : return
0 commit comments