Last active
August 16, 2021 20:24
-
-
Save toonetown/6f77d12a143655c8825f6a757d854674 to your computer and use it in GitHub Desktop.
A script which will help decode macOS kernel panics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
########### | |
# A script which will help to decode macOS kernel panics | |
########### | |
# Helper functions | |
function do_jq { | |
_J="$(which jq 2>/dev/null)" || { | |
echo "You must install jq (brew install jq) to use the script" >&2; return 1; | |
}; "${_J}" "$@" | |
} | |
function make_absolute { cd "$(dirname "${1}")"; echo "$(pwd)/$(basename "${1}")"; } | |
function strip_trailing_slash { echo "${1}" | sed -e 's/\/$//g'; } | |
function exit_usage { cat << EOF | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
!! ${1} | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
Usage: ${0} <PANIC_FILE> <PATH_TO_KEXT> [PATH_TO_KDK] | |
Note: You must place the dSYM file in the same directory as the KEXT file is located | |
KDKs are downloaded from https://developer.apple.com/downloads/ and when installed are placed locally | |
in /Library/Developer/KDKs. | |
If you do not specify a path to the KDK, the script will attempt to locate the KDK corresponding to the | |
macOS version in the panic file. | |
EOF | |
exit 1 | |
} | |
# Point to the right xcode | |
: ${XCODE:="/Applications/Xcode-10.3.app"} | |
LLDB="${XCODE}/Contents/Developer/usr/bin/lldb" | |
[ -x "${LLDB}" ] || { exit_usage "Missing Xcode version 10.3 - set XCODE environment variable"; } | |
# Check our panic file | |
PANIC_FILE="$(make_absolute "${1}")" | |
[ -f "${PANIC_FILE}" ] || { exit_usage "Missing panic file ${1}"; } | |
PANIC_DATA="$(cat "${PANIC_FILE}")" | |
echo "${PANIC_DATA}" | grep -q macOSPanicString && { | |
PANIC_DATA="$(echo "${PANIC_DATA}" | grep macOSPanicString | do_jq -r .macOSPanicString)" | |
} | |
OS_VER="$(echo "${PANIC_DATA}" | grep -a1 'Mac OS version:' 2>/dev/null | tail -n1)" | |
[ -n "${OS_VER}" ] || { exit_usage "Invalid panic file ${1}"; } | |
# Check the KEXT file | |
KEXT_PATH="$(strip_trailing_slash "$(make_absolute "${2}")")" | |
KEXT_PLIST="${KEXT_PATH}/Contents/Info.plist" | |
KEXT_ID="$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "${KEXT_PLIST}" 2>/dev/null)" | |
KEXT_VER="$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${KEXT_PLIST}" 2>/dev/null)" | |
KEXT_EXE="$(/usr/libexec/PlistBuddy -c "Print :CFBundleExecutable" "${KEXT_PLIST}" 2>/dev/null)" | |
KEXT_BIN="${KEXT_PATH}/Contents/MacOS/${KEXT_EXE}" | |
[ -f "${KEXT_BIN}" ] || { exit_usage "Invalid or missing kext path ${2}"; } | |
# Check the dSYM | |
DSYM_PATH="${KEXT_PATH}.dSYM" | |
[ -d "${DSYM_PATH}" ] || { exit_usage "Missing dSYM at ${DSYM_PATH}"; } | |
# Check the provided KDK (or find one) | |
if [ -d "${3}" ]; then | |
KDK_PATH="$(strip_trailing_slash "$(make_absolute "${3}")")" | |
else | |
KDK_PATH="$(ls -d "/Library/Developer/KDKs/"*"_${OS_VER}.kdk" 2>/dev/null)" | |
[ -d "${KDK_PATH}" ] || { exit_usage "Could not find KDK for OS Version ${OS_VER}"; } | |
fi | |
KDK_KERN="${KDK_PATH}/System/Library/Kernels/kernel" | |
KDK_SCRIPT="${KDK_KERN}.dSYM/Contents/Resources/Python/kernel.py" | |
[ -f "${KDK_KERN}" -a -f "${KDK_SCRIPT}" ] || { exit_usage "Invalid or missing KDK path ${3}"; } | |
echo "=========================" | |
echo "Symbolicate: ${PANIC_FILE}" | |
echo " with: ${KDK_PATH}" | |
echo " image: ${KEXT_PATH}" | |
echo " symbols: ${DSYM_PATH}" | |
echo "-------------------------" | |
COMMANDS=() | |
COMMANDS+=("command script import \"${KDK_SCRIPT}\"") | |
COMMANDS+=("settings set target.load-script-from-symbol-file true") | |
LOAD_ADDR="$(echo "${PANIC_DATA}" | sed -nE "s/^ +${KEXT_ID}\(${KEXT_VER}\).*@(0x[a-f0-9]+)->0x[a-f0-9]+$/\1/p")" | |
[ -n "${LOAD_ADDR}" ] || { exit_usage "Could not find ${KEXT_ID}(${KEXT_VER}) load address in ${PANIC_FILE}"; } | |
COMMANDS+=("addkext -F \"${KEXT_BIN}\" ${LOAD_ADDR}") | |
for i in $(echo "${PANIC_DATA}" | sed -nE 's/^0x[a-f0-9]+ : (0x[a-f0-9]+).*$/\1/p'); do | |
COMMANDS+=("image lookup -a ${i}") | |
done | |
for i in "${COMMANDS[@]}"; do echo "${i}"; done | PATH="/usr/bin:${PATH}" "${LLDB}" "${KDK_KERN}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Functionality from this script has been merged into https://gist.github.com/toonetown/618507f37da728bbfe3f3e3490c8a550