xref: /xnu-10002.61.3/tools/lldbmacros/ipcimportancedetail.py (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1from __future__ import absolute_import, print_function
2
3from builtins import hex
4from builtins import object
5
6from xnu import *
7
8"""
9Recursive ipc importance chain viewing macro. This file incorporates complex python datastructures
10interspersed with cvalue based objects from lldb interface.
11"""
12
13class TaskNode(object):
14    def __init__(self, task_kobj):
15        self.task = task_kobj
16        self.importance_refs = []
17
18    @staticmethod
19    def GetHeaderString():
20        return GetTaskSummary.header + " " + GetProcSummary.header + " {: <18s}".format("task_imp_base")
21
22    def __str__(self):
23        out_arr = []
24        if unsigned(self.task) != 0:
25            out_arr.append(GetTaskSummary(self.task) + " " + GetProcSummary(GetProcFromTask(self.task)) + " {: <#018x}".format(self.task.task_imp_base) )
26        else:
27            out_arr.append("Unknown task.")
28        #out_arr.append("TASK: {: <#018x} {: <s}".format(self.task, GetProcNameForTask(self.task))
29        for i in self.importance_refs:
30            out_arr.append("\t" + i.GetBackRefChain())
31        return "\n".join(out_arr)
32
33    def AddImportanceNode(self, iinode):
34        self.importance_refs.append(iinode)
35
36class IIINode(object):
37    """docstring for IIINode"""
38    def __init__(self, elem, parentNode):
39        super(IIINode, self).__init__()
40        self.elem = elem
41        self.children = []
42        self.parent = parentNode
43
44    def addChildNode(self, elemNode):
45        self.children.append(elemNode)
46
47    def __str__(self):
48        if unsigned(self.elem.iii_elem.iie_bits) & xnudefines.IIE_TYPE_MASK:
49            return GetIPCImportanceInheritSummary(self.elem)
50        else:
51            return GetIPCImportantTaskSummary(self.elem)
52
53    def GetShortSummary(self):
54        to_task = self.GetToTask()
55        if unsigned(self.elem.iii_elem.iie_bits) & xnudefines.IIE_TYPE_MASK:
56            return "{: <#018x} INH ({:d}){: <s}".format(self.elem, GetProcPIDForTask(to_task), GetProcNameForTask(to_task))
57        else:
58            return "{: <#018x} IIT ({:d}){: <s}".format(self.elem, GetProcPIDForTask(to_task), GetProcNameForTask(to_task))
59
60    def GetChildSummaries(self, prefix="\t"):
61        retval = []
62        for i in self.children:
63            retval.append(prefix + str(i))
64            retval.append(i.GetChildSummaries(prefix+"\t"))
65        return "\n".join(retval)
66
67    def GetToTask(self):
68        if unsigned(self.elem.iii_elem.iie_bits) & xnudefines.IIE_TYPE_MASK:
69            return self.elem.iii_to_task.iit_task
70        else:
71            return self.elem.iit_task
72
73    def GetParentNode(self):
74        return self.parent
75
76    def GetBackRefChain(self):
77        out_str = ""
78        cur_elem = self.elem
79        out_str += self.GetShortSummary()
80        from_elem = Cast(cur_elem.iii_from_elem, 'ipc_importance_inherit *')
81        # NOTE: We are exploiting the layout of iit and iii to have iie at the begining.
82        # so casting one to another is fine as long as we tread carefully.
83
84        while (unsigned(from_elem.iii_elem.iie_bits) & xnudefines.IIE_TYPE_MASK) == xnudefines.IIE_TYPE_INHERIT:
85            out_str += " <- {: <#018x} INH ({:d}){: <s}".format(from_elem, GetProcPIDForTask(from_elem.iii_to_task.iit_task), GetProcNameForTask(from_elem.iii_to_task.iit_task))
86            from_elem = Cast(from_elem.iii_from_elem, 'ipc_importance_inherit *')
87
88        if (unsigned(from_elem.iii_elem.iie_bits) & xnudefines.IIE_TYPE_MASK) == xnudefines.IIE_TYPE_TASK:
89            iit_elem = Cast(from_elem, 'ipc_importance_task *')
90            out_str += " <- {: <#018x} IIT ({:d}){: <s}".format(iit_elem, GetProcPIDForTask(iit_elem.iit_task), GetProcNameForTask(iit_elem.iit_task))
91
92        return out_str
93
94        #unused
95        cur_elem = self
96        while cur_elem.parent:
97            out_str += "<-" + cur_elem.GetShortSummary()
98            cur_elem = cur_elem.GetParentNode()
99        return out_str
100
101def GetIIIListFromIIT(iit, rootnode):
102    """ walk the iii queue and find each III element in a list format
103    """
104    for iii in IterateQueue(iit.iit_inherits, 'struct ipc_importance_inherit *',  'iii_inheritance'):
105        iiiNode = IIINode(iii, rootnode)
106        if unsigned(iii.iii_elem.iie_bits) & xnudefines.IIE_TYPE_MASK:
107            rootnode.addChildNode(iiiNode)
108            GetIIIListFromIIT(iii.iii_to_task, iiiNode)
109            GetTaskNodeByKernelTaskObj(iiiNode.GetToTask()).AddImportanceNode(iiiNode)
110    return
111
112AllTasksCollection = {}
113def GetTaskNodeByKernelTaskObj(task_kobj):
114    global AllTasksCollection
115    key = hex(unsigned(task_kobj))
116    if key not in AllTasksCollection:
117        AllTasksCollection[key] = TaskNode(task_kobj)
118    return AllTasksCollection[key]
119
120
121
122@lldb_command('showallipcimportance')
123def ShowInheritanceChains(cmd_args=[], cmd_options={}):
124    """ show boost inheritance chains.
125        Usage: (lldb) showboostinheritancechains  <task_t>
126    """
127    print(' ' + GetIPCImportantTaskSummary.header + ' ' + GetIPCImportanceElemSummary.header)
128    for task in kern.tasks:
129        if unsigned(task.task_imp_base):
130            print(" " + GetIPCImportantTaskSummary(task.task_imp_base) + ' ' + GetIPCImportanceElemSummary(addressof(task.task_imp_base.iit_elem)))
131            base_node = IIINode(Cast(task.task_imp_base, 'ipc_importance_inherit *'), None)
132            GetIIIListFromIIT(task.task_imp_base, base_node)
133            print(base_node.GetChildSummaries(prefix="\t\t"))
134
135    print("\n\n ======================== TASK REVERSE CHAIN OF IMPORTANCES =========================")
136    print(TaskNode.GetHeaderString())
137    for k in list(AllTasksCollection.keys()):
138        t = AllTasksCollection[k]
139        print("\n" + str(t))
140
141