]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/lldbmacros/ioreg.py
xnu-4903.221.2.tar.gz
[apple/xnu.git] / tools / lldbmacros / ioreg.py
old mode 100644 (file)
new mode 100755 (executable)
index 26cb4b6..e2bdaf2
@@ -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 <address of object to be dumped> [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'<vtable for ([A-Za-z].*)>', 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