summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2016-05-17 08:17:14 (GMT)
committerKevin Smith <kevin.smith@isode.com>2016-05-26 09:46:59 (GMT)
commit606e6090fcefb82a21a2d73b75af96ee77734207 (patch)
tree4ba389986ee7a28eebebf51b584f3037964250ec /BuildTools
parent64901783526b8d9c9370b297bfd1d109a6cc0bbe (diff)
downloadswift-606e6090fcefb82a21a2d73b75af96ee77734207.zip
swift-606e6090fcefb82a21a2d73b75af96ee77734207.tar.bz2
Add minidump analysis python script for Windows crash dumps
This script takes a Swift version and minidump file path as arguments and will checkout the corresponding source, fetch and extract the corresponding installer, fetch and extract the corresponding debug symbols to finally run the Windows SDK command line debugger (cdb) to write a human readable stack trace and further info to a txt file. Test-Information: Tested it successfully on Windows 10 with various minidumps. Change-Id: I5915255dfb23e6b45c1273a3c1c42cc83125df57
Diffstat (limited to 'BuildTools')
-rw-r--r--BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py b/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py
new file mode 100644
index 0000000..dada920
--- /dev/null
+++ b/BuildTools/CrashReportAnalysis/WindowsMinidumpAnalyse.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+# Note
+# ----
+# This script requires:
+# - cdb, the Windows command line debugger installed and available in PATH.
+# - the SWIFT_DIST environment variable set to a locatioon that contains msi and pdb.gz files.
+
+import sys
+from subprocess import call
+from subprocess import Popen, PIPE
+import ntpath
+import shutil
+import re
+import urllib2
+import os
+import gzip
+import time
+
+
+swiftWindowBuildsPathPrefix = os.getenv("SWIFT_DIST")
+if swiftWindowBuildsPathPrefix == None :
+ print "Please set the SWIFT_DIST environment variable to a location containing msi and pdb.gz files."
+ sys.exit(1)
+
+if len(sys.argv) != 3:
+ print "Usage: python WindowsMinidumpAnalyse.py VERSION MINIDUMP_FILE"
+ sys.exit(1)
+
+version = sys.argv[1]
+minidump_file = sys.argv[2]
+minidump_filename = ntpath.basename(minidump_file)
+minidump_fullpath = os.path.abspath(minidump_file)
+humantext_fullpath = os.path.splitext(minidump_fullpath)[0]+".txt"
+symbol_cache_path = os.path.join(os.getenv("TEMP"), "\symbols")
+working_folder = "tmp-crash-{0}".format(minidump_filename)
+commit = ""
+
+def downloadInstaller(version) :
+ onlineFilename = "{0}.msi".format(version.capitalize())
+ url = "{0}{1}".format(swiftWindowBuildsPathPrefix, onlineFilename)
+ print("Download {0}.".format(url))
+ file = urllib2.urlopen(url)
+ with open(onlineFilename,'wb') as output:
+ output.write(file.read())
+
+def unpackInstaller(version) :
+ msiFilename = "{0}.msi".format(version.capitalize())
+ msiExtractDirectory = os.getcwd() + "\\msi"
+ if not os.path.exists(msiExtractDirectory):
+ os.makedirs(msiExtractDirectory)
+ print("Unpack {0} to {1}.".format(msiFilename, os.getcwd()))
+ call(["msiexec", "/a", msiFilename, "/qb", "TARGETDIR={0}".format(msiExtractDirectory)], shell=True)
+
+def unpackDebugSymbols(version) :
+ symbolsFilename = "{0}.pdb.gz".format(version.capitalize())
+ print("Unpack {0}.".format(symbolsFilename))
+ if not os.path.isdir(symbolsFilename):
+ with gzip.open(symbolsFilename, 'rb') as in_file:
+ s = in_file.read()
+
+ path_to_store = symbolsFilename[:-3]
+
+ with open("msi\PFiles\Swift\{0}".format("Swift.pdb"), 'wb') as f:
+ f.write(s)
+
+def downloadDebugSymbols(version) :
+ onlineFilename = "{0}.pdb.gz".format(version.capitalize())
+ url = "{0}{1}".format(swiftWindowBuildsPathPrefix, onlineFilename)
+ print("Download {0}.".format(url))
+ file = urllib2.urlopen(url)
+ with open(onlineFilename,'wb') as output:
+ output.write(file.read())
+
+def copyMinidump(filename) :
+ shutil.copyfile(filename, "msi\PFiles\Swift\{0}".format(minidump_filename))
+
+def printHumanReadableReport():
+ oldDir = os.getcwd()
+
+ # change dir to Swift.exe dir
+ os.chdir("msi\PFiles\Swift")
+
+ # print all stacks and analyze crash for exceptions
+ cdbCommand = ".symopt+0x40;.lines -e;.kframes 200;!analyze -v -p;!uniqstack -vp;.ecxr;k;q"
+
+ symbolPath = "cache*{0};srv*https://msdl.microsoft.com/download/symbols;C:\\Qt\\Qt5.4.2\\5.4\\msvc2013_opengl\\bin;C:\\Qt\\Qt5.4.2\\5.4\\msvc2013_opengl\\lib;{1}".format(symbol_cache_path, os.getcwd())
+
+ cdbFullCommand = ["cdb", "-i", os.getcwd(), "-y", symbolPath, "-z", minidump_filename, "-srcpath", oldDir, "-logo", humantext_fullpath, "-c", cdbCommand ]
+ print("Run command: " + str(cdbFullCommand))
+ call(cdbFullCommand)
+
+# for testing, delete the old folder
+try:
+ shutil.rmtree(working_folder)
+except:
+ print ""
+
+# clone local git repository into dedicated directory
+call(["git", "clone", ".", working_folder], shell=True)
+
+# git version from swift version
+match = re.match( r"(.*)-dev(\d+)", version)
+if match:
+ basetag = match.group(1)
+ commits = int(match.group(2))
+ process = Popen(["git", "-C", working_folder, "log", "--ancestry-path", "--format=%H", "{0}..HEAD".format(basetag)], stdout=PIPE)
+ (output, err) = process.communicate()
+ exit_code = process.wait()
+ commit = output.splitlines()[-commits].strip()
+else:
+ basetag = version
+ process = Popen(["git", "-C", working_folder, "log", "--format=%H", "-n", "1" "{0}".format(basetag)], stdout=PIPE)
+ (output, err) = process.communicate()
+ exit_code = process.wait()
+ commit = output.strip()
+
+assert(len(commit) > 0)
+
+# Create symbol cache directory
+if not os.path.exists(symbol_cache_path):
+ os.makedirs(symbol_cache_path)
+
+#print "Checking out commit {0}.".format(commit)
+call(["git", "-C", working_folder, "checkout", commit])
+
+os.chdir(working_folder)
+
+downloadInstaller(version)
+downloadDebugSymbols(version)
+unpackInstaller(version)
+unpackDebugSymbols(version)
+copyMinidump(minidump_fullpath)
+time.sleep(10)
+printHumanReadableReport()