]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/ipc.py
xnu-2782.40.9.tar.gz
[apple/xnu.git] / tools / lldbmacros / ipc.py
CommitLineData
39236c6e
A
1""" Please make sure you read the README file COMPLETELY BEFORE reading anything below.
2 It is very critical that you read coding guidelines in Section E in README file.
3"""
4from xnu import *
5import sys, shlex
6from utils import *
7from process import *
fe8ab488
A
8from atm import *
9from bank import *
39236c6e
A
10import xnudefines
11
12@header("{0: <20s} {1: <6s} {2: <6s} {3: <10s} {4: <15s}".format("task", "pid", '#acts', "tablesize", "command"))
13def GetTaskIPCSummary(task):
14 """ Display a task's ipc summary.
15 params:
16 task : core.value represeting a Task in kernel
17 returns
18 str - string of ipc info for the task
19 """
20 out_string = ''
21 format_string = "{0: <#020x} {1: <6d} {2: <6d} {3: <10d} {4: <15s}"
22 pval = Cast(task.bsd_info, 'proc *')
23 table_size = int(task.itk_space.is_table_size)
24 proc_name = str(pval.p_comm)
25 out_string += format_string.format(task, pval.p_pid, task.thread_count, table_size, proc_name)
26 return out_string
27
28@header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <4s} {5: <20s} {6: <4s}\n".format(
29 "port", "mqueue", "recvname", "flags", "refs", "recvname", "dest"))
30def GetPortSummary(port, show_kmsg_summary=True, prefix=""):
31 """ Display a port's summary
32 params:
33 port : core.value representing a port in the kernel
34 returns
35 str : string of ipc info for the given port
36 """
37 out_string = ""
38 portp = Cast(port, 'struct ipc_port *')
39 destspacep = kern.GetValueFromAddress(0, 'struct ipc_space *')
40 spacep = portp.data.receiver
41 format_string = "{0: #019x} {1: #019x} {2: <8s} {3: #011x} {4: <5s} {5: #05x} {6: #019x} {7: <16s}\n"
42 if portp.ip_object.io_bits & 0x80000000:
43 out_string += prefix + format_string.format(
44 unsigned(portp), addressof(portp.ip_messages), ' '*8,
45 unsigned(portp.ip_messages.data.port.receiver_name),
46 "APort", portp.ip_object.io_references,
47 unsigned(portp.ip_messages.data.port.receiver_name),
48 GetPortDestProc(portp))
49 else:
50 out_string += prefix + format_string.format(
51 unsigned(portp), addressof(portp.ip_messages), ' '*8,
52 unsigned(portp.ip_messages.data.port.receiver_name),
53 "DPort", portp.ip_object.io_references, unsigned(portp),
54 "inactive-port")
55
56 if show_kmsg_summary:
57 kmsgp = Cast(portp.ip_messages.data.port.messages.ikmq_base, 'ipc_kmsg_t')
58 out_string += prefix + GetKMsgSummary.header + prefix + GetKMsgSummary(kmsgp)
59
60 kmsgheadp = kmsgp
61 kmsgp = kmsgp.ikm_next
62 while (kmsgp) != (kmsgheadp):
63 out_string += prefix + GetKMsgSummary(kmsgp)
64 kmsgp = kmsgp.ikm_next
65 return out_string
66
67def GetPortDestProc(portp):
68 """ Display the name and pid of a given port's receiver
69 params:
70 portp : core.value representing a pointer to a port in the kernel
71 destspacep : core.value representing a pointer to an ipc_space
72 returns:
73 str : string containing receiver's name and pid
74 """
75 spacep = portp.data.receiver
76 out_str = "Not found"
77 for tsk in kern.tasks:
78 if tsk.itk_space == spacep:
79 if tsk.bsd_info:
80 destprocp = Cast(tsk.bsd_info, 'struct proc *')
81 out_str = "{0:s}({1: <d})".format(destprocp.p_comm, destprocp.p_pid)
82 else:
fe8ab488 83 out_str = "unknown"
39236c6e
A
84 break
85
86 return out_str
87
fe8ab488
A
88@header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <19s} {6: <26s} {7: <26s}\n".format(
89 "dest-port", "kmsg", "msgid", "disp", "size", "reply-port", "source", "destination"))
39236c6e
A
90def GetKMsgSummary(kmsgp):
91 """ Display a summary for type ipc_kmsg_t
92 params:
93 kmsgp : core.value representing the given ipc_kmsg_t struct
94 returns:
95 str : string of summary info for the given ipc_kmsg_t instance
96 """
97 kmsghp = kmsgp.ikm_header
98 kmsgh = dereference(kmsghp)
99 out_string = ""
fe8ab488 100 out_string += "{0: <19s} {1: <#019x} {2: <8s} {3: <#011x} ".format(
39236c6e
A
101 ' '*19, unsigned(kmsgp), ' '*8, kmsgh.msgh_id)
102
fe8ab488
A
103 if (kmsgh.msgh_bits & 0xff) == 17:
104 out_string += "{0: <2s}".format("rS")
39236c6e 105 else:
fe8ab488 106 out_string += "{0: <2s}".format("rO")
39236c6e 107
fe8ab488
A
108 if (kmsgh.msgh_bits & 0xff00) == (17 << 8):
109 out_string += "{0: <2s}".format("lS")
39236c6e 110 else:
fe8ab488
A
111 if (kmsgh.msgh_bits & 0xff00) == (18 << 8):
112 out_string += "{0: <2s}".format("lO")
113 else:
114 out_string += "{0: <2s}".format("l-")
39236c6e
A
115 if kmsgh.msgh_bits & 0xf0000000:
116 out_string += "{0: <2s}".format("c")
117 else:
118 out_string += "{0: <2s}".format("s")
119
fe8ab488
A
120 dest_proc_name = ""
121 if kmsgp.ikm_header.msgh_remote_port:
122 dest_proc_name = GetDestinationProcessFromPort(kmsgp.ikm_header.msgh_remote_port)
123
124 out_string += "{0: ^6d} {1: <#019x} {2: <26s} {3: <26s}\n".format(
125 unsigned(kmsgh.msgh_size), unsigned(kmsgh.msgh_local_port),
126 GetKMsgSrc(kmsgp), dest_proc_name)
39236c6e
A
127 return out_string
128
129def GetKMsgSrc(kmsgp):
130 """ Routine that prints a kmsg's source process and pid details
131 params:
132 kmsgp : core.value representing the given ipc_kmsg_t struct
133 returns:
134 str : string containing the name and pid of the kmsg's source proc
135 """
136 kmsgsrchp = Cast(kmsgp, 'ipc_kmsg_t').ikm_header
137 kmsgpid = int(Cast(kern.GetValueFromAddress(unsigned(kmsgsrchp) + kmsgsrchp.msgh_size, 'uint *')[10], 'pid_t'))
138
139 return "{0:s} ({1:d})".format(GetProcNameForPid(kmsgpid), kmsgpid)
140
141@header("{0: <20s} {1: <28s} {2: <12s} {3: <6s} {4: <6s} {5: <20s} {6: <7s}\n".format(
142 "portset", "waitqueue", "recvname", "flags", "refs", "recvname", "process"))
143def GetPortSetSummary(pset):
144 """ Display summary for a given struct ipc_pset *
145 params:
146 pset : core.value representing a pset in the kernel
147 returns:
148 str : string of summary information for the given pset
149 """
150 out_str = ""
151 if pset.ips_object.io_bits & 0x80000000:
152 out_str += "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
153 unsigned(pset), addressof(pset.ips_messages), ' '*7,
154 pset.ips_messages.data.pset.local_name, "ASet",
155 pset.ips_object.io_references,
156 pset.ips_messages.data.pset.local_name)
157
158 else:
159 out_str += "{0: #019x} {1: #019x} {2: <7s} {3: #011x} {4: <4s} {5: >6d} {6: #019x} ".format(
160 unsigned(pset), addressof(pset.ips_messages), ' '*7,
161 pset.ips_messages.data.pset.local_name, "DSet",
162 pset.ips_object.io_references,
163 pset.ips_messages.data.pset.local_name)
164
165 once = True
166 setlinksp = addressof(pset.ips_messages.data.pset.set_queue.wqs_setlinks)
167 wql = Cast(pset.ips_messages.data.pset.set_queue.wqs_setlinks.next, 'WaitQueueLink *')
168 portoff = getfieldoffset('struct ipc_port', 'ip_messages')
169 prefix_str = "{0:<21s}".format(' '*21)
170 while unsigned(wql) != unsigned(Cast(setlinksp, 'void *')):
171 portp = kern.GetValueFromAddress(unsigned(wql.wql_element.wqe_queue) - portoff, 'ipc_port *')
172 if once:
173 once = False
174 out_str += "{0:s}\n{1:s}{2:s}".format(GetPortDestProc(portp), prefix_str, GetPortSummary.header)
175 out_str += GetPortSummary(portp, False, prefix_str)
176 wql = Cast(wql.wql_setlinks.next, 'WaitQueueLink *')
177 return out_str
178
179# Macro: showipc
180
181@lldb_command('showipc')
182def ShowIPC(cmd_args=None):
183 """ Routine to print data for the given IPC space
184 Usage: showipc <address of ipc space>
185 """
186 if not cmd_args:
187 print "No arguments passed"
188 print ShowIPC.__doc__
189 return False
190 ipc = kern.GetValueFromAddress(cmd_args[0], 'ipc_space *')
191 if not ipc:
192 print "unknown arguments:", str(cmd_args)
193 return False
194 print GetIPCInformation.header
195 print GetIPCInformation(ipc, False, False)
196
197# EndMacro: showipc
198
199# Macro: showtaskipc
200
201@lldb_command('showtaskipc')
202def ShowTaskIPC(cmd_args=None):
203 """ Routine to print IPC summary of given task
204 Usage: showtaskipc <address of task>
205 """
206 if not cmd_args:
207 print "No arguments passed"
208 print ShowTaskIPC.__doc__
209 return False
210 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
211 if not tval:
212 print "unknown arguments:", str(cmd_args)
213 return False
214 print GetTaskSummary.header + " " + GetProcSummary.header
215 pval = Cast(tval.bsd_info, 'proc *')
216 print GetTaskSummary(tval) + " " + GetProcSummary(pval)
217 print GetTaskIPCSummary.header
218 print GetTaskIPCSummary(tval)
219
220# EndMacro: showtaskipc
221
222# Macro: showallipc
223
224@lldb_command('showallipc')
225def ShowAllIPC(cmd_args=None):
226 """ Routine to print IPC summary of all tasks
227 Usage: showallipc
228 """
229 for t in kern.tasks:
230 print GetTaskSummary.header + " " + GetProcSummary.header
231 pval = Cast(t.bsd_info, 'proc *')
232 print GetTaskSummary(t) + " " + GetProcSummary(pval)
233 print GetIPCInformation.header
234 print GetIPCInformation(t.itk_space, False, False) + "\n\n"
235
236# EndMacro: showallipc
237
238@lldb_command('showipcsummary')
239def ShowIPCSummary(cmd_args=None):
240 """ Summarizes the IPC state of all tasks.
241 This is a convenient way to dump some basic clues about IPC messaging. You can use the output to determine
242 tasks that are candidates for further investigation.
243 """
244 print GetTaskIPCSummary.header
245 for t in kern.tasks:
246 print GetTaskIPCSummary(t)
247 return
248
249def GetKObjectFromPort(portval):
250 """ Get Kobject description from the port.
251 params: portval - core.value representation of 'ipc_port *' object
252 returns: str - string of kobject information
253 """
254 kobject_str = "{0: <#020x}".format(portval.kdata.kobject)
255 io_bits = unsigned(portval.ip_object.io_bits)
256 objtype_index = io_bits & 0xfff
257 if objtype_index < len(xnudefines.kobject_types) :
258 desc_str = "kobject({0:s})".format(xnudefines.kobject_types[objtype_index])
fe8ab488
A
259 if xnudefines.kobject_types[objtype_index] in ('TASK_RESUME', 'TASK'):
260 desc_str += " " + GetProcNameForTask(Cast(portval.kdata.kobject, 'task *'))
39236c6e
A
261 else:
262 desc_str = "kobject(UNKNOWN) {:d}".format(objtype_index)
263 return kobject_str + " " + desc_str
264
265@static_var('destcache', {})
266def GetDestinationProcessFromPort(port):
267 """
268 params: port - core.value representation of 'ipc_port *' object
269 returns: str - name of process
270 """
271 out_str = ''
272 dest_space = port.data.receiver
273 found_dest = False
274 #update destcache if data is not found
275 if hex(dest_space) not in GetDestinationProcessFromPort.destcache:
276 for t in kern.tasks:
277 if hex(t.itk_space) == hex(dest_space):
278 pval = Cast(t.bsd_info, 'proc *')
279 GetDestinationProcessFromPort.destcache[hex(dest_space)] = (t, pval)
280 found_dest = True
281 break
282 #end of for loop
283 else: found_dest = True
284
285 if found_dest:
286 (ftask , fproc) = GetDestinationProcessFromPort.destcache[hex(dest_space)]
287 if fproc:
288 out_str = "{0:s}({1:d})".format(fproc.p_comm, fproc.p_pid )
289 else:
290 out_str = "task {0: <#020x}".format(ftask)
291 return out_str
292
293
294
295@header("{0: <20s} {1: <20s}".format("destname", "destination") )
296def GetPortDestinationSummary(port):
297 """ Get destination information for a port.
298 params: port - core.value representation of 'ipc_port *' object
299 returns: str - string of info about ports destination
300 """
301 out_str = ''
302 format_string = "{0: <20s} {1: <20s}"
303 destname_str = ''
304 destination_str = ''
305 ipc_space_kernel = unsigned(kern.globals.ipc_space_kernel)
306 target_spaceval = port.data.receiver
307 if unsigned(target_spaceval) == ipc_space_kernel :
308 destname_str = GetKObjectFromPort(port)
309 else:
310 if int(port.ip_object.io_bits) & 0x80000000 :
311 destname_str = "{0: <#020x}".format(port.ip_messages.data.port.receiver_name)
312 destination_str = GetDestinationProcessFromPort(port)
313 else:
314 destname_str = "{0: <#020x}".format(port)
315 destination_str = "inactive-port"
316
317 out_str += format_string.format(destname_str, destination_str)
318 return out_str
319
320@lldb_type_summary(['ipc_entry_t'])
321@header("{0: <20s} {1: <20s} {2: <8s} {3: <8s} {4: <20s} {5: <20s}".format("object", "name","rite", "urefs", "destname", "destination"))
322def GetIPCEntrySummary(entry, ipc_name=''):
323 """ Get summary of a ipc entry.
324 params:
325 entry - core.value representing ipc_entry_t in the kernel
326 ipc_name - str of format '0x0123' for display in summary.
327 returns:
328 str - string of ipc entry related information
329 """
330 out_str = ''
331 entry_ptr = int(hex(entry), 16)
332 format_string = "{0: <#020x} {1: <12s} {2: <8s} {3: <8d} {4: <20s} {5: <20s}"
333 right_str = ''
334 destname_str = ''
335 destination_str = ''
336
337 ie_object = entry.ie_object
338 ie_bits = int(entry.ie_bits)
339 urefs = int(ie_bits & 0xffff)
340 if ie_bits & 0x00100000 :
341 right_str = 'Dead'
342 elif ie_bits & 0x00080000:
343 right_str = 'Set'
344 else:
345 if ie_bits & 0x00010000 :
346 if ie_bits & 0x00020000 :
347 right_str = 'SR'
348 else:
349 right_str = 'S'
350 elif ie_bits & 0x00020000:
351 right_str = 'R'
352 elif ie_bits & 0x00040000 :
353 right_str = 'O'
fe8ab488 354 portval = Cast(ie_object, 'ipc_port_t')
39236c6e 355 if int(entry.index.request) != 0:
39236c6e
A
356 requestsval = portval.ip_requests
357 sorightval = requestsval[int(entry.index.request)].notify.port
358 soright_ptr = unsigned(sorightval)
359 if soright_ptr != 0:
360 if soright_ptr & 0x1 : right_str +='s'
361 elif soright_ptr & 0x2 : right_str +='d'
362 else : right_str +='n'
363 if ie_bits & 0x00800000 : right_str +='c'
fe8ab488 364 if portval.ip_nsrequest != 0: right_str +='x'
39236c6e
A
365 # now show the port destination part
366 destname_str = GetPortDestinationSummary(Cast(ie_object, 'ipc_port_t'))
367
368 out_str = format_string.format(ie_object, ipc_name, right_str, urefs, destname_str, destination_str)
369 return out_str
370
371@header("{0: >20s}".format("user bt") )
372def GetPortUserStack(port, task):
373 """ Get UserStack information for the given port & task.
374 params: port - core.value representation of 'ipc_port *' object
375 task - value representing 'task *' object
376 returns: str - string information on port's userstack
377 """
378 out_str = ''
379 ie_port_callstack = port.ip_callstack
380 ie_port_spares = port.ip_spares[0]
381 proc_val = Cast(task.bsd_info, 'proc *')
382 if ie_port_callstack[0]:
383 out_str += "{: <10x}".format(ie_port_callstack[0])
384 count = 1
385 while count < 16 and ie_port_callstack[count]:
386 out_str += ": <10x".format(ie_port_callstack[count])
387 count = count + 1
388 if ie_port_spares != proc_val.p_pid:
389 out_str += " ({:<10d})".format(ie_port_spares)
390 out_str += '\n'
391 return out_str
392
393@lldb_type_summary(['ipc_space *'])
394@header("{0: <20s} {1: <20s} {2: <20s} {3: <8s} {4: <10s} {5: <16s} {6: <10s} {7: <7s}".format('ipc_space', 'is_task', 'is_table', 'flags', 'ports', 'table_next', 'low_mod', 'high_mod'))
395def GetIPCInformation(space, show_entries=False, show_userstack=False):
396 """ Provide a summary of the ipc space
397 """
398 out_str = ''
399 format_string = "{0: <#020x} {1: <#020x} {2: <#020x} {3: <8s} {4: <10d} {5: <#01x} {6: >10d} {7: >10d}"
400 is_tableval = space.is_table
401 ports = int(space.is_table_size)
402 flags =''
403 is_bits = int(space.is_bits)
404 if (is_bits & 0x40000000) == 0: flags +='A'
405 else: flags += ' '
406 if (is_bits & 0x20000000) != 0: flags +='G'
407 out_str += format_string.format(space, space.is_task, space.is_table, flags, space.is_table_size, space.is_table_next, space.is_low_mod, space.is_high_mod)
408
409 #should show the each individual entries if asked.
410 if show_entries == True:
411 out_str += "\n\t" + GetIPCEntrySummary.header + "\n"
412 num_entries = ports
413 index = 0
414 while index < num_entries:
415 entryval = GetObjectAtIndexFromArray(is_tableval, index)
416 entry_ie_bits = unsigned(entryval.ie_bits)
417 if (int(entry_ie_bits) & 0x001f0000 ) != 0:
418 entry_name = "{0: <#020x}".format( (index <<8 | entry_ie_bits >> 24) )
419 out_str += "\t" + GetIPCEntrySummary(entryval, entry_name) + "\n"
420 if show_userstack == True:
421 entryport = Cast(entryval.ie_object, 'ipc_port *')
422 if entryval.ie_object and (int(entry_ie_bits) & 0x00070000) and entryport.ip_callstack[0]:
423 out_str += GetPortUserStack.header
424 out_str += GetPortUserStack(entryport, space.is_task)
425 index +=1
426 #done with showing entries
427 return out_str
428
429# Macro: showrights
430
431@lldb_command('showrights')
432def ShowRights(cmd_args=None):
433 """ Routine to print rights information for the given IPC space
434 Usage: showrights <address of ipc space>
435 """
436 if not cmd_args:
437 print "No arguments passed"
438 print ShowRights.__doc__
439 return False
440 ipc = kern.GetValueFromAddress(cmd_args[0], 'ipc_space *')
441 if not ipc:
442 print "unknown arguments:", str(cmd_args)
443 return False
444 print GetIPCInformation.header
445 print GetIPCInformation(ipc, True, False)
446
447# EndMacro: showrights
448
449@lldb_command('showtaskrights')
450def ShowTaskRights(cmd_args=None):
451 """ Routine to ipc rights information for a task
452 Usage: showtaskrights <task address>
453 """
454 if cmd_args == None:
455 print "No arguments passed"
456 print ShowTaskStacksCmdHelper.__doc__
457 return False
458 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
459 if not tval:
460 print "unknown arguments:", str(cmd_args)
461 return False
462 print GetTaskSummary.header + " " + GetProcSummary.header
463 pval = Cast(tval.bsd_info, 'proc *')
464 print GetTaskSummary(tval) + " " + GetProcSummary(pval)
465 print GetIPCInformation.header
466 print GetIPCInformation(tval.itk_space, True, False)
467
468# Macro: showataskrightsbt
469
470@lldb_command('showtaskrightsbt')
471def ShowTaskRightsBt(cmd_args=None):
472 """ Routine to ipc rights information with userstacks for a task
473 Usage: showtaskrightsbt <task address>
474 """
475 if cmd_args == None:
476 print "No arguments passed"
477 print ShowTaskRightsBt.__doc__
478 return False
479 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
480 if not tval:
481 print "unknown arguments:", str(cmd_args)
482 return False
483 print GetTaskSummary.header + " " + GetProcSummary.header
484 pval = Cast(tval.bsd_info, 'proc *')
485 print GetTaskSummary(tval) + " " + GetProcSummary(pval)
486 print GetIPCInformation.header
487 print GetIPCInformation(tval.itk_space, True, True)
488
489# EndMacro: showtaskrightsbt
490
491# Macro: showallrights
492
493@lldb_command('showallrights')
494def ShowAllRights(cmd_args=None):
495 """ Routine to print rights information for IPC space of all tasks
496 Usage: showallrights
497 """
498 for t in kern.tasks:
499 print GetTaskSummary.header + " " + GetProcSummary.header
500 pval = Cast(t.bsd_info, 'proc *')
501 print GetTaskSummary(t) + " " + GetProcSummary(pval)
fe8ab488
A
502 try:
503 print GetIPCInformation.header
504 print GetIPCInformation(t.itk_space, True, False) + "\n\n"
505 except (KeyboardInterrupt, SystemExit):
506 raise
507 except:
508 print "Failed to get IPC information. Do individual showtaskrights <task> to find the error. \n\n"
39236c6e
A
509
510# EndMacro: showallrights
511
512# Macro: showpipestats
513@lldb_command('showpipestats')
514def ShowPipeStats(cmd_args=None):
515 """ Display pipes usage information in the kernel
516 """
517 print "Number of pipes: {: d}".format(kern.globals.amountpipes)
518 print "Memory used by pipes: {:s}".format(sizeof_fmt(int(kern.globals.amountpipekva)))
519 print "Max memory allowed for pipes: {:s}".format(sizeof_fmt(int(kern.globals.maxpipekva)))
520# EndMacro: showpipestats
521
522# Macro: showtaskbusyports
523@lldb_command('showtaskbusyports')
524def ShowTaskBusyPorts(cmd_args=None):
525 """ Routine to print information about receive rights belonging to this task that
526 have enqueued messages. This is oten a sign of a blocked or hung process
527 Usage: showtaskbusyports <task address>
528 """
529 if not cmd_args:
530 print "No arguments passed. Please pass in the address of a task"
531 print ShowTaskBusyPorts.__doc__
532 return
533 task = kern.GetValueFromAddress(cmd_args[0], 'task_t')
534 print GetTaskBusyPorts(task)
535 return
536
537def GetTaskBusyPorts(task):
538 """ Prints all busy ports for a given task. ie. all receive rights belonging
539 to this task that have enqueued messages.
540 params:
541 task : core.value representing a task in kernel
542 returns:
543 str : String containing information about the given task's busy ports
544 """
545 isp = task.itk_space
546 i = 0
547 out_string = ""
548 while i < isp.is_table_size:
549 iep = addressof(isp.is_table[i])
550 if iep.ie_bits & 0x00020000:
551 port = Cast(iep.ie_object, 'ipc_port_t')
552 if port.ip_messages.data.port.msgcount > 0:
553 out_string += GetPortSummary.header + GetPortSummary(port)
554 i = i + 1
555 return out_string
556# EndMacro: showtaskbusyports
557
558# Macro: showallbusyports
559@lldb_command('showallbusyports')
560def ShowAllBusyPorts(cmd_args=None):
561 """ Routine to print information about all receive rights on the system that
562 have enqueued messages.
563 """
564 task_queue_head = kern.globals.tasks
565
566 for tsk in kern.tasks:
567 print GetTaskBusyPorts(tsk)
568 return
569# EndMacro: showallbusyports
570
571# Macro: showmqueue:
572@lldb_command('showmqueue')
573def ShowMQueue(cmd_args=None):
574 """ Routine that lists details about a given mqueue
575 Syntax: (lldb) showmqueue 0xaddr
576 """
577 if not cmd_args:
578 print "Please specify the address of the ipc_mqueue whose details you want to print"
579 print ShowMQueue.__doc__
580 return
581 mqueue = kern.GetValueFromAddress(cmd_args[0], 'struct ipc_mqueue *')
582 wq_type = mqueue.data.pset.set_queue.wqs_wait_queue.wq_type
583 if int(wq_type) == 3:
fe8ab488 584 psetoff = getfieldoffset('struct ipc_pset', 'ips_messages')
39236c6e
A
585 pset = unsigned(ArgumentStringToInt(cmd_args[0])) - unsigned(psetoff)
586 print GetPortSetSummary.header + GetPortSetSummary(kern.GetValueFromAddress(pset, 'struct ipc_pset *'))
587 if int(wq_type) == 2:
588 portoff = getfieldoffset('struct ipc_port', 'ip_messages')
589 port = unsigned(ArgumentStringToInt(cmd_args[0])) - unsigned(portoff)
590 print GetPortSummary.header + GetPortSummary(kern.GetValueFromAddress(port, 'struct ipc_port *'))
591# EndMacro: showmqueue
592
fe8ab488
A
593# Macro: showkmsg:
594@lldb_command('showkmsg')
595def ShowKMSG(cmd_args=[]):
596 """ Show detail information about a <ipc_kmsg_t> structure
597 Usage: (lldb) showkmsg <ipc_kmsg_t>
598 """
599 if not cmd_args:
600 raise ArgumentError('Invalid arguments')
601 kmsg = kern.GetValueFromAddress(cmd_args[0], 'ipc_kmsg_t')
602 print GetKMsgSummary.header
603 print GetKMsgSummary(kmsg)
604
605# EndMacro: showkmsg
606
39236c6e
A
607# Macro: showpset
608@lldb_command('showpset')
609def ShowPSet(cmd_args=None):
610 """ Routine that prints details for a given ipc_pset *
611 Syntax: (lldb) showpset 0xaddr
612 """
613 if not cmd_args:
614 print "Please specify the address of the pset whose details you want to print"
615 print ShowPSet.__doc__
616 return
617
618 print GetPortSetSummary.header + GetPortSetSummary(kern.GetValueFromAddress(cmd_args[0], 'ipc_pset *'))
619# EndMacro: showpset
620
fe8ab488
A
621# IPC importance inheritance related macros.
622
623@lldb_command('showalliits')
624def ShowAllIITs(cmd_args=[], cmd_options={}):
625 """ Development only macro. Show list of all iits allocated in the system. """
626 try:
627 iit_queue = kern.globals.global_iit_alloc_queue
628 except ValueError:
629 print "This debug macro is only available in development or debug kernels"
630 return
631
632 print GetIPCImportantTaskSummary.header
633 for iit in IterateQueue(iit_queue, 'struct ipc_importance_task *', 'iit_allocation'):
634 print GetIPCImportantTaskSummary(iit)
635 return
636
637@header("{: <18s} {: <3s} {: <18s} {: <20s} {: <18s} {: <8s}".format("ipc_imp_inherit", "don", "to_task", "proc_name", "from_elem", "depth"))
638@lldb_type_summary(['ipc_importance_inherit *', 'ipc_importance_inherit_t'])
639def GetIPCImportanceInheritSummary(iii):
640 """ describes iii object of type ipc_importance_inherit_t * """
641 out_str = ""
642 fmt = "{o: <#018x} {don: <3s} {o.iii_to_task.iit_task: <#018x} {task_name: <20s} {o.iii_from_elem: <#018x} {o.iii_depth: <#08x}"
643 donating_str = ""
644 if unsigned(iii.iii_donating):
645 donating_str = "DON"
646 taskname = GetProcNameForTask(iii.iii_to_task.iit_task)
647 if hasattr(iii.iii_to_task, 'iit_bsd_pid'):
648 taskname = "({:d}) {:s}".format(iii.iii_to_task.iit_bsd_pid, iii.iii_to_task.iit_procname)
649 out_str += fmt.format(o=iii, task_name = taskname, don=donating_str)
650 return out_str
651
652@static_var('recursion_count', 0)
653@header("{: <18s} {: <4s} {: <8s} {: <8s} {: <18s} {: <18s}".format("iie", "type", "refs", "made", "#kmsgs", "#inherits"))
654@lldb_type_summary(['ipc_importance_elem *'])
655def GetIPCImportanceElemSummary(iie):
656 """ describes an ipc_importance_elem * object """
657
658 if GetIPCImportanceElemSummary.recursion_count > 500:
659 GetIPCImportanceElemSummary.recursion_count = 0
660 return "Recursion of 500 reached"
661
662 out_str = ''
663 fmt = "{: <#018x} {: <4s} {: <8d} {: <8d} {: <#018x} {: <#018x}"
664 type_str = 'TASK'
665 if unsigned(iie.iie_bits) & 0x80000000:
666 type_str = "INH"
667 refs = unsigned(iie.iie_bits) & 0x7fffffff
668 made_refs = unsigned(iie.iie_made)
669 kmsg_count = sum(1 for i in IterateQueue(iie.iie_kmsgs, 'struct ipc_kmsg *', 'ikm_inheritance'))
670 inherit_count = sum(1 for i in IterateQueue(iie.iie_inherits, 'struct ipc_importance_inherit *', 'iii_inheritance'))
671 out_str += fmt.format(iie, type_str, refs, made_refs, kmsg_count, inherit_count)
672 if config['verbosity'] > vHUMAN:
673 if kmsg_count > 0:
674 out_str += "\n\t"+ GetKMsgSummary.header
675 for k in IterateQueue(iie.iie_kmsgs, 'struct ipc_kmsg *', 'ikm_inheritance'):
676 out_str += "\t" + "{: <#018x}".format(k.ikm_header.msgh_remote_port) + ' ' + GetKMsgSummary(k).lstrip()
677 out_str += "\n"
678 if inherit_count > 0:
679 out_str += "\n\t" + GetIPCImportanceInheritSummary.header + "\n"
680 for i in IterateQueue(iie.iie_inherits, 'struct ipc_importance_inherit *', 'iii_inheritance'):
681 out_str += "\t" + GetIPCImportanceInheritSummary(i) + "\n"
682 out_str += "\n"
683 if type_str == "INH":
684 iii = Cast(iie, 'struct ipc_importance_inherit *')
685 out_str += "Inherit from: " + GetIPCImportanceElemSummary(iii.iii_from_elem)
686
687 return out_str
688
689@header("{: <18s} {: <18s} {: <20s}".format("iit", "task", "name"))
690@lldb_type_summary(['ipc_importance_task *'])
691def GetIPCImportantTaskSummary(iit):
692 """ iit is a ipc_importance_task value object.
693 """
694 fmt = "{: <#018x} {: <#018x} {: <20s}"
695 out_str=''
696 pname = GetProcNameForTask(iit.iit_task)
697 if hasattr(iit, 'iit_bsd_pid'):
698 pname = "({:d}) {:s}".format(iit.iit_bsd_pid, iit.iit_procname)
699 out_str += fmt.format(iit, iit.iit_task, pname)
700 return out_str
701
702@lldb_command('showallimportancetasks')
703def ShowIPCImportanceTasks(cmd_args=[], cmd_options={}):
704 """ display a list of all tasks with ipc importance information.
705 Usage: (lldb) showallimportancetasks
706 Tip: add "-v" to see detailed information on each kmsg or inherit elems
707 """
708 print ' ' + GetIPCImportantTaskSummary.header + ' ' + GetIPCImportanceElemSummary.header
709 for t in kern.tasks:
710 s = ""
711 if unsigned(t.task_imp_base):
712 s += ' ' + GetIPCImportantTaskSummary(t.task_imp_base)
713 s += ' ' + GetIPCImportanceElemSummary(addressof(t.task_imp_base.iit_elem))
714 print s
715
716@lldb_command('showipcimportance', '')
717def ShowIPCImportance(cmd_args=[], cmd_options={}):
718 """ Describe an importance from <ipc_importance_elem_t> argument.
719 Usage: (lldb) showimportance <ipc_importance_elem_t>
720 """
721 if not cmd_args:
722 raise ArgumentError("Please provide valid argument")
723
724 elem = kern.GetValueFromAddress(cmd_args[0], 'ipc_importance_elem_t')
725 print GetIPCImportanceElemSummary.header
726 print GetIPCImportanceElemSummary(elem)
727
728@header("{: <18s} {: <10s} {: <18s} {: <18s} {: <8s} {: <5s} {: <5s} {: <5s}".format("ivac", "refs", "port", "tbl", "tblsize", "index", "Grow", "freelist"))
729@lldb_type_summary(['ipc_voucher_attr_control *', 'ipc_voucher_attr_control_t'])
730def GetIPCVoucherAttrControlSummary(ivac):
731 """ describes a voucher attribute control settings """
732 out_str = ""
733 fmt = "{c: <#018x} {c.ivac_refs: <10d} {c.ivac_port: <#018x} {c.ivac_table: <#018x} {c.ivac_table_size: <8d} {c.ivac_key_index: <5d} {growing: <5s} {c.ivac_freelist: <5d}"
734 growing_str = ""
735
736 if unsigned(ivac) == 0:
737 return "{: <#018x}".format(ivac)
738
739 if unsigned(ivac.ivac_is_growing):
740 growing_str = "Y"
741 out_str += fmt.format(c=ivac, growing = growing_str)
742 return out_str
743
744@lldb_command('showivac','')
745def ShowIPCVoucherAttributeControl(cmd_args=[], cmd_options={}):
746 """ Show summary of voucher attribute contols.
747 Usage: (lldb) showivac <ipc_voucher_attr_control_t>
748 """
749 if not cmd_args:
750 raise ArgumentError("Please provide correct arguments.")
751 ivac = kern.GetValueFromAddress(cmd_args[0], 'ipc_voucher_attr_control_t')
752 print GetIPCVoucherAttrControlSummary.header
753 print GetIPCVoucherAttrControlSummary(ivac)
754 if config['verbosity'] > vHUMAN:
755 cur_entry_index = 0
756 last_entry_index = unsigned(ivac.ivac_table_size)
757 print "index " + GetIPCVoucherAttributeEntrySummary.header
758 while cur_entry_index < last_entry_index:
759 print "{: <5d} ".format(cur_entry_index) + GetIPCVoucherAttributeEntrySummary(addressof(ivac.ivac_table[cur_entry_index]))
760 cur_entry_index += 1
761
762
763
764
765@header("{: <18s} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}".format("ivam", "get_value_fn", "extract_fn", "release_value_fn", "command_fn", "release_fn"))
766@lldb_type_summary(['ipc_voucher_attr_manager *', 'ipc_voucher_attr_manager_t'])
767def GetIPCVoucherAttrManagerSummary(ivam):
768 """ describes a voucher attribute manager settings """
769 out_str = ""
770 fmt = "{: <#018x} {: <30s} {: <30s} {: <30s} {: <30s} {: <30s}"
771
772 if unsigned(ivam) == 0 :
773 return "{: <#018x}".format(ivam)
774
775 get_value_fn = kern.Symbolicate(unsigned(ivam.ivam_get_value))
776 extract_fn = kern.Symbolicate(unsigned(ivam.ivam_extract_content))
777 release_value_fn = kern.Symbolicate(unsigned(ivam.ivam_release_value))
778 command_fn = kern.Symbolicate(unsigned(ivam.ivam_command))
779 release_fn = kern.Symbolicate(unsigned(ivam.ivam_release))
780 out_str += fmt.format(ivam, get_value_fn, extract_fn, release_value_fn, command_fn, release_fn)
781 return out_str
782
783
784
785@header("{: <18s} {: <10s} {:s} {:s}".format("ivgte", "key", GetIPCVoucherAttrControlSummary.header.strip(), GetIPCVoucherAttrManagerSummary.header.strip()))
786@lldb_type_summary(['ipc_voucher_global_table_element *', 'ipc_voucher_global_table_element_t'])
787def GetIPCVoucherGlobalTableElementSummary(ivgte):
788 """ describes a ipc_voucher_global_table_element object """
789 out_str = ""
790 fmt = "{g: <#018x} {g.ivgte_key: <10d} {ctrl_s:s} {mgr_s:s}"
791 out_str += fmt.format(g=ivgte, ctrl_s=GetIPCVoucherAttrControlSummary(ivgte.ivgte_control), mgr_s=GetIPCVoucherAttrManagerSummary(ivgte.ivgte_manager))
792 return out_str
793
794@lldb_command('showglobalvouchertable', '')
795def ShowGlobalVoucherTable(cmd_args=[], cmd_options={}):
796 """ show detailed information of all voucher attribute managers registered with vouchers system
797 Usage: (lldb) showglobalvouchertable
798 """
799 entry_size = sizeof(kern.globals.iv_global_table[0])
800 elems = sizeof(kern.globals.iv_global_table) / entry_size
801 print GetIPCVoucherGlobalTableElementSummary.header
802 for i in range(elems):
803 elt = addressof(kern.globals.iv_global_table[i])
804 print GetIPCVoucherGlobalTableElementSummary(elt)
805
806# Type summaries for Bag of Bits.
807
808@lldb_type_summary(['user_data_value_element', 'user_data_element_t'])
809@header("{0: <20s} {1: <16s} {2: <20s} {3: <20s} {4: <16s} {5: <20s}".format("user_data_ve", "maderefs", "checksum", "hash value", "size", "data"))
810def GetBagofBitsElementSummary(data_element):
811 """ Summarizes the Bag of Bits element
812 params: data_element = value of the object of type user_data_value_element_t
813 returns: String with summary of the type.
814 """
815 format_str = "{0: <#020x} {1: <16d} {2: <#020x} {3: <#020x} {4: <16d}"
816 out_string = format_str.format(data_element, unsigned(data_element.e_made), data_element.e_sum, data_element.e_hash, unsigned(data_element.e_size))
817 out_string += " 0x"
818
819 for i in range(0, (unsigned(data_element.e_size) - 1)):
820 out_string += "{:02x}".format(int(data_element.e_data[i]))
821 return out_string
822
823def GetIPCHandleSummary(handle_ptr):
824 """ converts a handle value inside a voucher attribute table to ipc element and returns appropriate summary.
825 params: handle_ptr - uint64 number stored in handle of voucher.
826 returns: str - string summary of the element held in internal structure
827 """
828 elem = kern.GetValueFromAddress(handle_ptr, 'ipc_importance_elem_t')
829 if elem.iie_bits & 0x80000000 :
830 iie = Cast(elem, 'struct ipc_importance_inherit *')
831 return GetIPCImportanceInheritSummary(iie)
832 else:
833 iit = Cast(elem, 'struct ipc_importance_task *')
834 return GetIPCImportantTaskSummary(iit)
835
836def GetATMHandleSummary(handle_ptr):
837 """ Convert a handle value to atm value and returns corresponding summary of its fields.
838 params: handle_ptr - uint64 number stored in handle of voucher
839 returns: str - summary of atm value
840 """
841 elem = kern.GetValueFromAddress(handle_ptr, 'atm_value *')
842 return GetATMValueSummary(elem)
843
844def GetBankHandleSummary(handle_ptr):
845 """ converts a handle value inside a voucher attribute table to bank element and returns appropriate summary.
846 params: handle_ptr - uint64 number stored in handle of voucher.
847 returns: str - summary of bank element
848 """
849 elem = kern.GetValueFromAddress(handle_ptr, 'bank_element_t')
850 if elem.be_type & 1 :
851 ba = Cast(elem, 'struct bank_account *')
852 return GetBankAccountSummary(ba)
853 else:
854 bt = Cast(elem, 'struct bank_task *')
855 return GetBankTaskSummary(bt)
856
857def GetBagofBitsHandleSummary(handle_ptr):
858 """ Convert a handle value to bag of bits value and returns corresponding summary of its fields.
859 params: handle_ptr - uint64 number stored in handle of voucher
860 returns: str - summary of bag of bits element
861 """
862 elem = kern.GetValueFromAddress(handle_ptr, 'user_data_element_t')
863 return GetBagofBitsElementSummary(elem)
864
865@static_var('attr_managers',{1: GetATMHandleSummary, 2: GetIPCHandleSummary, 3: GetBankHandleSummary, 7: GetBagofBitsHandleSummary})
866def GetHandleSummaryForKey(handle_ptr, key_num):
867 """ Get a summary of handle pointer from the voucher attribute manager.
868 For example key 1 -> ATM and it puts atm_value_t in the handle. So summary of it would be atm value and refs etc.
869 key 2 -> ipc and it puts either ipc_importance_inherit_t or ipc_important_task_t.
870 key 3 -> Bank and it puts either bank_task_t or bank_account_t.
871 key 7 -> Bag of Bits and it puts user_data_element_t in handle. So summary of it would be Bag of Bits content and refs etc.
872 """
873 key_num = int(key_num)
874 if key_num not in GetHandleSummaryForKey.attr_managers:
875 return "Unknown key %d" % key_num
876 return GetHandleSummaryForKey.attr_managers[key_num](handle_ptr)
877
878
879@header("{: <18s} {: <18s} {: <10s} {: <4s} {: <18s} {: <18s}".format("ivace", "value_handle", "#refs", "rel?", "maderefs", "next_layer"))
880@lldb_type_summary(['ivac_entry *', 'ivac_entry_t'])
881def GetIPCVoucherAttributeEntrySummary(ivace, manager_key_num = 0):
882 """ Get summary for voucher attribute entry.
883 """
884 out_str = ""
885 fmt = "{e: <#018x} {e.ivace_value: <#018x} {e.ivace_refs: <10d} {release: <4s} {made_refs: <18s} {next_layer: <18s}"
886 release_str = ""
887 free_str = ""
888 made_refs = ""
889 next_layer = ""
890
891 if unsigned(ivace.ivace_releasing):
892 release_str = "Y"
893 if unsigned(ivace.ivace_free):
894 free_str = 'F'
895 if unsigned(ivace.ivace_layered):
896 next_layer = "{: <#018x}".format(ivace.ivace_u.ivaceu_layer)
897 else:
898 made_refs = "{: <18d}".format(ivace.ivace_u.ivaceu_made)
899
900 out_str += fmt.format(e=ivace, release=release_str, made_refs=made_refs, next_layer=next_layer)
901 if config['verbosity'] > vHUMAN and manager_key_num > 0:
902 out_str += " " + GetHandleSummaryForKey(unsigned(ivace.ivace_value), manager_key_num)
903 if config['verbosity'] > vHUMAN :
904 out_str += ' {: <2s} {: <4d} {: <4d}'.format(free_str, ivace.ivace_next, ivace.ivace_index)
905 return out_str
906
907@lldb_command('showivacfreelist','')
908def ShowIVACFreeList(cmd_args=[], cmd_options={}):
909 """ Walk the free list and print every entry in the list.
910 usage: (lldb) showivacfreelist <ipc_voucher_attr_control_t>
911 """
912 if not cmd_args:
913 raise ArgumentError('Please provide <ipc_voucher_attr_control_t>')
914 ivac = kern.GetValueFromAddress(cmd_args[0], 'ipc_voucher_attr_control_t')
915 print GetIPCVoucherAttrControlSummary.header
916 print GetIPCVoucherAttrControlSummary(ivac)
917 if unsigned(ivac.ivac_freelist) == 0:
918 print "ivac table is full"
919 return
920 print "index " + GetIPCVoucherAttributeEntrySummary.header
921 next_free = unsigned(ivac.ivac_freelist)
922 while next_free != 0:
923 print "{: <5d} ".format(next_free) + GetIPCVoucherAttributeEntrySummary(addressof(ivac.ivac_table[next_free]))
924 next_free = unsigned(ivac.ivac_table[next_free].ivace_next)
925
926
927
928@header('{: <18s} {: <8s} {: <18s} {: <18s} {: <18s} {: <18s} {: <18s}'.format("ipc_voucher", "refs", "checksum", "hash", "tbl_size", "table", "voucher_port"))
929@lldb_type_summary(['ipc_voucher *', 'ipc_voucher_t'])
930def GetIPCVoucherSummary(voucher, show_entries=False):
931 """ describe a voucher from its ipc_voucher * object """
932 out_str = ""
933 fmt = "{v: <#018x} {v.iv_refs: <8d} {v.iv_sum: <#018x} {v.iv_hash: <#018x} {v.iv_table_size: <#018x} {v.iv_table: <#018x} {v.iv_port: <#018x}"
934 out_str += fmt.format(v = voucher)
935 entries_str = ''
936 if show_entries or config['verbosity'] > vHUMAN:
937 elems = unsigned(voucher.iv_table_size)
938 entries_header_str = "\n\t" + "{: <5s} {: <3s} {: <16s} {: <30s}".format("index", "key", "value_index", "manager") + " " + GetIPCVoucherAttributeEntrySummary.header
939 fmt = "{: <5d} {: <3d} {: <16d} {: <30s}"
940 for i in range(elems):
941 voucher_entry_index = unsigned(voucher.iv_inline_table[i])
942 if voucher_entry_index:
943 s = fmt.format(i, GetVoucherManagerKeyForIndex(i), voucher_entry_index, GetVoucherAttributeManagerNameForIndex(i))
944 e = GetVoucherValueHandleFromVoucherForIndex(voucher, i)
945 if e is not None:
946 s += " " + GetIPCVoucherAttributeEntrySummary(addressof(e), GetVoucherManagerKeyForIndex(i) )
947 if entries_header_str :
948 entries_str = entries_header_str
949 entries_header_str = ''
950 entries_str += "\n\t" + s
951 if not entries_header_str:
952 entries_str += "\n\t"
953 out_str += entries_str
954 return out_str
955
956def GetVoucherManagerKeyForIndex(idx):
957 """ Returns key number for index based on global table. Will raise index error if value is incorrect
958 """
959 return unsigned(kern.globals.iv_global_table[idx].ivgte_key)
960
961def GetVoucherAttributeManagerForKey(k):
962 """ Walks through the iv_global_table and finds the attribute manager name
963 params: k - int key number of the manager
964 return: cvalue - the attribute manager object.
965 None - if not found
966 """
967 retval = None
968 entry_size = sizeof(kern.globals.iv_global_table[0])
969 elems = sizeof(kern.globals.iv_global_table) / entry_size
970 for i in range(elems):
971 elt = addressof(kern.globals.iv_global_table[i])
972 if k == unsigned(elt.ivgte_key):
973 retval = elt.ivgte_manager
974 break
975 return retval
976
977def GetVoucherAttributeControllerForKey(k):
978 """ Walks through the iv_global_table and finds the attribute controller
979 params: k - int key number of the manager
980 return: cvalue - the attribute controller object.
981 None - if not found
982 """
983 retval = None
984 entry_size = sizeof(kern.globals.iv_global_table[0])
985 elems = sizeof(kern.globals.iv_global_table) / entry_size
986 for i in range(elems):
987 elt = addressof(kern.globals.iv_global_table[i])
988 if k == unsigned(elt.ivgte_key):
989 retval = elt.ivgte_control
990 break
991 return retval
992
993
994def GetVoucherAttributeManagerName(ivam):
995 """ find the name of the ivam object
996 param: ivam - cvalue object of type ipc_voucher_attr_manager_t
997 returns: str - name of the manager
998 """
999 return kern.Symbolicate(unsigned(ivam))
1000
1001def GetVoucherAttributeManagerNameForIndex(idx):
1002 """ get voucher attribute manager name for index
1003 return: str - name of the attribute manager object
1004 """
1005 return GetVoucherAttributeManagerName(GetVoucherAttributeManagerForKey(GetVoucherManagerKeyForIndex(idx)))
1006
1007def GetVoucherValueHandleFromVoucherForIndex(voucher, idx):
1008 """ traverse the voucher attrs and get value_handle in the voucher attr controls table
1009 params:
1010 voucher - cvalue object of type ipc_voucher_t
1011 idx - int index in the entries for which you wish to get actual handle for
1012 returns: cvalue object of type ivac_entry_t
1013 None if no handle found.
1014 """
1015 manager_key = GetVoucherManagerKeyForIndex(idx)
1016 voucher_num_elems = unsigned(voucher.iv_table_size)
1017 if idx >= voucher_num_elems:
1018 debuglog("idx %d is out of range max: %d" % (idx, voucher_num_elems))
1019 return None
1020 voucher_entry_value = unsigned(voucher.iv_inline_table[idx])
1021 debuglog("manager_key %d" % manager_key)
1022 ivac = GetVoucherAttributeControllerForKey(manager_key)
1023 if ivac is None or unsigned(ivac) == 0:
1024 debuglog("No voucher attribute controller for idx %d" % idx)
1025 return None
1026
1027 ivac = kern.GetValueFromAddress(unsigned(ivac), 'ipc_voucher_attr_control_t') # ??? No idea why lldb does not addressof directly
1028 ivace_table = ivac.ivac_table
1029 if voucher_entry_value >= unsigned(ivac.ivac_table_size):
1030 print "Failed to get ivace for value %d in table of size %d" % (voucher_entry_value, unsigned(ivac.ivac_table_size))
1031 return None
1032 return ivace_table[voucher_entry_value]
1033
1034
1035
1036@lldb_command('showallvouchers')
1037def ShowAllVouchers(cmd_args=[], cmd_options={}):
1038 """ Display a list of all vouchers in the global voucher hash table
1039 Usage: (lldb) showallvouchers
1040 """
1041 iv_hash_table = kern.globals.ivht_bucket
1042 num_buckets = sizeof(kern.globals.ivht_bucket) / sizeof(kern.globals.ivht_bucket[0])
1043 print GetIPCVoucherSummary.header
1044 for i in range(num_buckets):
1045 for v in IterateQueue(iv_hash_table[i], 'ipc_voucher_t', 'iv_hash_link'):
1046 print GetIPCVoucherSummary(v)
1047
1048@lldb_command('showvoucher', '')
1049def ShowVoucher(cmd_args=[], cmd_options={}):
1050 """ Describe a voucher from <ipc_voucher_t> argument.
1051 Usage: (lldb) showvoucher <ipc_voucher_t>
1052 """
1053 if not cmd_args:
1054 raise ArgumentError("Please provide valid argument")
1055
1056 voucher = kern.GetValueFromAddress(cmd_args[0], 'ipc_voucher_t')
1057 print GetIPCVoucherSummary.header
1058 print GetIPCVoucherSummary(voucher, show_entries=True)
1059
1060