]>
Commit | Line | Data |
---|---|---|
fe8ab488 A |
1 | from xnu import * |
2 | ||
3 | """ | |
4 | Recursive ipc importance chain viewing macro. This file incorporates complex python datastructures | |
5 | interspersed with cvalue based objects from lldb interface. | |
6 | """ | |
7 | ||
8 | class 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(Cast(self.task.bsd_info, 'proc *')) + " {: <#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 | ||
31 | class IIINode(object): | |
32 | """docstring for IIINode""" | |
33 | def __init__(self, elem, parentNode): | |
34 | super(IIINode, self).__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) & 0x80000000: | |
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) & 0x80000000: | |
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) & 0x80000000: | |
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) & 0x80000000: | |
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) & 0x80000000 == 0: | |
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 | ||
96 | def GetIIIListFromIIE(iie, rootnode): | |
97 | """ walk the iii queue and find each III element in a list format | |
98 | """ | |
99 | for i in IterateQueue(iie.iie_inherits, 'struct ipc_importance_inherit *', 'iii_inheritance'): | |
100 | iieNode = IIINode(i, rootnode) | |
101 | if unsigned(i.iii_elem.iie_bits) & 0x80000000: | |
102 | rootnode.addChildNode(iieNode) | |
103 | GetIIIListFromIIE(i.iii_elem, iieNode) | |
104 | GetTaskNodeByKernelTaskObj(iieNode.GetToTask()).AddImportanceNode(iieNode) | |
105 | return | |
106 | ||
107 | AllTasksCollection = {} | |
108 | def 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') | |
118 | def 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 | GetIIIListFromIIE(task.task_imp_base.iit_elem, 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 AllTasksCollection.keys(): | |
133 | t = AllTasksCollection[k] | |
134 | print "\n" + str(t) | |
135 |