X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/cb3231590a3c94ab4375e2228bd5e86b0cf1ad7e..a991bd8d3e7fe02dbca0644054bab73c5b75324a:/tools/lldbmacros/xnu.py diff --git a/tools/lldbmacros/xnu.py b/tools/lldbmacros/xnu.py index 7ec9ca7c8..d935362ab 100755 --- a/tools/lldbmacros/xnu.py +++ b/tools/lldbmacros/xnu.py @@ -669,8 +669,15 @@ def ParseMacOSPanicLog(panic_header, cmd_options={}): if other_log_begin_offset != 0 and (other_log_len == 0 or other_log_len < (cur_debug_buf_ptr_offset - other_log_begin_offset)): other_log_len = cur_debug_buf_ptr_offset - other_log_begin_offset expected_panic_magic = xnudefines.MACOS_PANIC_MAGIC - panic_stackshot_addr = unsigned(panic_header) + unsigned(panic_header.mph_stackshot_offset) - panic_stackshot_len = unsigned(panic_header.mph_stackshot_len) + + # use the global if it's available (on an x86 corefile), otherwise refer to the header + if hasattr(kern.globals, "panic_stackshot_buf"): + panic_stackshot_addr = unsigned(kern.globals.panic_stackshot_buf) + panic_stackshot_len = unsigned(kern.globals.panic_stackshot_len) + else: + panic_stackshot_addr = unsigned(panic_header) + unsigned(panic_header.mph_stackshot_offset) + panic_stackshot_len = unsigned(panic_header.mph_stackshot_len) + panic_header_flags = unsigned(panic_header.mph_panic_flags) warn_str = "" @@ -756,7 +763,7 @@ def ParseAURRPanicLog(panic_header, cmd_options={}): # Adjust panic log string length (cap to maximum supported values) if panic_log_version == xnudefines.AURR_PANIC_VERSION: - max_string_len = panic_log_reset_log_len and min(panic_log_reset_log_len, xnudefines.AURR_PANIC_STRING_LEN) or 0 + max_string_len = panic_log_reset_log_len elif panic_log_version == xnudefines.AURR_CRASHLOG_PANIC_VERSION: max_string_len = xnudefines.CRASHLOG_PANIC_STRING_LEN @@ -948,7 +955,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 +963,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 ex: (lldb) walklist_entry 0x7fffff80 "struct proc *" "p_sibling" @@ -969,22 +978,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 +1029,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 [,...,] : 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 +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 +1047,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 +1065,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 +1085,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 [,...,] : 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) + """ + 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 [,...,] : 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 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 : 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 = "" 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 * @@ -1129,7 +1223,6 @@ from pci import * from misc import * from apic import * from scheduler import * -from atm import * from structanalyze import * from ipcimportancedetail import * from bank import *