]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/lldbmacros/xnu.py
xnu-6153.141.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / xnu.py
index 7ec9ca7c8c88e76ae5419f73ea85f6b72848dbb9..6e58e3209985e6106a61d1455c9696031038de67 100755 (executable)
@@ -948,7 +948,7 @@ def WalkQueueHead(cmd_args=[], cmd_options={}):
 
 
 
-@lldb_command('walklist_entry', 'S')
+@lldb_command('walklist_entry', 'SE')
 def WalkList(cmd_args=[], cmd_options={}):
     """ iterate over a list as defined with LIST_ENTRY in bsd/sys/queue.h
         params:
@@ -956,7 +956,9 @@ def WalkList(cmd_args=[], cmd_options={}):
             element_type - str   : Type of the next element
             field_name   - str   : Name of the field in next element's structure
 
-        Option: -S - suppress summary output.
+        Options: -S - suppress summary output.
+                 -E - Iterate using SLIST_ENTRYs
+
         Usage: (lldb) walklist_entry  <obj with list_entry *> <struct type> <fieldname>
         ex:    (lldb) walklist_entry  0x7fffff80 "struct proc *" "p_sibling"
 
@@ -969,22 +971,25 @@ def WalkList(cmd_args=[], cmd_options={}):
     el_type = cmd_args[1]
     queue_head = kern.GetValueFromAddress(cmd_args[0], el_type)
     field_name = cmd_args[2]
-
     showsummary = False
     if el_type in lldb_summary_definitions:
         showsummary = True
     if '-S' in cmd_options:
         showsummary = False
+    if '-E' in cmd_options:
+        prefix = 's'
+    else:
+        prefix = ''
     elt = queue_head
     while unsigned(elt) != 0:
         i = elt
-        elt = elt.__getattr__(field_name).le_next
+        elt = elt.__getattr__(field_name).__getattr__(prefix + 'le_next')
         if showsummary:
             print lldb_summary_definitions[el_type](i)
         else:
             print "{0: <#020x}".format(i)
 
-def iotrace_parse_Copt(Copt):
+def trace_parse_Copt(Copt):
     """Parses the -C option argument and returns a list of CPUs
     """
     cpusOpt = Copt
@@ -1017,30 +1022,17 @@ def iotrace_parse_Copt(Copt):
     return chosen_cpus
 
 
-@lldb_command('iotrace', 'C:N:S:RB')
-def IOTrace_cmd(cmd_args=[], cmd_options={}):
-    """ Prints the iotrace ring buffers for all CPUs by default.
-        Arguments:
-          -B                              : Print backtraces for each ring entry
-          -C <cpuSpec#>[,...,<cpuSpec#N>] : Limit trace entries to those generated by the specified CPUs (each cpuSpec can be a
-                                            single CPU number or a range separated by a dash (e.g. "0-3"))
-          -N <count>                      : Limit output to the first <count> entries (across all chosen CPUs)
-          -R                              : Display results in reverse-sorted order (oldest first; default is newest-first)
-          -S <sort_key_field_name>        : Sort output by specified iotrace_entry_t field name (instead of by timestamp)
+IDX_CPU = 0
+IDX_RINGPOS = 1
+IDX_RINGENTRY = 2
+def Trace_cmd(cmd_args=[], cmd_options={}, headerString=lambda:"", entryString=lambda x:"", ring=[], entries_per_cpu=0, max_backtraces=0):
+    """Generic trace dumper helper function
     """
-    IDX_CPU = 0
-    IDX_RINGPOS = 1
-    IDX_RINGENTRY = 2
-    MAX_IOTRACE_BACKTRACES = 16
-
-    if kern.arch != "x86_64":
-        print "Sorry, iotrace is an x86-only command."
-        return
 
     if '-S' in cmd_options:
         field_arg = cmd_options['-S']
         try:
-            getattr(kern.globals.iotrace_ring[0][0], field_arg)
+            getattr(ring[0][0], field_arg)
             sort_key_field_name = field_arg
         except AttributeError:
             raise ArgumentError("Invalid sort key field name `%s'" % field_arg)
@@ -1048,7 +1040,7 @@ def IOTrace_cmd(cmd_args=[], cmd_options={}):
             sort_key_field_name = 'start_time_abs'
 
     if '-C' in cmd_options:
