X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4bd07ac2140668789aa3ee8ec4dde4a3e0a3bba5..d9a64523371fa019c4575bb400cbbc3a50ac9903:/tools/lldbmacros/ioreg.py?ds=sidebyside diff --git a/tools/lldbmacros/ioreg.py b/tools/lldbmacros/ioreg.py old mode 100644 new mode 100755 index 26cb4b64a..e2bdaf20e --- a/tools/lldbmacros/ioreg.py +++ b/tools/lldbmacros/ioreg.py @@ -1,5 +1,6 @@ from xnu import * from utils import * +from kdp import * import sys ###################################### @@ -34,16 +35,17 @@ def GetObjectSummary(obj): vt = dereference(Cast(obj, 'uintptr_t *')) - 2 * sizeof('uintptr_t') vtype = kern.SymbolicateFromAddress(vt) + if len(vtype): + vtype_str = " <" + vtype[0].GetName() + ">" + else: + vtype_str = "" if hasattr(obj, 'retainCount'): retCount = (obj.retainCount & 0xffff) - cntnrRetCount = (retCount >> 16) - out_string = "`object 0x{0: <16x}, vt 0x{1: <16x} <{2:s}>, retain count {3:d}, container retain {4:d}` ".format(obj, vt, vtype[0].GetName(), retCount, cntnrRetCount) + cntnrRetCount = (obj.retainCount >> 16) + out_string = "`object 0x{0: <16x}, vt 0x{1: <16x}{2:s}, retain count {3:d}, container retain {4:d}` ".format(obj, vt, vtype_str, retCount, cntnrRetCount) else: - if len(vtype): - out_string = "`object 0x{0: <16x}, vt 0x{1: <16x} <{2:s}>` ".format(obj, vt, vtype[0].GetName()) - else: - out_string = "`object 0x{0: <16x}, vt 0x{1: <16x}` ".format(obj, vt) - + out_string = "`object 0x{0: <16x}, vt 0x{1: <16x}{2:s}` ".format(obj, vt, vtype_str) + ztvAddr = kern.GetLoadAddressForSymbol('_ZTV8OSString') if vt == ztvAddr: out_string += GetString(obj) @@ -81,6 +83,25 @@ def GetObjectSummary(obj): return out_string + +def GetObjectTypeStr(obj): + """ Return the type of an OSObject's container class + """ + if obj is None: + return None + + vt = dereference(Cast(obj, 'uintptr_t *')) - 2 * sizeof('uintptr_t') + vtype = kern.SymbolicateFromAddress(vt) + if len(vtype): + return vtype[0].GetName() + + # See if the value is in a kext with no symbols + for kval in IterateLinkedList(kern.globals.kmod, 'next'): + if vt >= unsigned(kval.address) and vt <= (unsigned(kval.address) + unsigned(kval.size)): + return "kmod:{:s}+{:#0x}".format(kval.name, vt - unsigned(kval.address)) + return None + + @lldb_type_summary(['IORegistryEntry *']) @header("") def GetRegistryEntrySummary(entry): @@ -161,6 +182,45 @@ def ShowObject(cmd_args=None): obj = kern.GetValueFromAddress(cmd_args[0], 'OSObject *') print GetObjectSummary(obj) +#Macro: dumpobject +@lldb_command('dumpobject') +def DumpObject(cmd_args=None): + """ Dumps object information if it is a valid object confirmed by showobject + Usage: dumpobject
[class/struct type of object] + """ + if not cmd_args: + print "No arguments passed" + print DumpObject.__doc__ + return False + + if len(cmd_args) == 1: + try: + object_info = lldb_run_command("showobject {:s}".format(cmd_args[0])) + except: + print "Error!! showobject failed due to invalid value" + print DumpObject.__doc__ + return False + + srch = re.search(r'', object_info) + if not srch: + print "Error!! Couldn't find object in registry, input type manually as 2nd argument" + print DumpObject.__doc__ + return False + + object_type = srch.group(1) + else: + type_lookup = lldb_run_command("image lookup -t {:s}".format(cmd_args[1])) + if type_lookup.find(cmd_args[1])!= -1: + object_type = cmd_args[1] + else: + print "Error!! Input type {:s} isn't available in image lookup".format(cmd_args[1]) + return False + + print "******** Object Dump for value \'{:s}\' with type \"{:s}\" ********".format(cmd_args[0], object_type) + print lldb_run_command("p/x *({:s}*){:s}".format(object_type, cmd_args[0])) + +#EndMacro: dumpobject + @lldb_command('setregistryplane') def SetRegistryPlane(cmd_args=None): """ Set the plane to be used for the IOKit registry macros @@ -839,10 +899,10 @@ def showinterruptstats(cmd_args=None): Workloop Time: Total time spent running the kernel context handler """ - header_format = "{0: <20s} {1: >5s} {2: >20s} {3: >20s} {4: >20s} {5: >20s} {6: >20s}" - content_format = "{0: <20s} {1: >5d} {2: >20d} {3: >20d} {4: >20d} {5: >20d} {6: >20d}" + header_format = "{0: <20s} {1: >5s} {2: >20s} {3: >20s} {4: >20s} {5: >20s} {6: >20s} {7: >20s} {8: >20s} {9: >20s}" + content_format = "{0: <20s} {1: >5d} {2: >20d} {3: >20d} {4: >20d} {5: >20d} {6: >20d} {7: >20d} {8: >20d} {9: >#20x}" - print header_format.format("Name", "Index", "Interrupt Count", "Interrupt Time", "Workloop Count", "Workloop CPU Time", "Workloop Time") + print header_format.format("Name", "Index", "Interrupt Count", "Interrupt Time", "Avg Interrupt Time", "Workloop Count", "Workloop CPU Time", "Workloop Time", "Avg Workloop Time", "Owner") for i in kern.interrupt_stats: owner = CastIOKitClass(i.owner, 'IOInterruptEventSource *') @@ -875,7 +935,16 @@ def showinterruptstats(cmd_args=None): second_level_cpu_time = i.interruptStatistics[3] second_level_system_time = i.interruptStatistics[4] - print content_format.format(nub_name, interrupt_index, first_level_count, first_level_time, second_level_count, second_level_cpu_time, second_level_system_time) + avg_first_level_time = 0 + if first_level_count != 0: + avg_first_level_time = first_level_time / first_level_count + + avg_second_level_time = 0 + if second_level_count != 0: + avg_second_level_time = second_level_system_time / second_level_count + + print content_format.format(nub_name, interrupt_index, first_level_count, first_level_time, avg_first_level_time, + second_level_count, second_level_cpu_time, second_level_system_time, avg_second_level_time, owner) return True