1#- 2# Copyright (c) 2022 The FreeBSD Foundation 3# 4# This software was developed by Mark Johnston under sponsorship from the 5# FreeBSD Foundation. 6# 7 8import gdb 9 10 11def symval(name): 12 return gdb.lookup_global_symbol(name).value() 13 14 15def tid_to_gdb_thread(tid): 16 for thread in gdb.inferiors()[0].threads(): 17 if thread.ptid[2] == tid: 18 return thread 19 else: 20 return None 21 22 23def all_pcpus(): 24 mp_maxid = symval("mp_maxid") 25 cpuid_to_pcpu = symval("cpuid_to_pcpu") 26 27 cpu = 0 28 while cpu <= mp_maxid: 29 pcpu = cpuid_to_pcpu[cpu] 30 if pcpu: 31 yield pcpu 32 cpu = cpu + 1 33 34 35class acttrace(gdb.Command): 36 def __init__(self): 37 super(acttrace, self).__init__("acttrace", gdb.COMMAND_USER) 38 39 def invoke(self, arg, from_tty): 40 # Save the current thread so that we can switch back after. 41 curthread = gdb.selected_thread() 42 43 for pcpu in all_pcpus(): 44 td = pcpu['pc_curthread'] 45 tid = td['td_tid'] 46 47 gdb_thread = tid_to_gdb_thread(tid) 48 if gdb_thread is None: 49 print("failed to find GDB thread with TID {}".format(tid)) 50 else: 51 gdb_thread.switch() 52 53 p = td['td_proc'] 54 print("Tracing command {} pid {} tid {} (CPU {})".format( 55 p['p_comm'], p['p_pid'], td['td_tid'], pcpu['pc_cpuid'])) 56 gdb.execute("bt") 57 print() 58 59 curthread.switch() 60 61 62# Registers the command with gdb, doesn't do anything. 63acttrace() 64