1from core import xnu_format, iter_SLIST_HEAD 2from xnu import * 3import sys, shlex 4from utils import * 5from waitq import * 6import kmemory 7import xnudefines 8 9@lldb_type_summary(['struct turnstile *']) 10@header("{0: <20s} {1: <5s} {2: <20s} {3: <8s} {4: <8s} {5: <23s} {6: <20s} {7: <10s} {8: <10s} {9: <20s} {10: <20s}".format( 11 "turnstile", "pri", "waitq", "type", "state", "inheritor", "proprietor", "gen cnt", "prim cnt", "thread", "prev_thread")) 12def GetTurnstileSummary(turnstile): 13 """ Summarizes the turnstile 14 params: turnstile = value of the object of type struct turnstile * 15 returns: String with summary of the type. 16 """ 17 18 ts_v = turnstile.GetSBValue() 19 ts_tg = ts_v.xGetScalarByName('ts_type_gencount') 20 ts_type = ts_tg & 0xff 21 ts_gen = ts_tg >> 8 22 23 if ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_NONE'): 24 turnstile_type = "none " 25 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_KERNEL_MUTEX'): 26 turnstile_type = "knl_mtx" 27 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_ULOCK'): 28 turnstile_type = "ulock " 29 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_PTHREAD_MUTEX'): 30 turnstile_type = "pth_mtx" 31 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_SYNC_IPC'): 32 turnstile_type = "syn_ipc" 33 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_WORKLOOPS'): 34 turnstile_type = "kqwl " 35 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_WORKQS'): 36 turnstile_type = "workq " 37 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_KNOTE'): 38 turnstile_type = "knote " 39 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_SLEEP_INHERITOR'): 40 turnstile_type = "slp_inh" 41 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_EPOCH_KERNEL'): 42 turnstile_type = "epoch_k" 43 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_EPOCH_USER'): 44 turnstile_type = "epoch_u" 45 else: 46 turnstile_type = " " 47 48 ts_state = ts_v.xGetScalarByName('ts_state') 49 if ts_state & 0x1: 50 turnstile_state = "T" 51 elif ts_state & 0x2: 52 turnstile_state = "F" 53 elif ts_state & 0x4: 54 turnstile_state = "H" 55 elif ts_state & 0x8: 56 turnstile_state = "P" 57 else: 58 turnstile_state = "" 59 60 ts_inheritor_flags = ts_v.xGetScalarByName('ts_inheritor_flags') 61 if ts_inheritor_flags & 0x4: 62 inheritor_type = "th" 63 elif ts_inheritor_flags & 0x8: 64 inheritor_type = "ts" 65 elif ts_inheritor_flags & 0x40: 66 inheritor_type = "wq" 67 else: 68 inheritor_type = "--" 69 70 format_str = ( 71 "{&ts_v: <#020x}" 72 " {$ts_v.ts_priority: <5d}" 73 " {&ts_v.ts_waitq: <#020x}" 74 " {0: <8s}" 75 " {1: <8s}" 76 " {2: <2s}:{$ts_v.ts_waitq.waitq_inheritor: <#020x}" 77 " {$ts_v.ts_proprietor: <#020x}" 78 " {3: <10d}" 79 " {$ts_v.ts_prim_count: <10d}" 80 ) 81 if hasattr(turnstile, 'ts_thread'): 82 format_str += ( 83 " {$ts_v.ts_thread: <#020x}" 84 " {$ts_v.ts_prev_thread: <#020x}" 85 ) 86 87 return xnu_format(format_str, 88 turnstile_type, turnstile_state, inheritor_type, ts_gen, 89 ts_v=ts_v) 90 91 92def PrintTurnstile(turnstile, O=None): 93 """ print turnstile and it's free list. 94 params: 95 turnstile - turnstile to print 96 """ 97 print(GetTurnstileSummary(turnstile)) 98 99 """ print turnstile freelist if its not on a thread or freelist """ 100 101 waitq = Waitq(addressof(turnstile.ts_waitq)) 102 if waitq.hasThreads(): 103 with O.table(GetWaitqSummary.header): 104 ShowWaitqHelper(waitq, O=O) 105 106 if turnstile.ts_state & 0x3 == 0: 107 needsHeader = True 108 for free_turnstile in IterateListEntry(turnstile.ts_free_turnstiles, 'ts_free_elm', 's'): 109 if needsHeader: 110 print("Turnstile free List:") 111 header_str = " " + GetTurnstileSummary.header 112 print(header_str) 113 needsHeader = False 114 print(" " + GetTurnstileSummary(free_turnstile)) 115 116# Macro: showturnstile 117@lldb_command('showturnstile', fancy=True) 118def ShowTurnstile(cmd_args=None, cmd_options={}, O=None): 119 """ show the turnstile and all free turnstiles hanging off the turnstile. 120 Usage: (lldb)showturnstile <struct turnstile *> 121 """ 122 if cmd_args is None or len(cmd_args) == 0: 123 raise ArgumentError("Please provide arguments") 124 125 turnstile = kern.GetValueFromAddress(cmd_args[0], 'struct turnstile *') 126 with O.table(GetTurnstileSummary.header): 127 PrintTurnstile(dereference(turnstile), O=O) 128# EndMacro: showturnstile 129 130@lldb_command('showturnstilehashtable', fancy=True) 131def ShowTurnstileHashTable(cmd_args=None, cmd_options={}, O=None): 132 """ show the global hash table for turnstiles. 133 Usage: (lldb)showturnstilehashtable 134 """ 135 with O.table(GetTurnstileSummary.header): 136 turnstile_htable_buckets = kern.globals.ts_htable_buckets 137 for index in range(0, turnstile_htable_buckets): 138 turnstile_bucket = GetObjectAtIndexFromArray(kern.globals.turnstile_htable, index) 139 for turnstile in iter_SLIST_HEAD(turnstile_bucket.ts_ht_bucket_list.GetSBValue(), 'ts_htable_link'): 140 PrintTurnstile(turnstile, O=O) 141 142# Macro: showallturnstiles 143@lldb_command('showallturnstiles', fancy=True) 144def ShowAllTurnstiles(cmd_args=None, cmd_options={}, O=None): 145 """ A macro that walks the list of all allocated turnstile objects and prints them. 146 usage: (lldb) showallturnstiles 147 """ 148 with O.table(GetTurnstileSummary.header): 149 ts_ty = gettype('struct turnstile') 150 for ts in kmemory.Zone("turnstiles").iter_allocated(ts_ty): 151 PrintTurnstile(value(ts), O=O) 152# EndMacro showallturnstiles 153 154# Macro: showallbusyturnstiles 155@lldb_command('showallbusyturnstiles', 'V', fancy=True) 156def ShowAllBusyTurnstiles(cmd_args=None, cmd_options={}, O=None): 157 """ A macro that walks the list of all allocated turnstile objects 158 and prints them. 159 usage: (lldb) showallbusyturnstiles [-V] 160 161 -V Even show turnstiles with no waiters (but with a proprietor) 162 """ 163 164 verbose = "-V" in cmd_options 165 166 def ts_is_interesting(ts): 167 if not ts.xGetScalarByName('ts_proprietor'): 168 # not owned by any primitive 169 return False 170 if verbose: 171 return True 172 return ts.xGetScalarByPath('.ts_waitq.waitq_prio_queue.pq_root') 173 174 with O.table(GetTurnstileSummary.header): 175 ts_ty = gettype('struct turnstile') 176 for ts in kmemory.Zone("turnstiles").iter_allocated(ts_ty): 177 if ts_is_interesting(ts): 178 PrintTurnstile(value(ts), O=O) 179 180# EndMacro showallbusyturnstiles 181 182@lldb_command('showthreadbaseturnstiles', fancy=True) 183def ShowThreadInheritorBase(cmd_args=None, cmd_options={}, O=None): 184 """ A macro that walks the list of userspace turnstiles pushing on a thread and prints them. 185 usage: (lldb) showthreadbaseturnstiles thread_pointer 186 """ 187 if cmd_args is None or len(cmd_args) == 0: 188 return O.error('invalid thread pointer') 189 190 thread = kern.GetValueFromAddress(cmd_args[0], "thread_t") 191 with O.table(GetTurnstileSummary.header): 192 for turnstile in IterateSchedPriorityQueue(thread.base_inheritor_queue, 'struct turnstile', 'ts_inheritor_links'): 193 PrintTurnstile(turnstile, O=O) 194 195@lldb_command('showthreadschedturnstiles', fancy=True) 196def ShowThreadInheritorSched(cmd_args=None, cmd_options={}, O=None): 197 """ A macro that walks the list of kernelspace turnstiles pushing on a thread 198 and prints them. 199 usage: (lldb) showthreadschedturnstiles thread_pointer 200 """ 201 if cmd_args is None or len(cmd_args) == 0: 202 return O.error('invalid thread pointer') 203 204 thread = kern.GetValueFromAddress(cmd_args[0], "thread_t") 205 with O.table(GetTurnstileSummary.header): 206 for turnstile in IterateSchedPriorityQueue(thread.sched_inheritor_queue, 'struct turnstile', 'ts_inheritor_links'): 207 PrintTurnstile(turnstile, O=O) 208