Files
textmate/Frameworks/CrashReporter/bin/symbolicate
2014-02-18 23:09:53 +07:00

82 lines
2.5 KiB
Ruby
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env ruby -wKU
#
# http://developer.apple.com/library/mac/#technotes/tn2004/tn2123.html
require "fileutils"
require "shellwords"
DSYM_ARCHIVE_DIR = "#{ENV['HOME']}/build/TextMate/Applications/TextMate/dsym"
DSYM_CACHE_DIR = "#{ENV['HOME']}/Library/Caches/com.macromates.TextMate/dsym"
BinaryImage = Struct.new(:first, :last, :name, :file)
def find_dsym(process, version)
path = File.expand_path("#{process}_#{version}", DSYM_CACHE_DIR)
return path if File.directory?(path)
archive = File.expand_path("#{process}_#{version}.tbz", DSYM_ARCHIVE_DIR)
return nil unless File.file?(archive)
FileUtils.mkdir_p(path)
STDERR << "Extracting dsym to #{path}’…\n"
%x{ tar -jxf #{archive.shellescape} -C #{path.shellescape} }
path
end
class BinaryImages
def initialize(files, report)
uuid_to_file = { }
files.each do |file|
res = %x{dwarfdump -u "#{file}"}
file = file.sub(%r{([^/]+?)(\.(app|framework))?\.dSYM$}, "\\0/Contents/Resources/DWARF/\\1") if File.directory? file
uuid_to_file[$1.gsub(/-/, '')] = file if res =~ /UUID: ([0-9A-F\-]*)/
end
@images = [ ]
if report =~ /^Binary Images:\n((?:\s*0x[[:xdigit:]]+ - \s*0x[[:xdigit:]]+.*\n)+)/i
$1.scan(/(0x[[:xdigit:]]+) - \s*(0x[[:xdigit:]]+)\s+\+?(\S+).*?<([0-9a-fA-F\-]+)>/).each do |arr|
first, last, name, uuid = *arr
uuid = uuid.gsub(/-/, '').upcase
@images << BinaryImage.new(first.to_i(16), last.to_i(16), name, uuid_to_file[uuid]) if uuid_to_file.member? uuid
end
end
end
def lookup(addr)
@images.each do |image|
next unless image.first <= addr && addr < image.last
res = %x{xcrun atos 2>/dev/null -o #{image.file} -l 0x#{image.first.to_s(16)} 0x#{addr.to_s(16)}}.chomp
res.gsub!(/ \(in #{File.basename image.file}\)/, '')
return res
end
nil
end
end
report = STDIN.read
process = $1 if report =~ /^Process:\s+(\w+)\s+\[\d+\]$/
version = $1 if report =~ /^Version:\s+(\S+) \(.*\)$/
dsym_dir = find_dsym(process, version)
abort "No dsym information for #{process} #{version}." if dsym_dir.nil?
images = BinaryImages.new(Dir["#{dsym_dir}/*"], report)
symbolicated = report.gsub(/^(Thread \d+(?: Crashed)?:.*)\n(?m:(.*?))\n\n/) do
threadName, stackDump = $1, $2
stackDump = stackDump.gsub(/^(.*?\s)(0x[[:xdigit:]]+)\s(.*)$/) do
left, addr, right = $1, $2, $3
if info = images.lookup(addr.to_i(16))
right = info
end
"#{left}#{addr} #{right}"
end
"#{threadName}\n#{stackDump}\n\n"
end
puts symbolicated