Created
June 3, 2015 04:08
-
-
Save tjw/db0e153c0e1ddb86c051 to your computer and use it in GitHub Desktop.
CGGStack dtrace wrapper script
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/zsh -euf | |
# NOTE: In order for the -c flag to work, 'main' must not be stripped from the executable. | |
# If it has been, you'll get the cryptic | |
# | |
# dtrace: failed to control pid 82297: process exited with status 0 | |
# | |
if [ $# -ne 1 ]; then | |
echo "usage: $0 [executable-name|app-path|app-identifier]" 1>&2 | |
exit 1 | |
fi | |
if [ "$UID" = "0" ]; then | |
echo "This script should not be run with sudo; it will sudo on its own when running dtrace." | |
exit 1 | |
fi | |
# Allow specifying a bundle identifier, using Spotlight to find the actual app to run. | |
app_path="" | |
case "$1" in | |
com\.*) | |
mdfind "kMDItemCFBundleIdentifier='$1'" | while read candidate; do | |
if [ -n "$app_path" ]; then | |
echo "Multiple applications found; please pass the path to the specific copy you want to run:" | |
mdfind "kMDItemCFBundleIdentifier='$1'" | |
exit 1 | |
else | |
app_path="$candidate" | |
fi | |
done | |
;; | |
*) | |
app_path="$1" | |
;; | |
esac | |
case "$app_path" in | |
*\.app) | |
process_path="$app_path/Contents/MacOS/`/usr/libexec/PlistBuddy -c Print:CFBundleExecutable "$app_path"/Contents/Info.plist`" | |
;; | |
*) | |
process_path="$app_path" | |
;; | |
esac | |
process_name="$process_path:t" | |
output_file="$HOME/Desktop/$process_name-$(date "+%Y%m%d-%H%M%S").$$.txt.gz" | |
echo "Tracing CGContext gstate operations to $output_file ..." | |
# If an application is sandboxed, it won't run correctly when launched as root (which dtrace needs). Also, we shouldn't be launching random applications as root anyway. | |
# dtrace has a -W option to wait for a named process. The process name can only be 16 bytes long though (MAXCOMLEN). | |
# The -Z flag allows dtrace to launch w/ zero matches to the probes. This is necessary for the -W flag, since the process gets stopped by the kernel before probes are registered. | |
echo "Launching dtrace, waiting for \"$process_name\"..." | |
# The "ring" policy means we'll cycle around our buffer until the process exits and only then emit output. In this case, we use the _DPSNextEvent:entry as a baseline starting point where we know there should be no gstates pushed. | |
sudo dtrace -q \ | |
-x bufsize=128m \ | |
-x bufpolicy=ring \ | |
-n 'pid$target:CoreGraphics:CGGStackCreateWithGState:return { printf("Stack create: %p\n", arg1); ustack(256); }' \ | |
-n 'pid$target:CoreGraphics:CGGStackSave:entry { printf("Context save: %p\n", arg0); ustack(256); }' \ | |
-n 'pid$target:CoreGraphics:CGGStackRestore:entry { printf("Context restore: %p\n", arg0); ustack(256); }' \ | |
-n 'pid$target:CoreGraphics:CGGStackRelease:entry { printf("Context release: %p\n", arg0); ustack(256); }' \ | |
-n 'pid$target:CoreGraphics:CGGStackReset:entry { printf("Context reset: %p\n", arg0); ustack(256); }' \ | |
-n 'pid$target:CoreGraphics:CGGStackSaveForLayer:entry { printf("Context save/layer: %p\n", arg0); ustack(256); }' \ | |
-n 'pid$target:CoreGraphics:CGGStackSetGState:entry { printf("Context set state: %p\n", arg0); ustack(256); }' \ | |
-n 'pid$target:AppKit:_DPSNextEvent:entry { ustack(); }' \ | |
-Z -W "$process_name" | gzip > "$output_file" & | |
dtrace_pid=$! | |
# Wait a bit to let dtrace get ready. Without this, it can miss the launch of the target app. | |
sleep 1 | |
# Launch the application in question and wait for it to exit (though we could launch it in the background and assume dtrace would latch onto it...) | |
"$process_path" | |
# Wait for dtrace to finish | |
echo "Waiting for dtrace to finish..." | |
wait "$dtrace_pid" | |
# Reveal the result diagnostics in Finder for the customer to submit! | |
open -R "$output_file" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment