def clang( bc_path, cpp_path, include_flags=None, define_flags=None, machine_flags=None, colors=True, ): cmd = [settings.clang()] cmd += clang_emit_llvm_flags() cmd += clang_ikos_flags() cmd += [cpp_path, '-o', bc_path] # For #include <ikos/analyzer/intrinsic.hpp> cmd += ['-isystem', settings.INCLUDE_DIR] if include_flags: cmd += ['-I%s' % i for i in include_flags] if define_flags: cmd += ['-D%s' % d for d in define_flags] if machine_flags: cmd += ['-m%s' % m for m in machine_flags] if colors: cmd.append('-fcolor-diagnostics') else: cmd.append('-fno-color-diagnostics') if cpp_path.endswith('.cpp'): cmd.append('-std=c++17') # available because clang >= 7.0 log.info('Compiling %s' % cpp_path) log.debug('Running %s' % command_string(cmd)) subprocess.check_call(cmd)
def compiler(mode): ''' Return the full path to the compiler for the given mode ''' if mode == 'cc': return settings.clang() elif mode == 'c++': return settings.clangxx() else: assert False, 'unexpected mode'
def build_bitcode(mode, parser, src_path, bc_path): ''' Compile the given source file to llvm bitcode ''' cmd = [mode] cmd += analyzer.clang_emit_llvm_flags() cmd += parser.compile_args cmd += analyzer.clang_ikos_flags() cmd += [src_path, '-o', bc_path] run(cmd, executable=settings.clang())
def clang(bc_path, cpp_path, colors=True): cmd = [ settings.clang(), '-emit-llvm', '-c', '-g', '-D_FORTIFY_SOURCE=0', '-Wall', cpp_path, '-o', bc_path ] if colors: cmd.append('-fcolor-diagnostics') else: cmd.append('-fno-color-diagnostics') if cpp_path.endswith('.cpp'): cmd.append('-std=c++14') # available because clang >= 4.0 subprocess.check_call(cmd)
def clang(bc_path, cpp_path, colors=True): cmd = [settings.clang(), '-c', '-emit-llvm', '-g', '-D_FORTIFY_SOURCE=0', '-Wall', cpp_path, '-o', bc_path] # For #include <ikos/analyzer/intrinsic.hpp> cmd += ['-isystem', settings.INCLUDE_DIR] if colors: cmd.append('-fcolor-diagnostics') else: cmd.append('-fno-color-diagnostics') if cpp_path.endswith('.cpp'): cmd.append('-std=c++14') # available because clang >= 4.0 log.info('Compiling %s' % cpp_path) log.debug('Running %s' % command_string(cmd)) subprocess.check_call(cmd)
def main(argv): progname = os.path.basename(argv[0]) start_date = datetime.datetime.now() # parse arguments opt = parse_arguments(argv[1:]) # setup colors and logging colors.setup(opt.color, file=log.out) log.setup(opt.log_level) if is_apron_domain(opt.domain) and not settings.HAS_APRON: printf( '%s: error: cannot use apron abstract domains.\n' 'ikos was compiled without apron support, ' 'see analyzer/README.md\n', progname, file=sys.stderr) sys.exit(1) # create working directory wd = create_working_directory(opt.temp_dir, opt.save_temps) input_path = opt.file # compile c/c++ code if path_ext(input_path) in c_extensions + cpp_extensions: bc_path = namer(opt.file, '.bc', wd) try: with stats.timer('clang'): clang(bc_path, input_path, opt.compiler_include_flags, opt.compiler_define_flags, opt.compiler_warning_flags, opt.compiler_disable_warnings, opt.compiler_machine_flags, colors.ENABLE) except subprocess.CalledProcessError as e: printf('%s: error while compiling %s, abort.\n', progname, input_path, file=sys.stderr) sys.exit(e.returncode) input_path = bc_path if path_ext(input_path) not in llvm_extensions: printf('%s: error: unexpected file extension.\n', progname, file=sys.stderr) sys.exit(1) # ikos-pp: preprocess llvm bitcode pp_path = namer(opt.file, '.pp.bc', wd) try: with stats.timer('ikos-pp'): ikos_pp(pp_path, input_path, opt.entry_points, opt.opt_level, opt.inline_all, not opt.no_bc_verify) except subprocess.CalledProcessError as e: printf('%s: error while preprocessing llvm bitcode, abort.\n', progname, file=sys.stderr) sys.exit(e.returncode) # display the llvm bitcode, if requested if opt.display_llvm: display_llvm(pp_path) # ikos-analyzer: analyze llvm bitcode try: with stats.timer('ikos-analyzer'): ikos_analyzer(opt.output_db, pp_path, opt) except AnalyzerError as e: printf('%s: error: %s\n', progname, e, file=sys.stderr) sys.exit(e.returncode) # open output database db = OutputDatabase(path=opt.output_db) # insert timing results in the database db.insert_timing_results(stats.rows()) # insert settings in the database settings_rows = [ ('version', settings.VERSION), ('start-date', start_date.isoformat(' ')), ('end-date', datetime.datetime.now().isoformat(' ')), ('working-directory', wd), ('input', opt.file), ('bc-file', input_path), ('pp-bc-file', pp_path), ('clang', settings.clang()), ('ikos-pp', settings.ikos_pp()), ('opt-level', opt.opt_level), ('inline-all', json.dumps(opt.inline_all)), ('use-libc-intrinsics', json.dumps(not opt.no_libc)), ('use-libcpp-intrinsics', json.dumps(not opt.no_libcpp)), ('use-libikos-intrinsics', json.dumps(not opt.no_libikos)), ('use-simplify-cfg', json.dumps(not opt.no_simplify_cfg)), ('use-simplify-upcast-comparison', json.dumps(not opt.no_simplify_upcast_comparison)), ] if opt.cpu: settings_rows.append(('cpu-limit', opt.cpu)) if opt.mem: settings_rows.append(('mem-limit', opt.mem)) db.insert_settings(settings_rows) first = (log.LEVEL >= log.ERROR) # display timing results if opt.display_times != 'no': if not first: printf('\n') report.print_timing_results(db, opt.display_times == 'full') first = False # display summary if opt.display_summary != 'no': if not first: printf('\n') report.print_summary(db, opt.display_summary == 'full') first = False # display raw checks if opt.display_raw_checks: if not first: printf('\n') report.print_raw_checks(db, opt.procedural == 'inter') first = False # start ikos-view if opt.format == 'web': ikos_view(opt, db) return # report if opt.format != 'no': if not first and opt.report_file is sys.stdout: printf('\n' + colors.bold('# Results') + '\n') first = False # setup colors again (in case opt.color = 'auto') colors.setup(opt.color, file=opt.report_file) # generate report rep = report.generate_report(db, status_filter=opt.status_filter, analyses_filter=None) # format report formatter_class = report.formats[opt.format] formatter = formatter_class(opt.report_file, opt.report_verbosity) formatter.format(rep) # close database db.close() if opt.remove_db: os.remove(opt.output_db)
def compile(mode, argv): assert mode in ('clang', 'clang++') progname = os.path.basename(argv[0]) if 'IKOS_SCAN_SERVER' not in os.environ: printf('error: %s: missing environment variable IKOS_SCAN_SERVER.\n', progname, file=sys.stderr) sys.exit(1) # setup colors and logging colors.setup(os.environ.get('IKOS_SCAN_COLOR', args.default_color), file=log.out) log.setup(os.environ.get('IKOS_SCAN_LOG_LEVEL', args.default_log_level)) # first step, run the actual command run([mode] + argv[1:], executable=settings.clang()) # second step, parse the command line and compile to llvm bitcode parser = ClangArgumentParser(argv[1:]) if parser.skip_bitcode_gen(): return try: if (len(parser.source_files) == 1 and len(parser.object_files) == 0 and not parser.is_link): # in this case, just compile to llvm bitcode and attach the llvm # bitcode path to the output object file src_path = parser.source_files[0] obj_path = parser.output_file bc_path = '%s.bc' % obj_path build_bitcode(mode, parser, src_path, bc_path) attach_bitcode_path(obj_path, bc_path) return # compile the source files one by one and attach the llvm bitcode path new_object_files = [] for src_path in parser.source_files: # build the object file obj_path = '%s.o' % src_path build_object(mode, parser, src_path, obj_path) new_object_files.append(obj_path) # build the bitcode file if src_path.endswith('.bc'): bc_path = src_path else: bc_path = '%s.bc' % obj_path build_bitcode(mode, parser, src_path, bc_path) # attach the bitcode path to the object file, ready to be linked attach_bitcode_path(obj_path, bc_path) # re-link to merge the llvm bitcode paths section if new_object_files: if parser.is_link: link_objects(mode, parser, new_object_files + parser.object_files, parser.output_file) else: log.warning('New object files but nothing to link') if parser.is_link and u'executable' in filetype(parser.output_file): bc_path = '%s.bc' % parser.output_file extract_bitcode(parser.output_file, bc_path) notify_binary_built(parser.output_file, bc_path) except IOError as error: # ./configure sometimes removes the file while we are still running if error.filename == parser.output_file: pass else: raise error
def link_objects(mode, parser, input_paths, output_path): cmd = [mode] cmd += input_paths cmd += parser.link_args cmd += ['-o', output_path] run(cmd, executable=settings.clang())
def build_object(mode, parser, src_path, obj_path): ''' Compile the given source file to an object file ''' cmd = [mode, '-c'] cmd += parser.compile_args cmd += [src_path, '-o', obj_path] run(cmd, executable=settings.clang())
def main(argv): progname = os.path.basename(argv[0]) start_date = datetime.datetime.now() # disable unix signals forwarding os.setpgrp() # parse arguments opt = parse_opt(argv[1:]) # setup colors colors.setup(opt.colors) try: # create working directory wd = create_work_dir(opt.temp_dir, opt.save_temps) input_path = opt.file # compile c/c++ code if path_ext(input_path) in ('.c', '.cpp'): bc_path = namer(opt.file, '.bc', wd) try: with stats.timer('clang'): clang(bc_path, input_path, colors.ENABLE) except subprocess.CalledProcessError as e: printf('%s: error while compiling %s, abort.\n', progname, input_path, file=sys.stderr) sys.exit(e.returncode) input_path = bc_path if path_ext(input_path) != '.bc': printf('%s: error: unexpected file extension.\n', progname, file=sys.stderr) sys.exit(1) # preprocess bitcode pp_path = namer(opt.file, '.pp.bc', wd) try: with stats.timer('ikos-pp'): ikos_pp(pp_path, input_path, opt.entry_points, opt.ikos_pp, opt.inline, opt.verify) except subprocess.CalledProcessError as e: printf('%s: error while preprocessing llvm bitcode, abort.\n', progname, file=sys.stderr) sys.exit(e.returncode) # translate bitcode to arbos ar ar_path = namer(opt.file, '.ar', wd) try: with stats.timer('llvm-to-ar'): llvm_to_ar(ar_path, pp_path, opt.gv_zero_initializers) except subprocess.CalledProcessError as e: printf('%s: error while running llvm-to-ar, abort.\n', progname, file=sys.stderr) sys.exit(e.returncode) # arbos (libanalyzer) try: with stats.timer('arbos'): passes = arbos(ar_path, opt.output_db, opt.analyses, opt.entry_points, opt.entry_points_init_gv, opt.arbos_optimize, opt.arbos_optimize_cfg, opt.dot_cfg, settings.ABSTRACT_DOMAIN.startswith('GAUGE'), not opt.intraprocedural, opt.precision_level, not opt.no_liveness, not opt.no_pointer, opt.gv_init, opt.use_summaries, opt.use_pointer_summaries, opt.display_invariants, opt.display_checks, opt.mem, opt.cpu, opt.print_command) except ArbosError as e: printf('%s: error: %s\n', progname, e, file=sys.stderr) sys.exit(e.returncode) if opt.print_command: return # open output database db = sqlite3.connect(opt.output_db) # insert timing results in the database stats.save_database(db) # insert settings in the database settings_rows = [ ('version', settings.VERSION), ('start-date', start_date.isoformat(' ')), ('end-date', datetime.datetime.now().isoformat(' ')), ('entry-points-init-gv', json.dumps(opt.entry_points_init_gv)), ('working-directory', wd), ('input', opt.file), ('bc-file', input_path), ('pp-bc-file', pp_path), ('ar-file', ar_path), ('clang', settings.clang()), ('opt', settings.opt()), ('arbos', settings.arbos()), ('llvm-to-ar', settings.llvm_to_ar()), ('ikos-pp', settings.ikos_pp()), ('ikos-pp-level', 'full' if opt.ikos_pp else 'simple'), ('ikos-pp-inline-all', json.dumps(opt.inline)), ('global-variables-init', json.dumps(opt.gv_init)), ('arbos-passes', json.dumps(passes)), ] if opt.cpu > 0: settings_rows.append(('cpu-limit', opt.cpu)) if opt.mem > 0: settings_rows.append(('mem-limit', opt.mem)) save_settings(db, settings_rows) # display timing results if opt.display_timing_results != 'off': printf('\n') render.print_timing_results(db, opt.display_timing_results == 'full') # display summary if opt.display_summary != 'off': printf('\n') render.print_summary(db, opt.display_summary == 'full') # display raw checks if opt.show_raw_checks: printf('\n') render.print_raw_checks(db, not opt.intraprocedural) # export if opt.export: if opt.export_file is sys.stdout: printf('\n') printf(colors.bold('# Results') + '\n') # setup colors again (in case opt.colors = 'auto') colors.setup(opt.colors, file=opt.export_file) # export format formatter_class = render.formats[opt.export_format] formatter = formatter_class(opt.export_file, opt.export_verbosity, opt.export_demangle) render.export(db, formatter, opt.export_level, not opt.export_no_unreachable) # close database db.close() # ikos view if opt.ikosview: ikos_view(opt.output_db, not opt.intraprocedural) if opt.remove_db: os.remove(opt.output_db) except KeyboardInterrupt: pass