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(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 31class 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 96def 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 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 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 136