2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """A utility script to help building Syzygy-instrumented Chrome binaries."""
17 # The default directory containing the Syzygy toolchain.
18 _DEFAULT_SYZYGY_DIR
= os
.path
.abspath(os
.path
.join(
19 os
.path
.dirname(__file__
), '../../../../..',
20 'third_party/syzygy/binaries/exe/'))
22 # Basenames of various tools.
23 _INSTRUMENT_EXE
= 'instrument.exe'
24 _GENFILTER_EXE
= 'genfilter.exe'
26 _LOGGER
= logging
.getLogger()
29 def _Shell(*cmd
, **kw
):
30 """Shells out to "cmd". Returns a tuple of cmd's stdout, stderr."""
31 _LOGGER
.info('Running command "%s".', cmd
)
32 prog
= subprocess
.Popen(cmd
, **kw
)
34 stdout
, stderr
= prog
.communicate()
35 if prog
.returncode
!= 0:
36 raise RuntimeError('Command "%s" returned %d.' % (cmd
, prog
.returncode
))
41 def _CompileFilter(syzygy_dir
, executable
, symbol
, filter_file
,
43 """Compiles the provided filter writing the compiled filter file to
46 cmd
= [os
.path
.abspath(os
.path
.join(syzygy_dir
, _GENFILTER_EXE
)),
48 '--input-image=%s' % executable
,
49 '--input-pdb=%s' % symbol
,
50 '--output-file=%s' % output_filter_file
,
52 os
.path
.abspath(filter_file
)]
55 if not os
.path
.exists(output_filter_file
):
56 raise RuntimeError('Compiled filter file missing: %s' % output_filter_file
)
60 def _InstrumentBinary(syzygy_dir
, mode
, executable
, symbol
, dst_dir
,
61 filter_file
, allocation_filter_file
):
62 """Instruments the executable found in input_dir, and writes the resultant
63 instrumented executable and symbol files to dst_dir.
65 cmd
= [os
.path
.abspath(os
.path
.join(syzygy_dir
, _INSTRUMENT_EXE
)),
69 '--input-image=%s' % executable
,
70 '--input-pdb=%s' % symbol
,
71 '--output-image=%s' % os
.path
.abspath(
72 os
.path
.join(dst_dir
, os
.path
.basename(executable
))),
73 '--output-pdb=%s' % os
.path
.abspath(
74 os
.path
.join(dst_dir
, os
.path
.basename(symbol
)))]
77 cmd
.append('--no-augment-pdb')
78 # Disable some of the new SysyASAN features. We're seeing an increase in
79 # crash rates and are wondering if they are to blame.
81 '--asan-rtl-options="--disable_ctmalloc --disable_large_block_heap"')
83 # If any filters were specified then pass them on to the instrumenter.
85 cmd
.append('--filter=%s' % os
.path
.abspath(filter_file
))
86 if allocation_filter_file
:
87 cmd
.append('--allocation-filter-config-file=%s' %
88 os
.path
.abspath(allocation_filter_file
))
94 # Make sure the destination directory exists.
95 if not os
.path
.isdir(options
.destination_dir
):
96 _LOGGER
.info('Creating destination directory "%s".',
97 options
.destination_dir
)
98 os
.makedirs(options
.destination_dir
)
100 # Compile the filter if one was provided.
102 _CompileFilter(options
.syzygy_dir
,
103 options
.input_executable
,
104 options
.input_symbol
,
106 options
.output_filter_file
)
108 # Instruments the binaries into the destination directory.
109 _InstrumentBinary(options
.syzygy_dir
,
111 options
.input_executable
,
112 options
.input_symbol
,
113 options
.destination_dir
,
114 options
.output_filter_file
,
115 options
.allocation_filter_file
)
119 option_parser
= optparse
.OptionParser()
120 option_parser
.add_option('--input_executable',
121 help='The path to the input executable.')
122 option_parser
.add_option('--input_symbol',
123 help='The path to the input symbol file.')
124 option_parser
.add_option('--mode',
125 help='Specifies which instrumentation mode is to be used.')
126 option_parser
.add_option('--syzygy-dir', default
=_DEFAULT_SYZYGY_DIR
,
127 help='Instrumenter executable to use, defaults to "%default".')
128 option_parser
.add_option('-d', '--destination_dir',
129 help='Destination directory for instrumented files.')
130 option_parser
.add_option('--filter',
131 help='An optional filter. This will be compiled and passed to the '
132 'instrumentation executable.')
133 option_parser
.add_option('--output-filter-file',
134 help='The path where the compiled filter will be written. This is '
135 'required if --filter is specified.')
136 option_parser
.add_option('--allocation-filter-file',
137 help='The path to the SyzyASAN allocation filter to use.')
138 options
, args
= option_parser
.parse_args()
141 option_parser
.error('You must provide an instrumentation mode.')
142 if not options
.input_executable
:
143 option_parser
.error('You must provide an input executable.')
144 if not options
.input_symbol
:
145 option_parser
.error('You must provide an input symbol file.')
146 if not options
.destination_dir
:
147 option_parser
.error('You must provide a destination directory.')
148 if options
.filter and not options
.output_filter_file
:
149 option_parser
.error('You must provide a filter output file.')
154 if '__main__' == __name__
:
155 logging
.basicConfig(level
=logging
.INFO
)
156 sys
.exit(main(_ParseOptions()))