-        chosen_cpus = iotrace_parse_Copt(cmd_options['-C'])
+        chosen_cpus = trace_parse_Copt(cmd_options['-C'])
     else:
         chosen_cpus = [x for x in range(kern.globals.real_ncpus)]
 
@@ -1066,7 +1058,7 @@ def IOTrace_cmd(cmd_args=[], cmd_options={}):
     # the original ring index, and the iotrace entry. 
     entries = []
     for x in chosen_cpus:
-        ring_slice = [(x, y, kern.globals.iotrace_ring[x][y]) for y in range(kern.globals.iotrace_entries_per_cpu)]
+        ring_slice = [(x, y, ring[x][y]) for y in range(entries_per_cpu)]
         entries.extend(ring_slice)
 
     total_entries = len(entries)
@@ -1086,33 +1078,128 @@ def IOTrace_cmd(cmd_args=[], cmd_options={}):
     else:
         entries_to_display = total_entries
 
-    print "%-19s %-8s %-10s %-20s SZ %-18s %-17s DATA" % (
-        "START TIME",
-        "DURATION",
-        "CPU#[RIDX]",
-        "      TYPE",
-        "   VIRT ADDR",
-        "   PHYS ADDR")
+    print headerString()
 
     for x in xrange(entries_to_display):
-        print "%-20u(%6u) %6s[%02d] %-20s %d 0x%016x 0x%016x 0x%x" % (
-            entries[x][IDX_RINGENTRY].start_time_abs,
-            entries[x][IDX_RINGENTRY].duration,
-            "CPU%d" % entries[x][IDX_CPU],
-            entries[x][IDX_RINGPOS],
-            str(entries[x][IDX_RINGENTRY].iotype).split("=")[1].strip(),
-            entries[x][IDX_RINGENTRY].size,
-            entries[x][IDX_RINGENTRY].vaddr,
-            entries[x][IDX_RINGENTRY].paddr,
-            entries[x][IDX_RINGENTRY].val)
+        print entryString(entries[x])
+
         if backtraces:
-            for btidx in range(MAX_IOTRACE_BACKTRACES):
+            for btidx in range(max_backtraces):
                 nextbt = entries[x][IDX_RINGENTRY].backtrace[btidx]
                 if nextbt == 0:
                     break
                 print "\t" + GetSourceInformationForAddress(nextbt)
