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) & 0x80000000: 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) & 0x80000000: 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) & 0x80000000: 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) & 0x80000000: 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) & 0x80000000 == 0: 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 GetIIIListFromIIE(iie, rootnode): 102 """ walk the iii queue and find each III element in a list format 103 """ 104 for i in IterateQueue(iie.iie_inherits, 'struct ipc_importance_inherit *', 'iii_inheritance'): 105 iieNode = IIINode(i, rootnode) 106 if unsigned(i.iii_elem.iie_bits) & 0x80000000: 107 rootnode.addChildNode(iieNode) 108 GetIIIListFromIIE(i.iii_elem, iieNode) 109 GetTaskNodeByKernelTaskObj(iieNode.GetToTask()).AddImportanceNode(iieNode) 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 GetIIIListFromIIE(task.task_imp_base.iit_elem, 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