| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Makes sure that all EXE and DLL files in the provided directory were built | 6 """Makes sure that all EXE and DLL files in the provided directory were built |
| 7 correctly. | 7 correctly. |
| 8 | 8 |
| 9 In essense it runs a subset of BinScope tests ensuring that binaries have | 9 In essense it runs a subset of BinScope tests ensuring that binaries have |
| 10 /NXCOMPAT, /DYNAMICBASE and /SAFESEH. | 10 /NXCOMPAT, /DYNAMICBASE and /SAFESEH. |
| 11 """ | 11 """ |
| 12 | 12 |
| 13 import os | 13 import os |
| 14 import optparse | 14 import optparse |
| 15 import sys | 15 import sys |
| 16 | 16 |
| 17 # Find /third_party/pefile based on current directory and script path. | 17 # Find /third_party/pefile based on current directory and script path. |
| 18 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', | 18 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', |
| 19 'third_party', 'pefile')) | 19 'third_party', 'pefile')) |
| 20 import pefile | 20 import pefile |
| 21 | 21 |
| 22 PE_FILE_EXTENSIONS = ['.exe', '.dll'] | 22 PE_FILE_EXTENSIONS = ['.exe', '.dll'] |
| 23 DYNAMICBASE_FLAG = 0x0040 | 23 DYNAMICBASE_FLAG = 0x0040 |
| 24 NXCOMPAT_FLAG = 0x0100 | 24 NXCOMPAT_FLAG = 0x0100 |
| 25 NO_SEH_FLAG = 0x0400 | 25 NO_SEH_FLAG = 0x0400 |
| 26 MACHINE_TYPE_AMD64 = 0x8664 |
| 26 | 27 |
| 27 # Please do not add your file here without confirming that it indeed doesn't | 28 # Please do not add your file here without confirming that it indeed doesn't |
| 28 # require /NXCOMPAT and /DYNAMICBASE. Contact cpu@chromium.org or your local | 29 # require /NXCOMPAT and /DYNAMICBASE. Contact cpu@chromium.org or your local |
| 29 # Windows guru for advice. | 30 # Windows guru for advice. |
| 30 EXCLUDED_FILES = ['chrome_frame_mini_installer.exe', | 31 EXCLUDED_FILES = ['chrome_frame_mini_installer.exe', |
| 31 'mini_installer.exe', | 32 'mini_installer.exe', |
| 32 'wow_helper.exe'] | 33 'wow_helper.exe'] |
| 33 | 34 |
| 34 def IsPEFile(path): | 35 def IsPEFile(path): |
| 35 return (os.path.isfile(path) and | 36 return (os.path.isfile(path) and |
| (...skipping 24 matching lines...) Expand all Loading... |
| 60 print "Checking %s for /DYNAMICBASE... FAIL" % path | 61 print "Checking %s for /DYNAMICBASE... FAIL" % path |
| 61 | 62 |
| 62 # Check for /NXCOMPAT. | 63 # Check for /NXCOMPAT. |
| 63 if pe.OPTIONAL_HEADER.DllCharacteristics & NXCOMPAT_FLAG: | 64 if pe.OPTIONAL_HEADER.DllCharacteristics & NXCOMPAT_FLAG: |
| 64 if options.verbose: | 65 if options.verbose: |
| 65 print "Checking %s for /NXCOMPAT... PASS" % path | 66 print "Checking %s for /NXCOMPAT... PASS" % path |
| 66 else: | 67 else: |
| 67 success = False | 68 success = False |
| 68 print "Checking %s for /NXCOMPAT... FAIL" % path | 69 print "Checking %s for /NXCOMPAT... FAIL" % path |
| 69 | 70 |
| 70 # Check for /SAFESEH. Binaries should either have no SEH table | 71 # Check for /SAFESEH. Binaries should meet one of the following |
| 71 # (in which case a bit is set in the DLL characteristics section) | 72 # criteria: |
| 72 # or there should be a LOAD_CONFIG section present containing | 73 # 1) Have no SEH table as indicated by the DLL characteristics |
| 73 # a valid SEH table. | 74 # 2) Have a LOAD_CONFIG section containing a valid SEH table |
| 75 # 3) Be a 64-bit binary, in which case /SAFESEH isn't required |
| 76 # |
| 77 # Refer to the following MSDN article for more information: |
| 78 # http://msdn.microsoft.com/en-us/library/9a89h429.aspx |
| 74 if (pe.OPTIONAL_HEADER.DllCharacteristics & NO_SEH_FLAG or | 79 if (pe.OPTIONAL_HEADER.DllCharacteristics & NO_SEH_FLAG or |
| 75 (hasattr(pe, "DIRECTORY_ENTRY_LOAD_CONFIG") and | 80 (hasattr(pe, "DIRECTORY_ENTRY_LOAD_CONFIG") and |
| 76 pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerCount > 0 and | 81 pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerCount > 0 and |
| 77 pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable != 0)): | 82 pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable != 0) or |
| 83 pe.FILE_HEADER.Machine == MACHINE_TYPE_AMD64): |
| 78 if options.verbose: | 84 if options.verbose: |
| 79 print "Checking %s for /SAFESEH... PASS" % path | 85 print "Checking %s for /SAFESEH... PASS" % path |
| 80 else: | 86 else: |
| 81 # TODO(scherkus): uncomment this code after we're confident that we | 87 # TODO(scherkus): uncomment this code after we're confident that we |
| 82 # won't cause unintentional failures on the build bots. | 88 # won't cause unintentional failures on the build bots. |
| 83 #success = False | 89 #success = False |
| 84 print "Checking %s for /SAFESEH... FAIL" % path | 90 print "Checking %s for /SAFESEH... FAIL" % path |
| 85 | 91 |
| 86 # Update tally. | 92 # Update tally. |
| 87 if success: | 93 if success: |
| 88 pe_passed = pe_passed + 1 | 94 pe_passed = pe_passed + 1 |
| 89 | 95 |
| 90 print "Result: %d files found, %d files passed" % (pe_total, pe_passed) | 96 print "Result: %d files found, %d files passed" % (pe_total, pe_passed) |
| 91 if pe_passed != pe_total: | 97 if pe_passed != pe_total: |
| 92 sys.exit(1) | 98 sys.exit(1) |
| 93 | 99 |
| 94 if __name__ == '__main__': | 100 if __name__ == '__main__': |
| 95 usage = "Usage: %prog [options] DIRECTORY" | 101 usage = "Usage: %prog [options] DIRECTORY" |
| 96 option_parser = optparse.OptionParser(usage=usage) | 102 option_parser = optparse.OptionParser(usage=usage) |
| 97 option_parser.add_option("-v", "--verbose", action="store_true", | 103 option_parser.add_option("-v", "--verbose", action="store_true", |
| 98 default=False, help="Print debug logging") | 104 default=False, help="Print debug logging") |
| 99 options, args = option_parser.parse_args() | 105 options, args = option_parser.parse_args() |
| 100 if not args: | 106 if not args: |
| 101 option_parser.print_help() | 107 option_parser.print_help() |
| 102 sys.exit(0) | 108 sys.exit(0) |
| 103 main(options, args) | 109 main(options, args) |
| OLD | NEW |