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