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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
import gdb
import ompdModule
import itertools
from gdb.FrameDecorator import FrameDecorator
import ompd
from ompd_handles import ompd_task, ompd_parallel, ompd_thread
import traceback
from tempfile import NamedTemporaryFile
class OmpdFrameDecorator(FrameDecorator):
def __init__(self, fobj, curr_task_handle):
"""Initializes a FrameDecorator with the given GDB Frame object. The global OMPD address space defined in
ompd.py is set as well.
"""
super(OmpdFrameDecorator, self).__init__(fobj)
self.addr_space = ompd.addr_space
self.fobj = None
if isinstance(fobj, gdb.Frame):
self.fobj = fobj
elif isinstance(fobj, FrameDecorator):
self.fobj = fobj.inferior_frame()
self.curr_task_handle = curr_task_handle
def function(self):
"""This appends the name of a frame that is printed with the information whether the task started in the frame
is implicit or explicit. The ICVs are evaluated to determine that.
"""
name = str(self.fobj.name())
if self.curr_task_handle is None:
return name
icv_value = ompdModule.call_ompd_get_icv_from_scope(
self.curr_task_handle,
ompd.icv_map["implicit-task-var"][1],
ompd.icv_map["implicit-task-var"][0],
)
if icv_value == 0:
name = '@thread %i: %s "#pragma omp task"' % (
gdb.selected_thread().num,
name,
)
elif icv_value == 1:
name = '@thread %i: %s "#pragma omp parallel"' % (
gdb.selected_thread().num,
name,
)
else:
name = "@thread %i: %s" % (gdb.selected_thread().num, name)
return name
class OmpdFrameDecoratorThread(FrameDecorator):
def __init__(self, fobj):
"""Initializes a FrameDecorator with the given GDB Frame object."""
super(OmpdFrameDecoratorThread, self).__init__(fobj)
if isinstance(fobj, gdb.Frame):
self.fobj = fobj
elif isinstance(fobj, FrameDecorator):
self.fobj = fobj.inferior_frame()
def function(self):
name = str(self.fobj.name())
return "@thread %i: %s" % (gdb.selected_thread().num, name)
class FrameFilter:
def __init__(self, addr_space):
"""Initializes the FrameFilter, registers is in the GDB runtime and saves the given OMPD address space capsule."""
self.addr_space = addr_space
self.name = "Filter"
self.priority = 100
self.enabled = True
gdb.frame_filters[self.name] = self
self.switched_on = False
self.continue_to_master = False
def set_switch(self, on_off):
"""Prints output when executing 'ompd bt on' or 'ompd bt off'."""
self.switched_on = on_off
if self.switched_on:
print('Enabled filter for "bt" output successfully.')
else:
print('Disabled filter for "bt" output successfully.')
def set_switch_continue(self, on_off):
"""Prints output when executing 'ompd bt on continued'." """
self.continue_to_master = on_off
if self.continue_to_master:
print(
'Enabled "bt" mode that continues backtrace on to master thread for worker threads.'
)
else:
print('Disabled "bt" mode that continues onto master thread.')
def get_master_frames_for_worker(self, past_thread_num, latest_sp):
"""Prints master frames for worker thread with id past_thread_num."""
gdb.execute("t 1")
gdb.execute("ompd bt on")
gdb.execute("bt")
frame = gdb.newest_frame()
while frame.older() is not None:
print("master frame sp:", str(frame.read_register("sp")))
yield OmpdFrameDecorator(frame)
frame = frame.older()
print("latest sp:", str(latest_sp))
gdb.execute("ompd bt on continued")
gdb.execute("t %d" % int(past_thread_num))
def filter_frames(self, frame_iter):
"""Iterates through frames and only returns those that are relevant to the application
being debugged. The OmpdFrameDecorator is applied automatically.
"""
curr_thread_num = gdb.selected_thread().num
is_no_omp_thread = False
if curr_thread_num in self.addr_space.threads:
curr_thread_obj = self.addr_space.threads[curr_thread_num]
self.curr_task = curr_thread_obj.get_current_task()
self.frames = self.curr_task.get_task_frame()
else:
is_no_omp_thread = True
print(
"Thread %d is no OpenMP thread, printing all frames:" % curr_thread_num
)
stop_iter = False
for x in frame_iter:
if is_no_omp_thread:
yield OmpdFrameDecoratorThread(x)
continue
if x.inferior_frame().older() is None:
continue
if self.curr_task.task_handle is None:
continue
gdb_sp = int(str(x.inferior_frame().read_register("sp")), 16)
gdb_sp_next_new = int(
str(x.inferior_frame()).split(",")[0].split("=")[1], 16
)
if x.inferior_frame().older():
gdb_sp_next = int(
str(x.inferior_frame().older().read_register("sp")), 16
)
else:
gdb_sp_next = int(str(x.inferior_frame().read_register("sp")), 16)
while 1:
(ompd_enter_frame, ompd_exit_frame) = self.frames
if ompd_enter_frame != 0 and gdb_sp_next_new < ompd_enter_frame:
break
if ompd_exit_frame != 0 and gdb_sp_next_new < ompd_exit_frame:
if (
x.inferior_frame().older().older()
and int(
str(x.inferior_frame().older().older().read_register("sp")),
16,
)
< ompd_exit_frame
):
if self.continue_to_master:
yield OmpdFrameDecoratorThread(x)
else:
yield OmpdFrameDecorator(x, self.curr_task.task_handle)
else:
yield OmpdFrameDecorator(x, self.curr_task.task_handle)
break
sched_task_handle = self.curr_task.get_scheduling_task_handle()
if sched_task_handle is None:
stop_iter = True
break
self.curr_task = self.curr_task.get_scheduling_task()
self.frames = self.curr_task.get_task_frame()
if stop_iter:
break
# implementation of "ompd bt continued"
if self.continue_to_master:
orig_thread = gdb.selected_thread().num
gdb_threads = dict([(t.num, t) for t in gdb.selected_inferior().threads()])
# iterate through generating tasks until outermost task is reached
while 1:
# get OMPD thread id for master thread (systag in GDB output)
try:
master_num = (
self.curr_task.get_task_parallel()
.get_thread_in_parallel(0)
.get_thread_id()
)
except:
break
# search for thread id without the "l" for long via "thread find" and get GDB thread num from output
hex_str = str(hex(master_num))
thread_output = gdb.execute(
"thread find %s" % hex_str[0 : len(hex_str) - 1], to_string=True
).split(" ")
if thread_output[0] == "No":
raise ValueError("Master thread num could not be found!")
gdb_master_num = int(thread_output[1])
# get task that generated last task of worker thread
try:
self.curr_task = (
self.curr_task.get_task_parallel()
.get_task_in_parallel(0)
.get_generating_task()
)
except:
break
self.frames = self.curr_task.get_task_frame()
(enter_frame, exit_frame) = self.frames
if exit_frame == 0:
print("outermost generating task was reached")
break
# save GDB num for worker thread to change back to it later
worker_thread = gdb.selected_thread().num
# use InferiorThread.switch()
gdb_threads = dict(
[(t.num, t) for t in gdb.selected_inferior().threads()]
)
gdb_threads[gdb_master_num].switch()
print("#### switching to thread %i ####" % gdb_master_num)
frame = gdb.newest_frame()
stop_iter = False
while not stop_iter:
if self.curr_task.task_handle is None:
break
self.frames = self.curr_task.get_task_frame()
while frame:
if self.curr_task.task_handle is None:
break
gdb_sp_next_new = int(
str(frame).split(",")[0].split("=")[1], 16
)
if frame.older():
gdb_sp_next = int(
str(frame.older().read_register("sp")), 16
)
else:
gdb_sp_next = int(str(frame.read_register("sp")), 16)
while 1:
(ompd_enter_frame, ompd_exit_frame) = self.frames
if (
ompd_enter_frame != 0
and gdb_sp_next_new < ompd_enter_frame
):
break
if (
ompd_exit_frame == 0
or gdb_sp_next_new < ompd_exit_frame
):
if (
ompd_exit_frame == 0
or frame.older()
and frame.older().older()
and int(
str(frame.older().older().read_register("sp")),
16,
)
< ompd_exit_frame
):
yield OmpdFrameDecoratorThread(frame)
else:
yield OmpdFrameDecorator(
frame, self.curr_task.task_handle
)
break
sched_task_handle = (
ompdModule.call_ompd_get_scheduling_task_handle(
self.curr_task.task_handle
)
)
if sched_task_handle is None:
stop_iter = True
break
self.curr_task = self.curr_task.get_generating_task()
self.frames = self.curr_task.get_task_frame()
frame = frame.older()
break
gdb_threads[worker_thread].switch()
gdb_threads[orig_thread].switch()
def filter(self, frame_iter):
"""Function is called automatically with every 'bt' executed. If switched on, this will only let revelant frames be printed
or all frames otherwise. If switched on, a FrameDecorator will be applied to state whether '.ompd_task_entry.' refers to an
explicit or implicit task.
"""
if self.switched_on:
return self.filter_frames(frame_iter)
else:
return frame_iter
|