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 *
8from atm import *
9from bank import *
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:
83                out_str = "unknown"
84            break
85
86    return out_str
87
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"))
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 = ""
100    out_string += "{0: <19s} {1: <#019x} {2: <8s} {3: <#011x} ".format(
101                    ' '*19, unsigned(kmsgp), ' '*8, kmsgh.msgh_id)
102
103    if (kmsgh.msgh_bits & 0xff) == 17:
104        out_string += "{0: <2s}".format("rS")
105    else:
106        out_string += "{0: <2s}".format("rO")
107
108    if (kmsgh.msgh_bits & 0xff00) == (17 << 8):
109        out_string += "{0: <2s}".format("lS")
110    else:
111        if (kmsgh.msgh_bits & 0xff00) == (18 << 8):
112            out_string += "{0: <2s}".format("lO")
113        else:
114            out_string += "{0: <2s}".format("l-")
115    if kmsgh.msgh_bits & 0xf0000000:
116        out_string += "{0: <2s}".format("c")
117    else:
118        out_string += "{0: <2s}".format("s")
119
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)
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])
259        if xnudefines.kobject_types[objtype_index] in ('TASK_RESUME', 'TASK'):
260            desc_str += " " + GetProcNameForTask(Cast(portval.kdata.kobject, 'task *'))
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'
354        portval = Cast(ie_object, 'ipc_port_t')
355        if int(entry.index.request) != 0:
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'
364        if portval.ip_nsrequest != 0: right_str +='x'
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)
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"
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:
584        psetoff = getfieldoffset('struct ipc_pset', 'ips_messages')
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
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
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
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
1061