Пример #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)
Пример #2
0
Файл: scan.py Проект: plkms/ikos
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)
Пример #3
0
def check_output(cmd):
    ''' Run the given command and return the standard output, in bytes '''
    log.debug('Running %s' % command_string(cmd))

    try:
        return subprocess.check_output(cmd)
    except OSError as e:
        printf('error: %s: %s\n', cmd[0], e.strerror, file=sys.stderr)
        sys.exit(e.errno)
Пример #4
0
    def _shift(self, nargs):
        if len(self.args) < nargs:
            printf('error: unexpected command line argument\n',
                   file=sys.stderr)
            sys.exit(1)

        ret = []
        for _ in range(nargs):
            ret.append(self.args.popleft())

        return ret
Пример #5
0
def filetype(path):
    ''' Return the file type as returned by the 'file' command '''
    try:
        output = subprocess.check_output(['file', '--brief', path])
    except OSError as e:
        printf('error: file: %s', e.strerror, file=sys.stderr)
        sys.exit(e.errno)

    if output.startswith(b'cannot open '):
        open(path)  # raise IOError

    return output.decode('utf-8').strip()
Пример #6
0
def run(cmd):
    ''' Run the given command and return the exit code '''
    log.debug('Running %s' % command_string(cmd))

    try:
        proc = subprocess.Popen(cmd)
        rc = proc.wait()
    except OSError as e:
        printf('error: %s: %s\n', cmd[0], e.strerror, file=sys.stderr)
        sys.exit(e.errno)

    if rc != 0:
        sys.exit(rc)

    return rc
Пример #7
0
def create_working_directory(wd=None, save=False):
    ''' Create a temporary working directory '''
    if not wd:
        wd = tempfile.mkdtemp(prefix='ikos-')

    if not os.path.exists(wd):
        try:
            os.makedirs(wd)
        except OSError as e:
            printf('error: %s: %s\n', wd, e.strerror, file=sys.stderr)
            sys.exit(1)

    if not os.path.isdir(wd):
        printf('error: %s: Not a directory\n', wd, file=sys.stderr)
        sys.exit(1)

    if not save:
        atexit.register(shutil.rmtree, path=wd)
    else:
        log.info('Temporary files will be kept in directory: %s' % wd)

    return wd
Пример #8
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)
Пример #9
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
Пример #10
0
 def _warning_link_unary(self, flag):
     printf('warning: flag "%s" cannot be used with ikos-scan, ignored.\n',
            flag,
            file=sys.stderr)