]> git.saurik.com Git - apple/libpthread.git/blob - lldbmacros/init.py
libpthread-416.40.3.tar.gz
[apple/libpthread.git] / lldbmacros / init.py
1 from xnu import *
2 import struct
3
4 def GetSeqCount(seq):
5 return (seq >> 8)
6
7 def GetLSeqBits(seq):
8 rv = ""
9 if seq & 0x1:
10 rv += "K"
11 if seq & 0x2:
12 rv += "E"
13 if seq & 0x4:
14 rv += "W"
15 if seq & 0x20:
16 rv += "M"
17 if seq & 0x40:
18 rv += "U"
19 if seq & 0x80:
20 rv += "I"
21 return rv
22
23 def GetSSeqBits(seq):
24 rv = ""
25 if seq & 0x1:
26 rv += "S"
27 if seq & 0x2:
28 rv += "I"
29 if seq & 0x4:
30 rv += "Ws"
31 return rv
32
33 def GetLSeqSummary(seq):
34 return "{:d} {:s}".format(GetSeqCount(seq), GetLSeqBits(seq))
35
36 def GetSSeqSummary(seq):
37 return "{:d} {:s}".format(GetSeqCount(seq), GetSSeqBits(seq))
38
39 @header("{0: <24s} {1: <16s} {2: <16s} {3: <16s} {4: <16s}".format('sig', 'tid', 'options', 'lseq', 'useq'))
40 def GetUserMutexSummary(task, uaddr):
41 if int(task.t_flags) & 0x1:
42 mtxlayout = "QIIhhIQIII"
43 padoffset = 1
44 else:
45 mtxlayout = "QIIhhQIII"
46 padoffset = 0
47
48 data = GetUserDataAsString(task, unsigned(uaddr), struct.calcsize(mtxlayout))
49 info = struct.unpack(mtxlayout, data)
50
51 format = "{0: <24s} {1: <16s} {2: <16s} {3: <16s} {4: <16s}"
52 sigstr = str("{0: <#020x}".format(info[0]))
53
54 # the options field dictates whether we were created misaligned
55 if info[2] & 0x800:
56 lseq = info[7+padoffset]
57 useq = info[8+padoffset]
58 else:
59 lseq = info[6+padoffset]
60 useq = info[7+padoffset]
61
62 return format.format(sigstr, hex(info[5+padoffset]), hex(info[2]), hex(lseq), hex(useq))
63
64 @lldb_command('showusermutex')
65 def PthreadShowUserMutex(cmd_args=None):
66 """
67 display information about a userspace mutex at a given address
68 Syntax: (lldb) showusermutex <task_t> <uaddr>
69 """
70 if not cmd_args:
71 raise ArgumentError("No arguments passed")
72 task = kern.GetValueFromAddress(cmd_args[0], "task_t")
73 uaddr = kern.GetValueFromAddress(cmd_args[1], "user_addr_t")
74
75 print GetUserMutexSummary.header
76 print GetUserMutexSummary(task, uaddr)
77
78 @lldb_type_summary(['ksyn_wait_queue *', 'ksyn_wait_queue_t'])
79 @header("{:<20s} {:<20s} {:<10s} {:<6s} {:<6s} {:<8s} {:<8s} {:<8s} {:<8s}".format('kwq', 'uaddr', 'type', 'pflags', 'kflags', 'refs', 'indrop', 'waiters', 'preposts'))
80 def GetKwqSummary(kwq):
81 format = "{:<#20x} {:<#20x} {:<10s} {:<6s} {:<6s} {:<8d} {:<8d} {:<8d} {:<8d}\n"
82 kwq = Cast(kwq, "ksyn_wait_queue_t")
83
84 kwqtype = ""
85 if kwq.kw_type & 0xff == 0x01:
86 kwqtype = "mtx"
87 if kwq.kw_type & 0xff == 0x02:
88 kwqtype = "cvar"
89 if kwq.kw_type & 0xff == 0x04:
90 kwqtype = "rwl"
91 if kwq.kw_type & 0xff == 0x05:
92 kwqtype = "sema"
93
94 if kwq.kw_type & 0x1000 == 0x1000:
95 kwqtype += "W" # INWAIT
96 if kwq.kw_type & 0x2000 == 0x2000:
97 kwqtype += "D" # INDROP
98
99 pflags = ""
100 if kwq.kw_pflags & 0x2:
101 pflags += "H" # INHASH
102 if kwq.kw_pflags & 0x4:
103 pflags += "S" # SHARED
104 if kwq.kw_pflags & 0x8:
105 pflags += "W" # WAITING
106 if kwq.kw_pflags & 0x10:
107 pflags += "F" # FREELIST
108
109 kflags = ""
110 if kwq.kw_kflags & 0x1:
111 kflags += "C" # INITCLEARED
112 if kwq.kw_kflags & 0x2:
113 kflags += "Z" # ZEROED
114 if kwq.kw_kflags & 0x4:
115 kflags += "Q" # QOS APPLIED
116 if kwq.kw_kflags & 0x8:
117 kflags += "O" # OVERLAP
118
119 rs = format.format(kwq, kwq.kw_addr, kwqtype, pflags, kflags, kwq.kw_iocount, kwq.kw_dropcount, kwq.kw_inqueue, kwq.kw_fakecount)
120
121 rs += "\t{:<10s} {:<10s} {:<10s} {:<10s} {:<10s} {:<10s} {:<10s}\n".format('lowest', 'highest', 'lword', 'uword', 'sword', 'last', 'next')
122 rs += "\t{:<10d} {:<10d} {:<10s} {:<10d} {:<10s} {:<10s} {:<10s}\n".format(
123 GetSeqCount(kwq.kw_lowseq), GetSeqCount(kwq.kw_highseq),
124 GetLSeqSummary(kwq.kw_lword), GetSeqCount(kwq.kw_uword),
125 GetSSeqSummary(kwq.kw_sword), GetSSeqSummary(kwq.kw_lastseqword),
126 GetSSeqSummary(kwq.kw_nextseqword))
127
128 rs += "\t{:<10s} {:<10s} {:<10s} {:<10s} {:<10s} {:<10s} {:<10s}\n".format(
129 'pposts', 'lseq', 'sseq', 'intr', 'count', 'seq', 'bits')
130
131 intr_type = "NONE"
132 if kwq.kw_intr.type == 0x1:
133 intr_type = "READ"
134 elif kwq.kw_intr.type == 0x2:
135 intr_type = "WRITE"
136
137 rs += "\t{:<10d} {:<10s} {:<10s} {:<10s} {:<10d} {:<10s} {:<10s}\n".format(
138 kwq.kw_prepost.count,
139 GetLSeqSummary(kwq.kw_prepost.lseq), GetSSeqSummary(kwq.kw_prepost.sseq),
140 intr_type, kwq.kw_intr.count,
141 GetSSeqSummary(kwq.kw_intr.seq), GetSSeqSummary(kwq.kw_intr.returnbits))
142
143 rs += "\twaiting readers:\n"
144 for kwe in IterateTAILQ_HEAD(kwq.kw_ksynqueues[0].ksynq_kwelist, 'kwe_list'):
145 rs += "\t" + GetKweSummary.header + "\n"
146 rs += "\t" + GetKweSummary(kwe) + "\n"
147
148 rs += "\twaiting writers:\n"
149 for kwe in IterateTAILQ_HEAD(kwq.kw_ksynqueues[1].ksynq_kwelist, 'kwe_list'):
150 rs += "\t" + GetKweSummary.header + "\n"
151 rs += "\t" + GetKweSummary(kwe) + "\n"
152
153 if kwq.kw_turnstile:
154 rs += GetTurnstileSummary.header + "\n"
155 rs += GetTurnstileSummary(Cast(kwq.kw_turnstile, "struct turnstile *"))
156
157 return rs
158
159 @lldb_type_summary(['ksyn_waitq_element *', 'ksyn_waitq_element_t'])
160 @header("{:<20s} {:<20s} {:<10s} {:<10s} {:<20s} {:<20s}".format('kwe', 'kwq', 'lseq', 'state', 'uthread', 'thread'))
161 def GetKweSummary(kwe):
162 format = "{:<#20x} {:<#20x} {:<10s} {:<10s} {:<#20x} {:<#20x}"
163 kwe = Cast(kwe, 'struct ksyn_waitq_element *')
164 state = ""
165 if kwe.kwe_state == 1:
166 state = "INWAIT"
167 elif kwe.kwe_state == 2:
168 state = "PPOST"
169 elif kwe.kwe_state == 3:
170 state = "BROAD"
171 else:
172 state = "{:#10x}".format(kwe.kwe_state)
173 return format.format(kwe, kwe.kwe_kwqqueue, GetLSeqSummary(kwe.kwe_lockseq), state, kwe.kwe_uth, kwe.kwe_thread)
174
175 @header("{0: <24s} {1: <24s} {2: <24s}".format('thread', 'thread_id', 'uthread'))
176 def GetPthreadSummary(thread):
177 format = "{0: <24s} {1: <24s} {2: <24s}"
178
179 threadstr = str("{0: <#020x}".format(thread))
180 if int(thread.static_param):
181 threadstr += "[WQ]"
182
183 uthread = Cast(thread.uthread, "uthread_t")
184 uthreadstr = str("{0: <#020x}".format(uthread))
185
186
187 return format.format(threadstr, hex(thread.thread_id), uthreadstr)
188
189 @header("{0: <24s} {1: <24s} {2: <10s} {3: <10s} {4: <10s} {5: <10s} {6: <10s}".format('proc', 'wq', 'sched', 'req', 'idle', 'wq_flags', 'wq_lflags'))
190 def GetPthreadWorkqueueSummary(wq):
191 format = "{0: <24s} {1: <24s} {2: <10d} {3: <10d} {4: <10d} {5: <10s} {6: <10s}"
192 procstr = str("{0: <#020x}".format(wq.wq_proc))
193 wqstr = str("{0: <#020x}".format(wq))
194
195 flags = []
196 if wq.wq_flags & 0x1:
197 flags.append("I")
198 if wq.wq_flags & 0x2:
199 flags.append("R")
200 if wq.wq_flags & 0x4:
201 flags.append("E")
202
203 wqflags = []
204 if wq.wq_lflags & 0x1:
205 wqflags.append("B")
206 if wq.wq_lflags & 0x2:
207 wqflags.append("W")
208 if wq.wq_lflags & 0x4:
209 wqflags.append("C")
210 if wq.wq_lflags & 0x8:
211 wqflags.append("L")
212
213 return format.format(procstr, wqstr, wq.wq_threads_scheduled, wq.wq_reqcount, wq.wq_thidlecount, "".join(flags), "".join(wqflags))
214
215 @header("{0: <24s} {1: <5s} {2: <5s} {3: <5s} {4: <5s} {5: <5s} {6: <5s} {7: <5s}".format('category', 'uint', 'uinit', 'lgcy', 'util', 'bckgd', 'maint', 'event'))
216 def GetPthreadWorkqueueDetail(wq):
217 format = " {0: <22s} {1: <5d} {2: <5d} {3: <5d} {4: <5d} {5: <5d} {6: <5d} {7: <5d}"
218 # requests
219 schedstr = format.format('scheduled', wq.wq_thscheduled_count[0], wq.wq_thscheduled_count[1], wq.wq_thscheduled_count[2], wq.wq_thscheduled_count[3], wq.wq_thscheduled_count[4], wq.wq_thscheduled_count[5], wq.wq_thscheduled_count[6])
220 activestr = format.format('active', wq.wq_thactive_count[0], wq.wq_thactive_count[1], wq.wq_thactive_count[2], wq.wq_thactive_count[3], wq.wq_thactive_count[4], wq.wq_thactive_count[5], wq.wq_thactive_count[6])
221 return "\n".join([schedstr, activestr])
222
223 @lldb_command('showthreadpsynch')
224 def PthreadCurrentMutex(cmd_args=None):
225 """
226 display information about a thread's pthread state
227 Syntax: (lldb) showthreadpsync <thread_t>
228 """
229 if not cmd_args:
230 raise ArgumentError("No arguments passed")
231
232 thread = kern.GetValueFromAddress(cmd_args[0], "thread_t")
233 print GetPthreadSummary.header
234 print GetPthreadSummary(thread)
235
236 uthread = Cast(thread.uthread, "uthread_t")
237 kwe = Cast(addressof(uthread.uu_save.uus_kwe), 'struct ksyn_waitq_element *')
238 if not kwe or not kwe.kwe_kwqqueue:
239 print GetKweSummary.header
240 print GetKweSummary(kwe)
241 else:
242 print GetKwqSummary.header
243 print GetKwqSummary(kwe.kwe_kwqqueue)
244
245 @lldb_command('showpthreadkwq')
246 def PthreadShowKsynQueue(cmd_args=None):
247 """
248 display information about a pthread ksyn_wait_queue_t
249 Syntax: (lldb) showpthreadkwq <ksyn_wait_queue_t>
250 """
251 if not cmd_args:
252 raise ArgumentError("No arguments passed")
253
254 kwq = kern.GetValueFromAddress(cmd_args[0], "ksyn_wait_queue_t")
255 print GetKwqSummary.header
256 print GetKwqSummary(kwq)
257
258 @lldb_command('showpthreadkwe')
259 def PthreadShowKsynElement(cmd_args=None):
260 """
261 display information about a thread's ksyn_waitq_element
262 Syntax: (lldb) showpthreadkwe <ksyn_waitq_element_t>
263 """
264 if not cmd_args:
265 raise ArgumentError("No arguments passed")
266
267 kwe = kern.GetValueFromAddress(cmd_args[0], "struct ksyn_waitq_element *")
268 print GetKweSummary.header
269 print GetKweSummary(kwe)
270
271 @lldb_command('showpthreadworkqueue')
272 def ShowPthreadWorkqueue(cmd_args=None):
273 """
274 display information about a processes' pthread workqueue
275 Syntax: (lldb) showpthreadworkqueue <proc_t>
276 """
277
278 if not cmd_args:
279 raise ArgumentError("No arguments passed")
280
281 proc = kern.GetValueFromAddress(cmd_args[0], "proc_t")
282 wq = Cast(proc.p_wqptr, "struct workqueue *");
283
284 print GetPthreadWorkqueueSummary.header
285 print GetPthreadWorkqueueSummary(wq)
286
287 print GetPthreadWorkqueueDetail.header
288 print GetPthreadWorkqueueDetail(wq)
289
290 def IterateTAILQ_HEAD(headval, element_name):
291 """ iterate over a TAILQ_HEAD in kernel. refer to bsd/sys/queue.h
292 params:
293 headval - value : value object representing the head of the list
294 element_name- str : string name of the field which holds the list links.
295 returns:
296 A generator does not return. It is used for iterating.
297 value : an object that is of type as headval->tqh_first. Always a pointer object
298 example usage:
299 list_head = kern.GetGlobalVariable('mountlist')
300 for entryobj in IterateTAILQ_HEAD(list_head, 'mnt_list'):
301 print GetEntrySummary(entryobj)
302 """
303 iter_val = headval.tqh_first
304 while unsigned(iter_val) != 0 :
305 yield iter_val
306 iter_val = iter_val.__getattr__(element_name).tqe_next
307 #end of yield loop
308
309 def __lldb_init_module(debugger, internal_dict):
310 pass