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