From 7ea1309a28c1f443fc964d431560e39a2d180de4 Mon Sep 17 00:00:00 2001 From: SkyLined Date: Mon, 26 Oct 2015 11:51:06 +0100 Subject: [PATCH 1/2] Add code to download and expand PDB files from microsoft symbol store --- ExpandCab.ps1 | 9 +++++++ PDBTypeCopy.py | 23 ++++++++++++++++ fbCopyPDBTypeData.py | 21 +++++++++++++++ fbDownloadPDB.py | 63 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 ExpandCab.ps1 create mode 100644 PDBTypeCopy.py create mode 100644 fbCopyPDBTypeData.py create mode 100644 fbDownloadPDB.py diff --git a/ExpandCab.ps1 b/ExpandCab.ps1 new file mode 100644 index 0000000..99ae867 --- /dev/null +++ b/ExpandCab.ps1 @@ -0,0 +1,9 @@ +Param([string]$sSourcePath, [string]$sDestinationPath) + +$oShell = New-Object -Comobject "Shell.Application" +if (!$?) { + $(Throw "unable to create Shell.Application object") +} +$oCab = $oShell.Namespace($sSourcePath).items() +$oDestinationFolder = $oShell.Namespace($sDestinationPath) +$oDestinationFolder.CopyHere($oCab) diff --git a/PDBTypeCopy.py b/PDBTypeCopy.py new file mode 100644 index 0000000..7b0e8b2 --- /dev/null +++ b/PDBTypeCopy.py @@ -0,0 +1,23 @@ +import os, sys; +from fbDownloadPDB import fbDownloadPDB; +from fbCopyPDBTypeData import fbCopyPDBTypeData; +from pdb_type_theft import PDB7, TPI_STREAM; + +if __name__ == "__main__": + if (len(sys.argv) != 5): + print "Usage: %s [file] [from hash] [to hash] [symbols folder path]" + sys.exit(1); + + sFileName, sFromHash, sToHash, sSymbolCacheFolderPath = sys.argv[1:]; + if (not fbDownloadPDB(sFileName, sFromHash, sSymbolCacheFolderPath)): + sys.exit(1); + if (not fbDownloadPDB(sFileName, sToHash, sSymbolCacheFolderPath)): + sys.exit(1); + + sPDBFromFilePath = os.path.join(sSymbolCacheFolderPath, sFileName, sFromHash, sFileName); + sPDBToFilePath = os.path.join(sSymbolCacheFolderPath, sFileName, sToHash, sFileName); + if (not fbCopyPDBTypeData(sPDBFromFilePath, sPDBToFilePath)): + sys.exit(1); + + print "+ PDB types copied successfully."; + diff --git a/fbCopyPDBTypeData.py b/fbCopyPDBTypeData.py new file mode 100644 index 0000000..cd75535 --- /dev/null +++ b/fbCopyPDBTypeData.py @@ -0,0 +1,21 @@ +import os; + +def fbCopyPDBTypeData(sPDBFromFilePath, sPDBToFilePath): + print "* Copying PDB type data..."; + with open(sPDBFromFilePath, 'rb') as hPdbFromFile: + oFromPDB = PDB7(hPdbFromFile); + + with open(sPDBToFilePath, 'rb') as hPDBToFile: + oToPDB = PDB7(hPDBToFile); + uFromTPIHashStream = oFromPDB.streams[TPI_STREAM].stream; + uToTPIHashStream = oToPDB.streams[TPI_STREAM].stream; + + oToPDB.streams[TPI_STREAM] = oFromPDB.streams[TPI_STREAM]; + oToPDB.streams[TPI_STREAM].stream = uToTPIHashStream; + oToPDB.streams[TPI_STREAM]._update_data(); + oToPDB.streams[uToTPIHashStream] = oFromPDB.streams[uFromTPIHashStream]; + + print "* Saving updated PDB file..."; + with open(sPDBToFilePath, 'wb') as hPDBToFile: + oToPDB.dump(hPDBToFile) + print " * PDB file size: %d bytes." % (os.path.getsize(sPDBToFilePath)); diff --git a/fbDownloadPDB.py b/fbDownloadPDB.py new file mode 100644 index 0000000..e3d9a8b --- /dev/null +++ b/fbDownloadPDB.py @@ -0,0 +1,63 @@ +import os, re, subprocess, sys, urllib, urllib2; + +sPowershellEXEPath = os.path.join(os.getenv("SystemRoot"), "System32", "Windowspowershell", "v1.0", "powershell.exe"); +sExpendsCabPS1Path = os.path.abspath(os.path.join(os.path.dirname("__file__"), "ExpandCab.ps1")); + +def fbDownloadPDB(sFileName, sHash, sSymbolCacheFolderPath): + sPdbFolderPath = os.path.join(sSymbolCacheFolderPath, sFileName, sHash); + sPdbFilePath = os.path.join(sPdbFolderPath, sFileName); +# if (os.path.isfile(sPdbFilePath)): +# print "* File already exists in local cache"; +# return True; + + print "* Downloading PDB Cab file for %s @ %s..." % (sFileName, sHash); + sCabFileURL = "http://msdl.microsoft.com/download/symbols/%s/%s/%s" % (sFileName, sHash, sFileName[:-1] + "_"); + oCabFileRequest = urllib2.Request(sCabFileURL, headers = {"User-Agent": "Microsoft-Symbol-Server/6.6.0007.5"}); + sTempCabFile = urllib2.urlopen(oCabFileRequest).read(); + print " * Cab file size: %d bytes." % (len(sTempCabFile)); + sTempCabFilePath = os.path.join(os.environ["TEMP"], "%s@%s.cab" % (sFileName, sHash)); + open(sTempCabFilePath, "wb").write(sTempCabFile); + + if (not os.path.isdir(sPdbFolderPath)): + os.makedirs(sPdbFolderPath); + + # Back up current file if any + if (os.path.isfile(sPdbFilePath)): + sPdbBackupFilePath = os.path.join(sPdbFolderPath, "#old#%s" % sFileName); + # Delete existing back up if any + if (os.path.isfile(sPdbBackupFilePath)): + os.remove(sPdbBackupFilePath); + # Back up current file + os.rename(sPdbFilePath, sPdbBackupFilePath); + print "* Extracting PDB Cab file to %s..." % sPdbFolderPath; + if (subprocess.call([sPowershellEXEPath, sExpendsCabPS1Path, sTempCabFilePath, sPdbFolderPath])): + print "- Extraction failed."; + # Delete failed PDB file if any + if (os.path.isfile(sPdbFilePath)): + os.remove(sPdbFilePath); + # Restore back up if any + if (sPdbBackupFilePath and os.path.isfile(sPdbBackupFilePath)): + os.rename(sPdbBackupFilePath, sPdbFilePath); + return False; + + if (not os.path.isfile(sPdbFilePath)): + print "- Extraction did not reveal a %s file as expected." % sFileName; + # Restore back up if any + if (sPdbBackupFilePath and os.path.isfile(sPdbBackupFilePath)): + os.rename(sPdbBackupFilePath, sPdbFilePath); + return False; + + # Remove back up if any + if (sPdbBackupFilePath and os.path.isfile(sPdbBackupFilePath)): + os.remove(sPdbBackupFilePath); + + print " * PDB file size: %d bytes." % (os.path.getsize(sPdbFilePath)); + return True; + +if __name__ == "__main__": + if (len(sys.argv) != 4): + print "Usage: %s [file] [hash] [symbols folder path]" + sys.exit(1); + sFileName, sHash, sSymbolCacheFolderPath = sys.argv[1:]; + if (not fbDownloadPDB(sFileName, sHash, sSymbolCacheFolderPath)): + sys.exit(1); \ No newline at end of file From c6a7b0266d2ca5b7aa10ebc28866eca634e0b2f9 Mon Sep 17 00:00:00 2001 From: SkyLined Date: Mon, 26 Oct 2015 12:04:35 +0100 Subject: [PATCH 2/2] Fix naming inconsistencies and import errors --- PDBTypeCopy.py | 1 - fbCopyPDBTypeData.py | 1 + fbDownloadPDB.py | 45 ++++++++++++++++++++++---------------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/PDBTypeCopy.py b/PDBTypeCopy.py index 7b0e8b2..4f3f00d 100644 --- a/PDBTypeCopy.py +++ b/PDBTypeCopy.py @@ -1,7 +1,6 @@ import os, sys; from fbDownloadPDB import fbDownloadPDB; from fbCopyPDBTypeData import fbCopyPDBTypeData; -from pdb_type_theft import PDB7, TPI_STREAM; if __name__ == "__main__": if (len(sys.argv) != 5): diff --git a/fbCopyPDBTypeData.py b/fbCopyPDBTypeData.py index cd75535..58106d8 100644 --- a/fbCopyPDBTypeData.py +++ b/fbCopyPDBTypeData.py @@ -1,4 +1,5 @@ import os; +from pdb_type_theft import PDB7, TPI_STREAM; def fbCopyPDBTypeData(sPDBFromFilePath, sPDBToFilePath): print "* Copying PDB type data..."; diff --git a/fbDownloadPDB.py b/fbDownloadPDB.py index e3d9a8b..d5bad90 100644 --- a/fbDownloadPDB.py +++ b/fbDownloadPDB.py @@ -4,9 +4,9 @@ sExpendsCabPS1Path = os.path.abspath(os.path.join(os.path.dirname("__file__"), "ExpandCab.ps1")); def fbDownloadPDB(sFileName, sHash, sSymbolCacheFolderPath): - sPdbFolderPath = os.path.join(sSymbolCacheFolderPath, sFileName, sHash); - sPdbFilePath = os.path.join(sPdbFolderPath, sFileName); -# if (os.path.isfile(sPdbFilePath)): + sPDBFolderPath = os.path.join(sSymbolCacheFolderPath, sFileName, sHash); + sPDBFilePath = os.path.join(sPDBFolderPath, sFileName); +# if (os.path.isfile(sPDBFilePath)): # print "* File already exists in local cache"; # return True; @@ -18,40 +18,41 @@ def fbDownloadPDB(sFileName, sHash, sSymbolCacheFolderPath): sTempCabFilePath = os.path.join(os.environ["TEMP"], "%s@%s.cab" % (sFileName, sHash)); open(sTempCabFilePath, "wb").write(sTempCabFile); - if (not os.path.isdir(sPdbFolderPath)): - os.makedirs(sPdbFolderPath); + if (not os.path.isdir(sPDBFolderPath)): + os.makedirs(sPDBFolderPath); + sPDBBackupFilePath = None; # Back up current file if any - if (os.path.isfile(sPdbFilePath)): - sPdbBackupFilePath = os.path.join(sPdbFolderPath, "#old#%s" % sFileName); + if (os.path.isfile(sPDBFilePath)): + sPDBBackupFilePath = os.path.join(sPDBFolderPath, "#old#%s" % sFileName); # Delete existing back up if any - if (os.path.isfile(sPdbBackupFilePath)): - os.remove(sPdbBackupFilePath); + if (os.path.isfile(sPDBBackupFilePath)): + os.remove(sPDBBackupFilePath); # Back up current file - os.rename(sPdbFilePath, sPdbBackupFilePath); - print "* Extracting PDB Cab file to %s..." % sPdbFolderPath; - if (subprocess.call([sPowershellEXEPath, sExpendsCabPS1Path, sTempCabFilePath, sPdbFolderPath])): + os.rename(sPDBFilePath, sPDBBackupFilePath); + print "* Extracting PDB Cab file to %s..." % sPDBFolderPath; + if (subprocess.call([sPowershellEXEPath, sExpendsCabPS1Path, sTempCabFilePath, sPDBFolderPath])): print "- Extraction failed."; # Delete failed PDB file if any - if (os.path.isfile(sPdbFilePath)): - os.remove(sPdbFilePath); + if (os.path.isfile(sPDBFilePath)): + os.remove(sPDBFilePath); # Restore back up if any - if (sPdbBackupFilePath and os.path.isfile(sPdbBackupFilePath)): - os.rename(sPdbBackupFilePath, sPdbFilePath); + if (sPDBBackupFilePath and os.path.isfile(sPDBBackupFilePath)): + os.rename(sPDBBackupFilePath, sPDBFilePath); return False; - if (not os.path.isfile(sPdbFilePath)): + if (not os.path.isfile(sPDBFilePath)): print "- Extraction did not reveal a %s file as expected." % sFileName; # Restore back up if any - if (sPdbBackupFilePath and os.path.isfile(sPdbBackupFilePath)): - os.rename(sPdbBackupFilePath, sPdbFilePath); + if (sPDBBackupFilePath and os.path.isfile(sPDBBackupFilePath)): + os.rename(sPDBBackupFilePath, sPDBFilePath); return False; # Remove back up if any - if (sPdbBackupFilePath and os.path.isfile(sPdbBackupFilePath)): - os.remove(sPdbBackupFilePath); + if (sPDBBackupFilePath and os.path.isfile(sPDBBackupFilePath)): + os.remove(sPDBBackupFilePath); - print " * PDB file size: %d bytes." % (os.path.getsize(sPdbFilePath)); + print " * PDB file size: %d bytes." % (os.path.getsize(sPDBFilePath)); return True; if __name__ == "__main__":