+
+
+@lldb_command('iotrace', 'C:N:S:RB')
+def IOTrace_cmd(cmd_args=[], cmd_options={}):
+    """ Prints the iotrace ring buffers for all CPUs by default.
+        Arguments:
+          -B                              : Print backtraces for each ring entry
+          -C <cpuSpec#>[,...,<cpuSpec#N>] : Limit trace entries to those generated by the specified CPUs (each cpuSpec can be a
+                                            single CPU number or a range separated by a dash (e.g. "0-3"))
+          -N <count>                      : Limit output to the first <count> entries (across all chosen CPUs)
+          -R                              : Display results in reverse-sorted order (oldest first; default is newest-first)
+          -S <sort_key_field_name>        : Sort output by specified iotrace_entry_t field name (instead of by timestamp)
+    """
+    MAX_IOTRACE_BACKTRACES = 16
+
+    if kern.arch != "x86_64":
+        print "Sorry, iotrace is an x86-only command."
+        return
+
+    hdrString = lambda : "%-19s %-8s %-10s %-20s SZ  %-18s %-17s DATA" % (
+        "START TIME",
+        "DURATION",
+        "CPU#[RIDX]",
+        "      TYPE",
+        "   VIRT ADDR",
+        "   PHYS ADDR")
+
+    entryString = lambda x : "%-20u(%6u) %6s[%02d] %-20s %-2d 0x%016x 0x%016x 0x%x" % (
+        x[IDX_RINGENTRY].start_time_abs,
+        x[IDX_RINGENTRY].duration,
+        "CPU%d" % x[IDX_CPU],
+        x[IDX_RINGPOS],
+        str(x[IDX_RINGENTRY].iotype).split("=")[1].strip(),
+        x[IDX_RINGENTRY].size,
+        x[IDX_RINGENTRY].vaddr,
+        x[IDX_RINGENTRY].paddr,
+        x[IDX_RINGENTRY].val)
+
+    Trace_cmd(cmd_args, cmd_options, hdrString, entryString, kern.globals.iotrace_ring, kern.globals.iotrace_entries_per_cpu, MAX_IOTRACE_BACKTRACES)
+
+
+@lldb_command('ttrace', 'C:N:S:RB')
+def TrapTrace_cmd(cmd_args=[], cmd_options={}):
+    """ Prints the iotrace ring buffers for all CPUs by default.
+        Arguments:
+          -B                              : Print backtraces for each ring entry
+          -C <cpuSpec#>[,...,<cpuSpec#N>] : Limit trace entries to those generated by the specified CPUs (each cpuSpec can be a
+                                            single CPU number or a range separated by a dash (e.g. "0-3"))
+          -N <count>                      : Limit output to the first <count> entries (across all chosen CPUs)
+          -R                              : Display results in reverse-sorted order (oldest first; default is newest-first)
+          -S <sort_key_field_name>        : Sort output by specified traptrace_entry_t field name (instead of by timestamp)
+    """
+    MAX_TRAPTRACE_BACKTRACES = 8
+
+    if kern.arch != "x86_64":
+        print "Sorry, ttrace is an x86-only command."
+        return
+
+    hdrString = lambda : "%-30s CPU#[RIDX] VECT INTERRUPTED_THREAD PREMLV INTRLV INTERRUPTED_PC" % (
+        "START TIME   (DURATION [ns])")
+    entryString = lambda x : "%-20u(%6s) %8s[%02d] 0x%02x 0x%016x %6d %6d %s" % (
+        x[IDX_RINGENTRY].start_time_abs,
+        str(x[IDX_RINGENTRY].duration) if hex(x[IDX_RINGENTRY].duration) != "0xffffffffffffffff" else 'inprog',
+        "CPU%d" % x[IDX_CPU],
+        x[IDX_RINGPOS],
+        int(x[IDX_RINGENTRY].vector),
+        x[IDX_RINGENTRY].curthread,
+        x[IDX_RINGENTRY].curpl,
+        x[IDX_RINGENTRY].curil,
+        GetSourceInformationForAddress(x[IDX_RINGENTRY].interrupted_pc))
+
+    Trace_cmd(cmd_args, cmd_options, hdrString, entryString, kern.globals.traptrace_ring,
+        kern.globals.traptrace_entries_per_cpu, MAX_TRAPTRACE_BACKTRACES)
                 
 
+@lldb_command('showsysctls', 'P:')
+def ShowSysctls(cmd_args=[], cmd_options={}):
+    """ Walks the list of sysctl data structures, printing out each during traversal.
+        Arguments:
+          -P <string> : Limit output to sysctls starting with the specified prefix.
+    """
+    if '-P' in cmd_options:
+        _ShowSysctl_prefix = cmd_options['-P']
+        allowed_prefixes = _ShowSysctl_prefix.split('.')
+        if allowed_prefixes:
+            for x in xrange(1, len(allowed_prefixes)):
+                allowed_prefixes[x] = allowed_prefixes[x - 1] + "." + allowed_prefixes[x]
+    else:
+        _ShowSysctl_prefix = ''
+        allowed_prefixes = []
+    def IterateSysctls(oid, parent_str, i):
+        headp = oid
+        parentstr = "<none>" if parent_str is None else parent_str
+        for pp in IterateListEntry(headp, 'struct sysctl_oid *', 'oid_link', 's'):
+            type = pp.oid_kind & 0xf
+            next_parent = str(pp.oid_name)
+            if parent_str is not None:
+                next_parent = parent_str + "." + next_parent
+            st = (" " * i) + str(pp.GetSBValue().Dereference()).replace("\n", "\n" + (" " * i))
+            if type == 1 and pp.oid_arg1 != 0:
+                # Check allowed_prefixes to see if we can recurse from root to the allowed prefix.
+                # To recurse further, we need to check only the the next parent starts with the user-specified
+                # prefix
+                if next_parent not in allowed_prefixes and next_parent.startswith(_ShowSysctl_prefix) is False:
+                    continue
+                print 'parent = "%s"' % parentstr, st[st.find("{"):]
+                IterateSysctls(Cast(pp.oid_arg1, "struct sysctl_oid_list *"), next_parent, i + 2)
+            elif _ShowSysctl_prefix == '' or next_parent.startswith(_ShowSysctl_prefix):
+                print ('parent = "%s"' % parentstr), st[st.find("{"):]
+    IterateSysctls(kern.globals.sysctl__children, None, 0)
+
 
 
 from memory import *