1from __future__ import absolute_import, print_function 2 3from builtins import range 4 5from core import xnu_format 6from xnu import * 7import sys, shlex 8from utils import * 9from waitq import * 10import kmemory 11import xnudefines 12 13@lldb_type_summary(['struct turnstile *']) 14@header("{0: <20s} {1: <5s} {2: <20s} {3: <8s} {4: <8s} {5: <23s} {6: <20s} {7: <10s} {8: <10s} {9: <20s} {10: <20s}".format( 15 "turnstile", "pri", "waitq", "type", "state", "inheritor", "proprietor", "gen cnt", "prim cnt", "thread", "prev_thread")) 16def GetTurnstileSummary(turnstile): 17 """ Summarizes the turnstile 18 params: turnstile = value of the object of type struct turnstile * 19 returns: String with summary of the type. 20 """ 21 22 ts_v = turnstile.GetSBValue() 23 ts_tg = ts_v.xGetScalarByName('ts_type_gencount') 24 ts_type = ts_tg & 0xff 25 ts_gen = ts_tg >> 8 26 27 if ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_NONE'): 28 turnstile_type = "none " 29 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_KERNEL_MUTEX'): 30 turnstile_type = "knl_mtx" 31 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_ULOCK'): 32 turnstile_type = "ulock " 33 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_PTHREAD_MUTEX'): 34 turnstile_type = "pth_mtx" 35 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_SYNC_IPC'): 36 turnstile_type = "syn_ipc" 37 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_WORKLOOPS'): 38 turnstile_type = "kqwl " 39 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_WORKQS'): 40 turnstile_type = "workq " 41 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_KNOTE'): 42 turnstile_type = "knote " 43 elif ts_type == GetEnumValue('turnstile_type_t', 'TURNSTILE_SLEEP_INHERITOR'): 44 turnstile_type = "slp_inh" 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): 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 if turnstile.ts_state & 0x3 == 0: 101 needsHeader = True 102 for free_turnstile in IterateListEntry(turnstile.ts_free_turnstiles, 'ts_free_elm', 's'): 103 if needsHeader: 104 print(" Turnstile free List") 105 header_str = " " + GetTurnstileSummary.header 106 print(header_str) 107 needsHeader = False 108 print(" " + GetTurnstileSummary(free_turnstile)) 109 print("") 110 111# Macro: showturnstile 112@lldb_command('showturnstile', fancy=True) 113def ShowTurnstile(cmd_args=None, cmd_options={}, O=None): 114 """ show the turnstile and all free turnstiles hanging off the turnstile. 115 Usage: (lldb)showturnstile <struct turnstile *> 116 """ 117 if not cmd_args: 118 raise ArgumentError("Please provide arguments") 119 120 turnstile = kern.GetValueFromAddress(cmd_args[0], 'struct turnstile') 121 with O.table(GetTurnstileSummary.header): 122 PrintTurnstile(turnstile) 123# EndMacro: showturnstile 124 125@lldb_command('showturnstilehashtable', fancy=True) 126def ShowTurnstileHashTable(cmd_args=None, cmd_options={}, O=None): 127 """ show the global hash table for turnstiles. 128 Usage: (lldb)showturnstilehashtable 129 """ 130 with O.table(GetTurnstileSummary.header): 131 turnstile_htable_buckets = kern.globals.ts_htable_buckets 132 for index in range(0, turnstile_htable_buckets): 133 turnstile_bucket = GetObjectAtIndexFromArray(kern.globals.turnstile_htable, index) 134 for turnstile in IterateQueue(turnstile_bucket.ts_ht_bucket_list, 'struct turnstile *', 'ts_htable_link'): 135 PrintTurnstile(turnstile) 136 137# Macro: showallturnstiles 138@lldb_command('showallturnstiles', fancy=True) 139def ShowAllTurnstiles(cmd_args=None, cmd_options={}, O=None): 140 """ A macro that walks the list of all allocated turnstile objects and prints them. 141 usage: (lldb) showallturnstiles 142 """ 143 with O.table(GetTurnstileSummary.header): 144 ts_ty = gettype('struct turnstile') 145 for ts in kmemory.Zone("turnstiles").iter_allocated(ts_ty): 146 PrintTurnstile(value(ts)) 147# EndMacro showallturnstiles 148 149# Macro: showallbusyturnstiles 150@lldb_command('showallbusyturnstiles', 'V', fancy=True) 151def ShowAllBusyTurnstiles(cmd_args=None, cmd_options={}, O=None): 152 """ A macro that walks the list of all allocated turnstile objects 153 and prints them. 154 usage: (lldb) showallbusyturnstiles [-V] 155 156 -V Even show turnstiles with no waiters (but with a proprietor) 157 """ 158 159 verbose = "-V" in cmd_options 160 161 def ts_is_interesting(ts): 162 if not ts.xGetScalarByName('ts_proprietor'): 163 # not owned by any primitive 164 return False 165 if verbose: 166 return True 167 return ts.xGetScalarByPath('.ts_waitq.waitq_prio_queue.pq_root') 168 169 with O.table(GetTurnstileSummary.header): 170 ts_ty = gettype('struct turnstile') 171 for ts in kmemory.Zone("turnstiles").iter_allocated(ts_ty): 172 if ts_is_interesting(ts): 173 PrintTurnstile(value(ts)) 174 175# EndMacro showallbusyturnstiles 176 177@lldb_command('showthreadbaseturnstiles', fancy=True) 178def ShowThreadInheritorBase(cmd_args=None, cmd_options={}, O=None): 179 """ A macro that walks the list of userspace turnstiles pushing on a thread and prints them. 180 usage: (lldb) showthreadbaseturnstiles thread_pointer 181 """ 182 if not cmd_args: 183 return O.error('invalid thread pointer') 184 185 thread = kern.GetValueFromAddress(cmd_args[0], "thread_t") 186 with O.table(GetTurnstileSummary.header): 187 for turnstile in IterateSchedPriorityQueue(thread.base_inheritor_queue, 'struct turnstile', 'ts_inheritor_links'): 188 PrintTurnstile(turnstile) 189 190@lldb_command('showthreadschedturnstiles', fancy=True) 191def ShowThreadInheritorSched(cmd_args=None, cmd_options={}, O=None): 192 """ A macro that walks the list of kernelspace turnstiles pushing on a thread 193 and prints them. 194 usage: (lldb) showthreadschedturnstiles thread_pointer 195 """ 196 if not cmd_args: 197 return O.error('invalid thread pointer') 198 199 thread = kern.GetValueFromAddress(cmd_args[0], "thread_t") 200 with O.table(GetTurnstileSummary.header): 201 for turnstile in IterateSchedPriorityQueue(thread.sched_inheritor_queue, 'struct turnstile', 'ts_inheritor_links'): 202 PrintTurnstile(turnstile) 203