X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/cc8bc92ae4a8e9f1a1ab61bf83d34ad8150b3405..0a7de7458d150b5d4dffc935ba399be265ef0a1a:/tools/lldbmacros/xnu.py diff --git a/tools/lldbmacros/xnu.py b/tools/lldbmacros/xnu.py index 8b5d5bb1e..688001678 100755 --- a/tools/lldbmacros/xnu.py +++ b/tools/lldbmacros/xnu.py @@ -793,6 +793,135 @@ def WalkList(cmd_args=[], cmd_options={}): else: print "{0: <#020x}".format(i) +def iotrace_parse_Copt(Copt): + """Parses the -C option argument and returns a list of CPUs + """ + cpusOpt = Copt + cpuList = cpusOpt.split(",") + chosen_cpus = [] + for cpu_num_string in cpuList: + try: + if '-' in cpu_num_string: + parts = cpu_num_string.split('-') + if len(parts) != 2 or not (parts[0].isdigit() and parts[1].isdigit()): + raise ArgumentError("Invalid cpu specification: %s" % cpu_num_string) + firstRange = int(parts[0]) + lastRange = int(parts[1]) + if firstRange >= kern.globals.real_ncpus or lastRange >= kern.globals.real_ncpus: + raise ValueError() + if lastRange < firstRange: + raise ArgumentError("Invalid CPU range specified: `%s'" % cpu_num_string) + for cpu_num in range(firstRange, lastRange + 1): + if cpu_num not in chosen_cpus: + chosen_cpus.append(cpu_num) + else: + chosen_cpu = int(cpu_num_string) + if chosen_cpu < 0 or chosen_cpu >= kern.globals.real_ncpus: + raise ValueError() + if chosen_cpu not in chosen_cpus: + chosen_cpus.append(chosen_cpu) + except ValueError: + raise ArgumentError("Invalid CPU number specified. Valid range is 0..%d" % (kern.globals.real_ncpus - 1)) + + 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 [,...,] : 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 : Limit output to the first entries (across all chosen CPUs) + -R : Display results in reverse-sorted order (oldest first; default is newest-first) + -S : Sort output by specified iotrace_entry_t field name (instead of by timestamp) + """ + 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) + sort_key_field_name = field_arg + except AttributeError: + raise ArgumentError("Invalid sort key field name `%s'" % field_arg) + else: + sort_key_field_name = 'start_time_abs' + + if '-C' in cmd_options: + chosen_cpus = iotrace_parse_Copt(cmd_options['-C']) + else: + chosen_cpus = [x for x in range(kern.globals.real_ncpus)] + + try: + limit_output_count = int(cmd_options['-N']) + except ValueError: + raise ArgumentError("Invalid output count `%s'" % cmd_options['-N']); + except KeyError: + limit_output_count = None + + reverse_sort = '-R' in cmd_options + backtraces = '-B' in cmd_options + + # entries will be a list of 3-tuples, each holding the CPU on which the iotrace entry was collected, + # 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)] + entries.extend(ring_slice) + + total_entries = len(entries) + + entries.sort(key=lambda x: getattr(x[IDX_RINGENTRY], sort_key_field_name), reverse=reverse_sort) + + if limit_output_count is not None and limit_output_count > total_entries: + print ("NOTE: Output count `%d' is too large; showing all %d entries" % (limit_output_count, total_entries)); + limit_output_count = total_entries + + if len(chosen_cpus) < kern.globals.real_ncpus: + print "NOTE: Limiting to entries from cpu%s %s" % ("s" if len(chosen_cpus) > 1 else "", str(chosen_cpus)) + + if limit_output_count is not None and limit_output_count < total_entries: + entries_to_display = limit_output_count + print "NOTE: Limiting to the %s" % ("first entry" if entries_to_display == 1 else ("first %d entries" % entries_to_display)) + 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") + + 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) + if backtraces: + for btidx in range(MAX_IOTRACE_BACKTRACES): + nextbt = entries[x][IDX_RINGENTRY].backtrace[btidx] + if nextbt == 0: + break + print "\t" + GetSourceInformationForAddress(nextbt) + + from memory import * @@ -802,6 +931,7 @@ from pmap import * from ioreg import * from mbufs import * from net import * +from skywalk import * from kdp import * from userspace import * from pci import * @@ -812,6 +942,7 @@ from atm import * from structanalyze import * from ipcimportancedetail import * from bank import * +from turnstile import * from kasan import * from kauth import * from waitq import * @@ -820,5 +951,6 @@ from ktrace import * from pgtrace import * from xnutriage import * from kevent import * +from workqueue import * from ntstat import * - +from zonetriage import *