+def ProcessPanicStackshot(panic_stackshot_addr, panic_stackshot_len):
+ """ Process the panic stackshot from the panic header, saving it to a file if it is valid
+ params: panic_stackshot_addr : start address of the panic stackshot binary data
+ panic_stackshot_len : length of the stackshot binary data
+ returns: nothing
+ """
+ if not panic_stackshot_addr:
+ print "No panic stackshot available (invalid addr)"
+ return
+
+ if not panic_stackshot_len:
+ print "No panic stackshot available (zero length)"
+ return;
+
+ ts = int(time.time())
+ ss_binfile = "/tmp/panic_%d.bin" % ts
+ ss_ipsfile = "/tmp/stacks_%d.ips" % ts
+
+ if not SaveDataToFile(panic_stackshot_addr, panic_stackshot_len, ss_binfile, None):
+ print "Failed to save stackshot binary data to file"
+ return
+
+ self_path = str(__file__)
+ base_dir_name = self_path[:self_path.rfind("/")]
+ print "python %s/kcdata.py %s -s %s" % (base_dir_name, ss_binfile, ss_ipsfile)
+ (c,so,se) = RunShellCommand("python %s/kcdata.py %s -s %s" % (base_dir_name, ss_binfile, ss_ipsfile))
+ if c == 0:
+ print "Saved ips stackshot file as %s" % ss_ipsfile
+ return
+ else:
+ print "Failed to run command: exit code: %d, SO: %s SE: %s" % (c, so, se)
+ return
+
+def ParseEmbeddedPanicLog(panic_header, cmd_options={}):
+ panic_buf = Cast(panic_header, 'char *')
+ panic_log_magic = unsigned(panic_header.eph_magic)
+ panic_log_begin_offset = unsigned(panic_header.eph_panic_log_offset)
+ panic_log_len = unsigned(panic_header.eph_panic_log_len)
+ other_log_begin_offset = unsigned(panic_header.eph_other_log_offset)
+ other_log_len = unsigned(panic_header.eph_other_log_len)
+ expected_panic_magic = xnudefines.EMBEDDED_PANIC_MAGIC
+ panic_stackshot_addr = unsigned(panic_header) + unsigned(panic_header.eph_stackshot_offset)
+ panic_stackshot_len = unsigned(panic_header.eph_stackshot_len)
+ panic_header_flags = unsigned(panic_header.eph_panic_flags)
+
+ warn_str = ""
+ out_str = ""
+
+ if panic_log_magic != 0 and panic_log_magic != expected_panic_magic:
+ warn_str += "BAD MAGIC! Found 0x%x expected 0x%x" % (panic_log_magic,
+ expected_panic_magic)
+
+ if warn_str:
+ print "\n %s" % warn_str
+ if panic_log_begin_offset == 0:
+ return
+
+ if "-S" in cmd_options:
+ if panic_header_flags & xnudefines.EMBEDDED_PANIC_STACKSHOT_SUCCEEDED_FLAG:
+ ProcessPanicStackshot(panic_stackshot_addr, panic_stackshot_len)
+ else:
+ print "No panic stackshot available"
+
+ panic_log_curindex = 0
+ while panic_log_curindex < panic_log_len:
+ p_char = str(panic_buf[(panic_log_begin_offset + panic_log_curindex)])
+ out_str += p_char
+ panic_log_curindex += 1
+
+ if other_log_begin_offset != 0:
+ other_log_curindex = 0
+ while other_log_curindex < other_log_len:
+ p_char = str(panic_buf[(other_log_begin_offset + other_log_curindex)])
+ out_str += p_char
+ other_log_curindex += 1
+
+ print out_str
+ return
+
+def ParseMacOSPanicLog(panic_header, cmd_options={}):
+ panic_buf = Cast(panic_header, 'char *')
+ panic_log_magic = unsigned(panic_header.mph_magic)
+ panic_log_begin_offset = unsigned(panic_header.mph_panic_log_offset)
+ panic_log_len = unsigned(panic_header.mph_panic_log_len)
+ other_log_begin_offset = unsigned(panic_header.mph_other_log_offset)
+ other_log_len = unsigned(panic_header.mph_other_log_len)
+ cur_debug_buf_ptr_offset = (unsigned(kern.globals.debug_buf_ptr) - unsigned(panic_header))
+ 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
+
+ # 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 = ""
+ out_str = ""
+
+ if panic_log_magic != 0 and panic_log_magic != expected_panic_magic:
+ warn_str += "BAD MAGIC! Found 0x%x expected 0x%x" % (panic_log_magic,
+ expected_panic_magic)
+
+ if warn_str:
+ print "\n %s" % warn_str
+ if panic_log_begin_offset == 0:
+ return
+
+ if "-S" in cmd_options:
+ if panic_header_flags & xnudefines.MACOS_PANIC_STACKSHOT_SUCCEEDED_FLAG:
+ ProcessPanicStackshot(panic_stackshot_addr, panic_stackshot_len)
+ else:
+ print "No panic stackshot available"
+
+ panic_log_curindex = 0
+ while panic_log_curindex < panic_log_len:
+ p_char = str(panic_buf[(panic_log_begin_offset + panic_log_curindex)])
+ out_str += p_char
+ panic_log_curindex += 1
+
+ if other_log_begin_offset != 0:
+ other_log_curindex = 0
+ while other_log_curindex < other_log_len:
+ p_char = str(panic_buf[(other_log_begin_offset + other_log_curindex)])
+ out_str += p_char
+ other_log_curindex += 1
+
+ print out_str
+ return
+
+def ParseAURRPanicLog(panic_header, cmd_options={}):
+ reset_cause = {
+ 0x0: "OTHER",
+ 0x1: "CATERR",
+ 0x2: "SWD_TIMEOUT",
+ 0x3: "GLOBAL RESET",
+ 0x4: "STRAIGHT TO S5",
+ }
+
+ expected_panic_magic = xnudefines.AURR_PANIC_MAGIC
+
+ panic_buf = Cast(panic_header, 'char *')
+
+ try:
+ # This line will blow up if there's not type info for this struct (older kernel)
+ # We fall back to manual parsing below
+ aurr_panic_header = Cast(panic_header, 'struct efi_aurr_panic_header *')
+ panic_log_magic = unsigned(aurr_panic_header.efi_aurr_magic)
+ panic_log_version = unsigned(aurr_panic_header.efi_aurr_version)
+ panic_log_reset_cause = unsigned(aurr_panic_header.efi_aurr_reset_cause)
+ panic_log_reset_log_offset = unsigned(aurr_panic_header.efi_aurr_reset_log_offset)
+ panic_log_reset_log_len = unsigned(aurr_panic_header.efi_aurr_reset_log_len)
+ except Exception as e:
+ print "*** Warning: kernel symbol file has no type information for 'struct efi_aurr_panic_header'..."
+ print "*** Warning: trying to manually parse..."
+ aurr_panic_header = Cast(panic_header, "uint32_t *")
+ panic_log_magic = unsigned(aurr_panic_header[0])
+ # panic_log_crc = unsigned(aurr_panic_header[1])
+ panic_log_version = unsigned(aurr_panic_header[2])
+ panic_log_reset_cause = unsigned(aurr_panic_header[3])
+ panic_log_reset_log_offset = unsigned(aurr_panic_header[4])
+ panic_log_reset_log_len = unsigned(aurr_panic_header[5])
+
+ if panic_log_magic != 0 and panic_log_magic != expected_panic_magic:
+ print "BAD MAGIC! Found 0x%x expected 0x%x" % (panic_log_magic,
+ expected_panic_magic)
+ return
+
+ print "AURR Panic Version: %d" % (panic_log_version)
+
+ # When it comes time to extend this in the future, please follow the
+ # construct used below in ShowPanicLog()
+ if panic_log_version in (xnudefines.AURR_PANIC_VERSION, xnudefines.AURR_CRASHLOG_PANIC_VERSION):
+ # AURR Report Version 1 (AURR/MacEFI) or 2 (Crashlog)
+ # see macefifirmware/Vendor/Apple/EfiPkg/AppleDebugSupport/Library/Debugger.h
+ print "Reset Cause: 0x%x (%s)" % (panic_log_reset_cause, reset_cause.get(panic_log_reset_cause, "UNKNOWN"))
+
+ # 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
+ elif panic_log_version == xnudefines.AURR_CRASHLOG_PANIC_VERSION:
+ max_string_len = xnudefines.CRASHLOG_PANIC_STRING_LEN
+
+ panic_str_offset = 0
+ out_str = ""
+
+ while panic_str_offset < max_string_len:
+ p_char = str(panic_buf[panic_log_reset_log_offset + panic_str_offset])
+ out_str += p_char
+ panic_str_offset += 1