Beispiel #1
0
def main(argv):
    progname = os.path.basename(argv[0])

    # parse arguments
    opt = parse_arguments(argv[1:])

    # setup colors and logging
    colors.setup(opt.color, file=log.out)
    log.setup(opt.log_level)

    if not os.path.isfile(opt.file):
        printf("%s: error: no such file: \'%s\'\n",
               progname,
               opt.file,
               file=sys.stderr)
        sys.exit(1)

    try:
        # open result database
        db = OutputDatabase(opt.file)

        v = View(db, port=opt.port)
        browser_timer = threading.Timer(0.1, open_browser,
                                        ['http://localhost:%d/' % opt.port])
        browser_timer.start()
        v.serve()

        # close database
        db.close()
    except sqlite3.DatabaseError as e:
        printf('%s: error: %s\n', progname, e, file=sys.stderr)
        sys.exit(1)
Beispiel #2
0
def scan_main(argv):
    # parse arguments
    opt = scan_parse_arguments(argv[1:])

    # setup colors and logging
    colors.setup(opt.color, file=log.out)
    log.setup(opt.log_level)

    # scan server
    server = ScanServer()
    server.daemon = True
    server.start()

    # setup environment variables
    os.environ['IKOS_SCAN_COLOR'] = 'yes' if colors.ENABLE else 'no'
    os.environ['IKOS_SCAN_LOG_LEVEL'] = opt.log_level
    os.environ['IKOS_SCAN_SERVER'] = 'http://localhost:%d' % server.port
    os.environ['PATH'] += os.path.pathsep + settings.BIN_DIR
    os.environ['CC'] = 'ikos-scan-cc'
    os.environ['CXX'] = 'ikos-scan-c++'
    os.environ['LD'] = 'ikos-scan-cc'

    # add -e to make commands, to avoid makefiles overriding CC/CXX/LD
    if os.path.basename(opt.args[0]) in ('make', 'gmake'):
        opt.args.insert(1, '-e')

    # run the build command
    rc = run(opt.args)

    # stop the scan server
    server.cancel()
    server.join()

    # skip binaries that have been removed
    binaries = [binary for binary in server.binaries
                if os.path.exists(binary['exe_path'])]

    if not binaries:
        printf('Nothing to analyze.\n')

    # analyze each binary
    for binary in binaries:
        exe_path = os.path.relpath(binary['exe_path'])
        bc_path = os.path.relpath(binary['bc_path'])

        printf('Analyze %s? [Y/n] ', colors.bold(exe_path))
        answer = sys.stdin.readline().strip().lower()

        if answer in ('', 'y', 'yes'):
            cmd = ['ikos', bc_path, '-o', '%s.db' % exe_path]
            log.info('Running %s' % colors.bold(command_string(cmd)))

            cmd = [sys.executable,
                   settings.ikos(),
                   bc_path,
                   '-o',
                   '%s.db' % exe_path,
                   '--color=%s' % opt.color,
                   '--log=%s' % opt.log_level]
            run(cmd)
Beispiel #3
0
def extract_main(argv):
    # parse arguments
    opt = extract_parse_arguments(argv[1:])

    # setup colors and logging
    colors.setup(opt.color, file=log.out)
    log.setup(opt.log_level)

    input_path = opt.input
    output_path = opt.output if opt.output else '%s.bc' % input_path
    extract_bitcode(input_path, output_path)
Beispiel #4
0
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)
Beispiel #5
0
def compile(mode, argv):
    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([compiler(mode)] + argv[1:])

    # 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
Beispiel #6
0
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