xref: /llvm-project/openmp/libompd/gdb-plugin/ompd/ompd.py (revision d2a6e165e8980ed35fb4e5c7d468bfdc797b28c3)
1import ompdModule
2import gdb
3import re
4import traceback
5from ompd_address_space import ompd_address_space
6from ompd_handles import ompd_thread, ompd_task, ompd_parallel
7from frame_filter import FrameFilter
8from enum import Enum
9
10
11addr_space = None
12ff = None
13icv_map = None
14ompd_scope_map = {1:'global', 2:'address_space', 3:'thread', 4:'parallel', 5:'implicit_task', 6:'task'}
15in_task_function = False
16
17class ompd(gdb.Command):
18	def __init__(self):
19		super(ompd, self).__init__('ompd',
20			gdb.COMMAND_STATUS,
21			gdb.COMPLETE_NONE,
22			True)
23
24class ompd_init(gdb.Command):
25	"""Find and initialize ompd library"""
26
27	# first parameter is command-line input, second parameter is gdb-specific data
28	def __init__(self):
29		self.__doc__ = 'Find and initialize OMPD library\n usage: ompd init'
30		super(ompd_init, self).__init__('ompd init',
31						gdb.COMMAND_DATA)
32
33	def invoke(self, arg, from_tty):
34		global addr_space
35		global ff
36		try:
37			try:
38				print(gdb.newest_frame())
39			except:
40				gdb.execute("start")
41			try:
42				lib_list = gdb.parse_and_eval("(char**)ompd_dll_locations")
43			except gdb.error:
44				raise ValueError("No ompd_dll_locations symbol in execution, make sure to have an OMPD enabled OpenMP runtime");
45
46			while(gdb.parse_and_eval("(char**)ompd_dll_locations") == False):
47				gdb.execute("tbreak ompd_dll_locations_valid")
48				gdb.execute("continue")
49
50			lib_list = gdb.parse_and_eval("(char**)ompd_dll_locations")
51
52			i = 0
53			while(lib_list[i]):
54				ret = ompdModule.ompd_open(lib_list[i].string())
55				if ret == -1:
56					raise ValueError("Handle of OMPD library is not a valid string!")
57				if ret == -2:
58					print("ret == -2")
59					pass # It's ok to fail on dlopen
60				if ret == -3:
61					print("ret == -3")
62					pass # It's ok to fail on dlsym
63				if ret < -10:
64					raise ValueError("OMPD error code %i!" % (-10 - ret))
65
66				if ret > 0:
67					print("Loaded OMPD lib successfully!")
68					try:
69						addr_space = ompd_address_space()
70						ff = FrameFilter(addr_space)
71					except:
72						traceback.print_exc()
73					return
74				i = i+1
75
76			raise ValueError("OMPD library could not be loaded!")
77		except:
78			traceback.print_exc()
79
80class ompd_threads(gdb.Command):
81	"""Register thread ids of current context"""
82	def __init__(self):
83		self.__doc__ = 'Provide information on threads of current context.\n usage: ompd threads'
84		super(ompd_threads, self).__init__('ompd threads',
85						gdb.COMMAND_STATUS)
86
87	def invoke(self, arg, from_tty):
88		global addr_space
89		if init_error():
90			return
91		addr_space.list_threads(True)
92
93def print_parallel_region(curr_parallel, team_size):
94	"""Helper function for ompd_parallel_region. To print out the details of the parallel region."""
95	for omp_thr in range(team_size):
96		thread = curr_parallel.get_thread_in_parallel(omp_thr)
97		ompd_state = str(addr_space.states[thread.get_state()[0]])
98		ompd_wait_id = thread.get_state()[1]
99		task = curr_parallel.get_task_in_parallel(omp_thr)
100		task_func_addr = task.get_task_function()
101		# Get the function this addr belongs to
102		sal = gdb.find_pc_line(task_func_addr)
103		block = gdb.block_for_pc(task_func_addr)
104		while block and not block.function:
105			block = block.superblock
106		if omp_thr == 0:
107			print('%6d (master) %-37s %ld    0x%lx %-25s %-17s:%d' % \
108			(omp_thr, ompd_state, ompd_wait_id, task_func_addr, \
109			 block.function.print_name, sal.symtab.filename, sal.line))
110		else:
111			print('%6d          %-37s %ld    0x%lx %-25s %-17s:%d' % \
112			(omp_thr, ompd_state, ompd_wait_id, task_func_addr, \
113			 block.function.print_name, sal.symtab.filename, sal.line))
114
115class ompd_parallel_region(gdb.Command):
116	"""Parallel Region Details"""
117	def __init__(self):
118		self.__doc__ = 'Display the details of the current and enclosing parallel regions.\n usage: ompd parallel'
119		super(ompd_parallel_region, self).__init__('ompd parallel',
120							   gdb.COMMAND_STATUS)
121
122	def invoke(self, arg, from_tty):
123		global addr_space
124		if init_error():
125			return
126		if addr_space.icv_map is None:
127			addr_space.get_icv_map()
128		if addr_space.states is None:
129			addr_space.enumerate_states()
130		curr_thread_handle = addr_space.get_curr_thread()
131		curr_parallel_handle = curr_thread_handle.get_current_parallel_handle()
132		curr_parallel = ompd_parallel(curr_parallel_handle)
133		while curr_parallel_handle is not None and curr_parallel is not None:
134			nest_level = ompdModule.call_ompd_get_icv_from_scope(curr_parallel_handle,\
135				     addr_space.icv_map['levels-var'][1], addr_space.icv_map['levels-var'][0])
136			if nest_level == 0:
137				break
138			team_size = ompdModule.call_ompd_get_icv_from_scope(curr_parallel_handle, \
139				    addr_space.icv_map['team-size-var'][1], \
140				    addr_space.icv_map['team-size-var'][0])
141			print ("")
142			print ("Parallel Region: Nesting Level %d: Team Size: %d" % (nest_level, team_size))
143			print ("================================================")
144			print ("")
145			print ("OMP Thread Nbr  Thread State                     Wait Id  EntryAddr FuncName                 File:Line");
146			print ("======================================================================================================");
147			print_parallel_region(curr_parallel, team_size)
148			enclosing_parallel = curr_parallel.get_enclosing_parallel()
149			enclosing_parallel_handle = curr_parallel.get_enclosing_parallel_handle()
150			curr_parallel = enclosing_parallel
151			curr_parallel_handle = enclosing_parallel_handle
152
153class ompd_icvs(gdb.Command):
154	"""ICVs"""
155	def __init__(self):
156		self.__doc__ = 'Display the values of the Internal Control Variables.\n usage: ompd icvs'
157		super(ompd_icvs, self).__init__('ompd icvs',
158						 gdb.COMMAND_STATUS)
159
160	def invoke(self, arg, from_tty):
161		global addr_space
162		global ompd_scope_map
163		if init_error():
164			return
165		curr_thread_handle = addr_space.get_curr_thread()
166		if addr_space.icv_map is None:
167			addr_space.get_icv_map()
168		print("ICV Name                        Scope                     Value")
169		print("===============================================================")
170
171		try:
172			for icv_name in addr_space.icv_map:
173				scope = addr_space.icv_map[icv_name][1]
174				#{1:'global', 2:'address_space', 3:'thread', 4:'parallel', 5:'implicit_task', 6:'task'}
175				if scope == 2:
176					handle = addr_space.addr_space
177				elif scope == 3:
178					handle = curr_thread_handle.thread_handle
179				elif scope == 4:
180					handle = curr_thread_handle.get_current_parallel_handle()
181				elif scope == 6:
182					handle = curr_thread_handle.get_current_task_handle()
183				else:
184					raise ValueError("Invalid scope")
185
186				if (icv_name == "nthreads-var" or icv_name == "bind-var"):
187					icv_value = ompdModule.call_ompd_get_icv_from_scope(
188						    handle, scope, addr_space.icv_map[icv_name][0])
189					if icv_value is None:
190						icv_string = ompdModule.call_ompd_get_icv_string_from_scope( \
191							     handle, scope, addr_space.icv_map[icv_name][0])
192						print('%-31s %-26s %s' % (icv_name, ompd_scope_map[scope], icv_string))
193					else:
194						print('%-31s %-26s %d' % (icv_name, ompd_scope_map[scope], icv_value))
195
196				elif (icv_name == "affinity-format-var" or icv_name == "run-sched-var" or \
197                                         icv_name == "tool-libraries-var" or icv_name == "tool-verbose-init-var"):
198					icv_string = ompdModule.call_ompd_get_icv_string_from_scope( \
199						     handle, scope, addr_space.icv_map[icv_name][0])
200					print('%-31s %-26s %s' % (icv_name, ompd_scope_map[scope], icv_string))
201				else:
202					icv_value = ompdModule.call_ompd_get_icv_from_scope(handle, \
203						    scope, addr_space.icv_map[icv_name][0])
204					print('%-31s %-26s %d' % (icv_name, ompd_scope_map[scope], icv_value))
205		except:
206		       traceback.print_exc()
207
208def curr_thread():
209	"""Helper function for ompd_step. Returns the thread object for the current thread number."""
210	global addr_space
211	if addr_space is not None:
212		return addr_space.threads[int(gdb.selected_thread().num)]
213	return None
214
215class ompd_test(gdb.Command):
216	"""Test area"""
217	def __init__(self):
218		self.__doc__ = 'Test functionalities for correctness\n usage: ompd test'
219		super(ompd_test, self).__init__('ompd test',
220						gdb.COMMAND_OBSCURE)
221
222	def invoke(self, arg, from_tty):
223		global addr_space
224		if init_error():
225			return
226		# get task function for current task of current thread
227		try:
228			current_thread = int(gdb.selected_thread().num)
229			current_thread_obj = addr_space.threads[current_thread]
230			task_function = current_thread_obj.get_current_task().get_task_function()
231			print("bt value:", int("0x0000000000400b6c",0))
232			print("get_task_function value:", task_function)
233
234			# get task function of implicit task in current parallel region for current thread
235			current_parallel_obj = current_thread_obj.get_current_parallel()
236			task_in_parallel = current_parallel_obj.get_task_in_parallel(current_thread)
237			task_function_in_parallel = task_in_parallel.get_task_function()
238			print("task_function_in_parallel:", task_function_in_parallel)
239		except:
240			print('Task function value not found for this thread')
241
242class ompdtestapi (gdb.Command):
243	""" To test API's return code """
244	def __init__(self):
245		self.__doc__ = 'Test OMPD tool Interface APIs.\nUsage: ompdtestapi <api name>'
246		super (ompdtestapi, self).__init__('ompdtestapi', gdb.COMMAND_OBSCURE)
247
248	def invoke (self, arg, from_tty):
249		global addr_space
250		if init_error():
251			print ("Error in Initialization.");
252			return
253		if not arg:
254			print ("No API provided to test, eg: ompdtestapi ompd_initialize")
255
256		if arg == "ompd_get_thread_handle":
257			addr_handle = addr_space.addr_space
258			threadId = gdb.selected_thread().ptid[1]
259			ompdModule.test_ompd_get_thread_handle(addr_handle, threadId)
260		elif arg == "ompd_get_curr_parallel_handle":
261			addr_handle = addr_space.addr_space
262			threadId = gdb.selected_thread().ptid[1]
263			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
264			ompdModule.test_ompd_get_curr_parallel_handle(thread_handle)
265		elif arg == "ompd_get_thread_in_parallel":
266			addr_handle = addr_space.addr_space
267			threadId = gdb.selected_thread().ptid[1]
268			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
269			parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
270			ompdModule.test_ompd_get_thread_in_parallel(parallel_handle)
271		elif arg == "ompd_thread_handle_compare":
272			addr_handle = addr_space.addr_space
273			threadId = gdb.selected_thread().ptid[1]
274			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
275			parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
276			thread_handle1 = ompdModule.call_ompd_get_thread_in_parallel(parallel_handle, 1);
277			thread_handle2 = ompdModule.call_ompd_get_thread_in_parallel(parallel_handle, 2);
278			ompdModule.test_ompd_thread_handle_compare(thread_handle1, thread_handle1)
279			ompdModule.test_ompd_thread_handle_compare(thread_handle1, thread_handle2)
280		elif arg == "ompd_get_thread_id":
281			addr_handle = addr_space.addr_space
282			threadId = gdb.selected_thread().ptid[1]
283			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
284			ompdModule.test_ompd_get_thread_id(thread_handle)
285		elif arg == "ompd_rel_thread_handle":
286			addr_handle = addr_space.addr_space
287			threadId = gdb.selected_thread().ptid[1]
288			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
289			ompdModule.test_ompd_rel_thread_handle(thread_handle)
290		elif arg == "ompd_get_enclosing_parallel_handle":
291			addr_handle = addr_space.addr_space
292			threadId = gdb.selected_thread().ptid[1]
293			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
294			parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
295			ompdModule.test_ompd_get_enclosing_parallel_handle(parallel_handle)
296		elif arg == "ompd_parallel_handle_compare":
297			addr_handle = addr_space.addr_space
298			threadId = gdb.selected_thread().ptid[1]
299			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
300			parallel_handle1 = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
301			parallel_handle2 = ompdModule.call_ompd_get_enclosing_parallel_handle(parallel_handle1)
302			ompdModule.test_ompd_parallel_handle_compare(parallel_handle1, parallel_handle1)
303			ompdModule.test_ompd_parallel_handle_compare(parallel_handle1, parallel_handle2)
304		elif arg == "ompd_rel_parallel_handle":
305			addr_handle = addr_space.addr_space
306			threadId = gdb.selected_thread().ptid[1]
307			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
308			parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
309			ompdModule.test_ompd_rel_parallel_handle(parallel_handle)
310		elif arg == "ompd_initialize":
311			ompdModule.test_ompd_initialize()
312		elif arg == "ompd_get_api_version":
313			ompdModule.test_ompd_get_api_version()
314		elif arg == "ompd_get_version_string":
315			ompdModule.test_ompd_get_version_string()
316		elif arg == "ompd_finalize":
317			ompdModule.test_ompd_finalize()
318		elif arg == "ompd_process_initialize":
319			ompdModule.call_ompd_initialize()
320			ompdModule.test_ompd_process_initialize()
321		elif arg == "ompd_device_initialize":
322			ompdModule.test_ompd_device_initialize()
323		elif arg == "ompd_rel_address_space_handle":
324			ompdModule.test_ompd_rel_address_space_handle()
325		elif arg == "ompd_get_omp_version":
326			addr_handle = addr_space.addr_space
327			ompdModule.test_ompd_get_omp_version(addr_handle)
328		elif arg == "ompd_get_omp_version_string":
329			addr_handle = addr_space.addr_space
330			ompdModule.test_ompd_get_omp_version_string(addr_handle)
331		elif arg == "ompd_get_curr_task_handle":
332			addr_handle = addr_space.addr_space
333			threadId = gdb.selected_thread().ptid[1]
334			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
335			ompdModule.test_ompd_get_curr_task_handle(thread_handle)
336		elif arg == "ompd_get_task_parallel_handle":
337			addr_handle = addr_space.addr_space
338			threadId = gdb.selected_thread().ptid[1]
339			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
340			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
341			ompdModule.test_ompd_get_task_parallel_handle(task_handle)
342		elif arg == "ompd_get_generating_task_handle":
343			addr_handle = addr_space.addr_space
344			threadId = gdb.selected_thread().ptid[1]
345			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
346			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
347			ompdModule.test_ompd_get_generating_task_handle(task_handle)
348		elif arg == "ompd_get_scheduling_task_handle":
349			addr_handle = addr_space.addr_space
350			threadId = gdb.selected_thread().ptid[1]
351			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
352			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
353			ompdModule.test_ompd_get_scheduling_task_handle(task_handle)
354		elif arg == "ompd_get_task_in_parallel":
355			addr_handle = addr_space.addr_space
356			threadId = gdb.selected_thread().ptid[1]
357			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
358			parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
359			ompdModule.test_ompd_get_task_in_parallel(parallel_handle)
360		elif arg == "ompd_rel_task_handle":
361			addr_handle = addr_space.addr_space
362			threadId = gdb.selected_thread().ptid[1]
363			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
364			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
365			ompdModule.test_ompd_rel_task_handle(task_handle)
366		elif arg == "ompd_task_handle_compare":
367			addr_handle = addr_space.addr_space
368			threadId = gdb.selected_thread().ptid[1]
369			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
370			task_handle1 = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
371			task_handle2 = ompdModule.call_ompd_get_generating_task_handle(task_handle1)
372			ompdModule.test_ompd_task_handle_compare(task_handle1, task_handle2)
373			ompdModule.test_ompd_task_handle_compare(task_handle2, task_handle1)
374		elif arg == "ompd_get_task_function":
375			addr_handle = addr_space.addr_space
376			threadId = gdb.selected_thread().ptid[1]
377			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
378			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
379			ompdModule.test_ompd_get_task_function(task_handle)
380		elif arg == "ompd_get_task_frame":
381			addr_handle = addr_space.addr_space
382			threadId = gdb.selected_thread().ptid[1]
383			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
384			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
385			ompdModule.test_ompd_get_task_frame(task_handle)
386		elif arg == "ompd_get_state":
387			addr_handle = addr_space.addr_space
388			threadId = gdb.selected_thread().ptid[1]
389			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
390			ompdModule.test_ompd_get_state(thread_handle)
391		elif arg == "ompd_get_display_control_vars":
392			addr_handle = addr_space.addr_space
393			ompdModule.test_ompd_get_display_control_vars(addr_handle)
394		elif arg == "ompd_rel_display_control_vars":
395			ompdModule.test_ompd_rel_display_control_vars()
396		elif arg == "ompd_enumerate_icvs":
397			addr_handle = addr_space.addr_space
398			ompdModule.test_ompd_enumerate_icvs(addr_handle)
399		elif arg== "ompd_get_icv_from_scope":
400			addr_handle = addr_space.addr_space
401			threadId = gdb.selected_thread().ptid[1]
402			thread_handle = ompdModule.get_thread_handle(threadId, addr_handle)
403			parallel_handle = ompdModule.call_ompd_get_curr_parallel_handle(thread_handle)
404			task_handle = ompdModule.call_ompd_get_curr_task_handle(thread_handle)
405			ompdModule.test_ompd_get_icv_from_scope_with_addr_handle(addr_handle)
406			ompdModule.test_ompd_get_icv_from_scope_with_thread_handle(thread_handle)
407			ompdModule.test_ompd_get_icv_from_scope_with_parallel_handle(parallel_handle)
408			ompdModule.test_ompd_get_icv_from_scope_with_task_handle(task_handle)
409		elif arg == "ompd_get_icv_string_from_scope":
410			addr_handle = addr_space.addr_space
411			ompdModule.test_ompd_get_icv_string_from_scope(addr_handle)
412		elif arg == "ompd_get_tool_data":
413			ompdModule.test_ompd_get_tool_data()
414		elif arg == "ompd_enumerate_states":
415			ompdModule.test_ompd_enumerate_states()
416		else:
417			print ("Invalid API.")
418
419
420
421class ompd_bt(gdb.Command):
422	"""Turn filter for 'bt' on/off for output to only contain frames relevant to the application or all frames."""
423	def __init__(self):
424		self.__doc__ = 'Turn filter for "bt" output on or off. Specify "on continued" option to trace worker threads back to master threads.\n usage: ompd bt on|on continued|off'
425		super(ompd_bt, self).__init__('ompd bt',
426					gdb.COMMAND_STACK)
427
428	def invoke(self, arg, from_tty):
429		global ff
430		global addr_space
431		global icv_map
432		global ompd_scope_map
433		if init_error():
434			return
435		if icv_map is None:
436			icv_map = {}
437			current = 0
438			more = 1
439			while more > 0:
440				tup = ompdModule.call_ompd_enumerate_icvs(addr_space.addr_space, current)
441				(current, next_icv, next_scope, more) = tup
442				icv_map[next_icv] = (current, next_scope, ompd_scope_map[next_scope])
443			print('Initialized ICV map successfully for filtering "bt".')
444
445		arg_list = gdb.string_to_argv(arg)
446		if len(arg_list) == 0:
447			print('When calling "ompd bt", you must either specify "on", "on continued" or "off". Check "help ompd".')
448		elif len(arg_list) == 1 and arg_list[0] == 'on':
449			addr_space.list_threads(False)
450			ff.set_switch(True)
451			ff.set_switch_continue(False)
452		elif arg_list[0] == 'on' and arg_list[1] == 'continued':
453			ff.set_switch(True)
454			ff.set_switch_continue(True)
455		elif len(arg_list) == 1 and arg_list[0] == 'off':
456			ff.set_switch(False)
457			ff.set_switch_continue(False)
458		else:
459			print('When calling "ompd bt", you must either specify "on", "on continued" or "off". Check "help ompd".')
460
461# TODO: remove
462class ompd_taskframes(gdb.Command):
463	"""Prints task handles for relevant task frames. Meant for debugging."""
464	def __init__(self):
465		self.__doc__ = 'Prints list of tasks.\nUsage: ompd taskframes'
466		super(ompd_taskframes, self).__init__('ompd taskframes',
467					gdb.COMMAND_STACK)
468
469	def invoke(self, arg, from_tty):
470		global addr_space
471		if init_error():
472			return
473		frame = gdb.newest_frame()
474		while(frame):
475			print (frame.read_register('sp'))
476			frame = frame.older()
477		curr_task_handle = None
478		if(addr_space.threads and addr_space.threads.get(gdb.selected_thread().num)):
479			curr_thread_handle = curr_thread().thread_handle
480			curr_task_handle = ompdModule.call_ompd_get_curr_task_handle(curr_thread_handle)
481		if(not curr_task_handle):
482			return None
483		prev_frames = None
484		try:
485			while(1):
486				frames_with_flags = ompdModule.call_ompd_get_task_frame(curr_task_handle)
487				frames = (frames_with_flags[0], frames_with_flags[3])
488				if(prev_frames == frames):
489					break
490				if(not isinstance(frames,tuple)):
491					break
492				(ompd_enter_frame, ompd_exit_frame) = frames
493				print(hex(ompd_enter_frame), hex(ompd_exit_frame))
494				curr_task_handle = ompdModule.call_ompd_get_scheduling_task_handle(curr_task_handle)
495				prev_frames = frames
496				if(not curr_task_handle):
497					break
498		except:
499			traceback.print_exc()
500
501def print_and_exec(string):
502	"""Helper function for ompd_step. Executes the given command in GDB and prints it."""
503	print(string)
504	gdb.execute(string)
505
506class TempFrameFunctionBp(gdb.Breakpoint):
507	"""Helper class for ompd_step. Defines stop function for breakpoint on frame function."""
508	def stop(self):
509		global in_task_function
510		in_task_function = True
511		self.enabled = False
512
513class ompd_step(gdb.Command):
514	"""Executes 'step' and skips frames irrelevant to the application / the ones without debug information."""
515	def __init__(self):
516		self.__doc__ = 'Executes "step" and skips runtime frames as much as possible.'
517		super(ompd_step, self).__init__('ompd step', gdb.COMMAND_STACK)
518
519	class TaskBeginBp(gdb.Breakpoint):
520		"""Helper class. Defines stop function for breakpoint ompd_bp_task_begin."""
521		def stop(self):
522			try:
523				code_line = curr_thread().get_current_task().get_task_function()
524				frame_fct_bp = TempFrameFunctionBp(('*%i' % code_line), temporary=True, internal=True)
525				frame_fct_bp.thread = self.thread
526				return False
527			except:
528				return False
529
530	def invoke(self, arg, from_tty):
531		global in_task_function
532		if init_error():
533			return
534		tbp = self.TaskBeginBp('ompd_bp_task_begin', temporary=True, internal=True)
535		tbp.thread = int(gdb.selected_thread().num)
536		print_and_exec('step')
537		while gdb.selected_frame().find_sal().symtab is None:
538			if not in_task_function:
539				print_and_exec('finish')
540			else:
541				print_and_exec('si')
542
543def init_error():
544	global addr_space
545	if (gdb.selected_thread() is None) or (addr_space is None) or (not addr_space):
546		print("Run 'ompd init' before running any of the ompd commands")
547		return True
548	return False
549
550def main():
551	ompd()
552	ompd_init()
553	ompd_threads()
554	ompd_icvs()
555	ompd_parallel_region()
556	ompd_test()
557	ompdtestapi()
558	ompd_taskframes()
559	ompd_bt()
560	ompd_step()
561
562if __name__ == "__main__":
563	try:
564		main()
565	except:
566		traceback.print_exc()
567
568# NOTE: test code using:
569# OMP_NUM_THREADS=... gdb a.out -x ../../projects/gdb_plugin/gdb-ompd/__init__.py
570# ompd init
571# ompd threads
572