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