summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'BuildTools/CrashReportAnalysis')
-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()