diff options
author | Jack Lloyd <[email protected]> | 2017-08-30 13:41:43 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-08-30 13:41:43 -0400 |
commit | bb305eff61014d326ae59f0e98a22c5bdf4842fc (patch) | |
tree | 39e4aa92698a73cdbea7658102dea60bd0555352 /configure.py | |
parent | 931fc0db4ae4a2b63c81bee65186bd181368a5cd (diff) |
Add support for fuzzing with KLEE
For the fuzzers, builds an object and then links in a second step,
because we need that to link the fuzzer binaries for LLVM. (Clang
will emit bitcode for us, but doesn't want to link it.)
Diffstat (limited to 'configure.py')
-rwxr-xr-x | configure.py | 77 |
1 files changed, 47 insertions, 30 deletions
diff --git a/configure.py b/configure.py index a01addbd0..b2c18fa94 100755 --- a/configure.py +++ b/configure.py @@ -186,9 +186,11 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes if options.build_fuzzers: self.fuzzer_sources = list(find_sources_in(source_paths.src_dir, 'fuzzer')) self.fuzzer_output_dir = os.path.join(self.build_dir, 'fuzzer') + self.fuzzobj_dir = os.path.join(self.build_dir, 'obj', 'fuzzer') else: self.fuzzer_sources = None self.fuzzer_output_dir = None + self.fuzzobj_dir = None def build_dirs(self): out = [ @@ -203,6 +205,7 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes if self.doc_output_dir_doxygen: out += [self.doc_output_dir_doxygen] if self.fuzzer_output_dir: + out += [self.fuzzobj_dir] out += [self.fuzzer_output_dir] return out @@ -214,7 +217,7 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes elif typ == 'test': return (self.test_sources, self.testobj_dir) elif typ == 'fuzzer': - return (self.fuzzer_sources, self.fuzzer_output_dir) + return (self.fuzzer_sources, self.fuzzobj_dir) else: raise InternalError("Unknown src info type '%s'" % (typ)) @@ -426,7 +429,7 @@ def process_command_line(args): # pylint: disable=too-many-locals build_group.add_option('--build-fuzzers=', dest='build_fuzzers', metavar='TYPE', default=None, - help='Build fuzzers (afl, libfuzzer, test)') + help='Build fuzzers (afl, libfuzzer, klee, test)') build_group.add_option('--with-fuzzer-lib=', metavar='LIB', default=None, dest='fuzzer_lib', help='additionally link in LIB') @@ -1727,15 +1730,18 @@ class MakefileListsGenerator(object): return set() + def _fuzzer_bin_list(self, fuzzer_objs, bin_dir): + for obj in fuzzer_objs: + (directory, name) = os.path.split(os.path.normpath(obj)) + name = name.replace('.' + self._osinfo.obj_suffix, '') + yield os.path.join(bin_dir, name) + def _objectfile_list(self, sources, obj_dir): + obj_suffix = '.' + self._osinfo.obj_suffix + for src in sources: (directory, filename) = os.path.split(os.path.normpath(src)) - - obj_suffix = '.' + self._osinfo.obj_suffix - parts = directory.split(os.sep) - if 'fuzzer' in parts: - obj_suffix = '' if 'src' in parts: parts = parts[parts.index('src')+2:] @@ -1766,10 +1772,9 @@ class MakefileListsGenerator(object): name = filename name = name.replace('.cpp', obj_suffix) - yield os.path.join(obj_dir, name) - def _build_commands(self, sources, obj_dir, flags): + def _build_commands(self, sources, obj_dir, objects, flags): """ Form snippets of makefile for building each source file """ @@ -1782,33 +1787,38 @@ class MakefileListsGenerator(object): is_fuzzer = obj_dir.find('fuzzer') != -1 - if is_fuzzer: - for (obj_file, src) in zip(self._objectfile_list(sources, obj_dir), sources): + for (obj_file, src) in zip(self._objectfile_list(sources, obj_dir), sources): + isa_specific_flags_str = "".join([" %s" % flagset for flagset in sorted(self._isa_specific_flags(src))]) - yield '%s: %s $(LIBRARIES)\n\t$(CXX) %s $(%s_FLAGS) %s -L. -lbotan-2 $(FUZZER_LINKS_TO) %s$@\n' % ( - obj_file, src, includes, flags, src, self._cc.output_to_option) - else: - for (obj_file, src) in zip(self._objectfile_list(sources, obj_dir), sources): - isa_specific_flags_str = "".join([" %s" % flagset for flagset in sorted(self._isa_specific_flags(src))]) + yield '%s: %s\n\t$(CXX)%s $(%s_FLAGS) %s %s %s %s$@\n' % ( + obj_file, src, isa_specific_flags_str, flags, + includes, self._cc.compile_flags, src, self._cc.output_to_option) - yield '%s: %s\n\t$(CXX)%s $(%s_FLAGS) %s %s %s %s$@\n' % ( - obj_file, src, isa_specific_flags_str, flags, - includes, self._cc.compile_flags, src, self._cc.output_to_option) + if is_fuzzer: + fuzz_basename = os.path.basename(obj_file).replace('.' + self._osinfo.obj_suffix, '') + fuzz_bin = self._build_paths.fuzzer_output_dir + yield '%s: %s $(LIBRARIES)\n\t$(FUZZER_LINK_CMD) %s $(FUZZER_LINKS_TO) %s$@\n' % ( + os.path.join(fuzz_bin, fuzz_basename), obj_file, obj_file, self._cc.output_to_option) def generate(self): out = {} - targets = ['lib', 'cli', 'test'] - if self._options.build_fuzzers: - targets += ['fuzzer'] + targets = ['lib', 'cli', 'test'] + \ + (['fuzzer'] if self._options.build_fuzzers else []) for t in targets: - obj_key = '%s_objs' % (t) src_list, src_dir = self._build_paths.src_info(t) src_list.sort() - out[obj_key] = makefile_list(self._objectfile_list(src_list, src_dir)) + objects = list(self._objectfile_list(src_list, src_dir)) + + obj_key = '%s_objs' % (t) + out[obj_key] = makefile_list(objects) + + if t == 'fuzzer': + out['fuzzer_bin'] = makefile_list(self._fuzzer_bin_list(objects, self._build_paths.fuzzer_output_dir)) + build_key = '%s_build_cmds' % (t) - out[build_key] = '\n'.join(self._build_commands(src_list, src_dir, t.upper())) + out[build_key] = '\n'.join(self._build_commands(src_list, src_dir, objects, t.upper())) return out @@ -1897,6 +1907,8 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch, main_executable = os.path.basename(sys.argv[0]) return ' '.join([main_executable] + sys.argv[1:]) + bin_link_cmd = cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd() + variables = { 'version_major': Version.major, 'version_minor': Version.minor, @@ -1938,7 +1950,9 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch, 'libobj_dir': build_config.libobj_dir, 'cliobj_dir': build_config.cliobj_dir, 'testobj_dir': build_config.testobj_dir, - 'fuzzobj_dir': build_config.fuzzer_output_dir if build_config.fuzzer_output_dir else '', + 'fuzzobj_dir': build_config.fuzzobj_dir, + + 'fuzzer_output_dir': build_config.fuzzer_output_dir if build_config.fuzzer_output_dir else '', 'doc_output_dir': build_config.doc_output_dir, @@ -1966,9 +1980,9 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch, 'visibility_attribute': cc.gen_visibility_attribute(options), 'lib_link_cmd': cc.so_link_command_for(osinfo.basename, options) + external_link_cmd(), - 'cli_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd(), - 'test_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd(), - 'fuzzer_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd(), + 'cli_link_cmd': bin_link_cmd, + 'test_link_cmd': bin_link_cmd, + 'fuzzer_link_cmd': bin_link_cmd, 'link_to': ' '.join( [cc.add_lib_option + lib for lib in link_to('libs')] + @@ -3058,12 +3072,15 @@ def main(argv): source_paths = SourcePaths(os.path.dirname(argv[0])) if options.build_fuzzers != None: - if options.build_fuzzers not in ['libfuzzer', 'afl', 'test']: + if options.build_fuzzers not in ['libfuzzer', 'afl', 'klee', 'test']: raise UserError('Bad value to --build-fuzzers') if options.build_fuzzers == 'libfuzzer' and options.fuzzer_lib is None: options.fuzzer_lib = 'Fuzzer' + if options.build_fuzzers == 'klee' and options.os != 'llvm': + raise UserError('Building for KLEE requires targetting LLVM') + info_modules = load_info_files(source_paths.lib_dir, 'Modules', "info.txt", ModuleInfo) info_arch = load_build_data_info_files(source_paths, 'CPU info', 'arch', ArchInfo) info_os = load_build_data_info_files(source_paths, 'OS info', 'os', OsInfo) |