Beispiel #1
0
def attach_bitcode_path(obj_path, bc_path):
    ''' Attach the bitcode full path to the given object file '''
    ext = os.path.splitext(obj_path)[1]

    if ext not in ('.o', '.lo', '.os', '.So', '.po'):
        return  # unexpected file format

    if not os.path.exists(obj_path):
        log.warning(
            "Cannot attach bitcode path to missing file '%s'" % obj_path
        )
        return

    abs_bc_path = os.path.abspath(bc_path)

    # write the absolute path to the bitcode file in a temporary file
    f = tempfile.NamedTemporaryFile(mode='w+b',
                                    suffix='.llvm_bc',
                                    delete=False)
    f.write(abs_bc_path.encode('utf-8'))
    f.write(b'\n')
    f.flush()
    os.fsync(f.fileno())
    f.close()

    # add a section in the object file
    if sys.platform.startswith('darwin'):
        # TODO(marthaud): use llvm-objcopy when they start supporting Mach-O
        cmd = ['ld',
               '-r',
               '-keep_private_externs',
               obj_path,
               '-sectcreate',
               DARWIN_SEGMENT_NAME,
               DARWIN_SECTION_NAME, f.name,
               '-o',
               obj_path]
        run(cmd)
    elif sys.platform.startswith('linux') or sys.platform.startswith('freebsd'):
        cmd = [settings.llvm_objcopy(),
               '--add-section',
               '%s=%s' % (ELF_SECTION_NAME, f.name),
               obj_path]
        run(cmd)
    elif sys.platform.startswith('win'):
        # TODO(marthaud): use llvm-objcopy when they start supporting COFF/PE
        cmd = ['objcopy',
               '--add-section',
               '%s=%s' % (PE_SECTION_NAME, f.name),
               obj_path]
        run(cmd)
    else:
        assert False, 'unsupported platform'

    os.remove(f.name)
Beispiel #2
0
def ikos_pp(pp_path, bc_path, entry_points, opt_level, inline_all, verify):
    if opt_level == 'aggressive':
        log.warning('Using aggressive optimizations is not recommended')
        log.warning('The translation from LLVM bitcode to AR might fail')

    cmd = [settings.ikos_pp(),
           '-opt=%s' % opt_level,
           '-entry-points=%s' % ','.join(entry_points)]

    if inline_all:
        cmd.append('-inline-all')

    if not verify:
        cmd.append('-no-verify')

    cmd += [bc_path, '-o', pp_path]

    log.info('Running ikos preprocessor')
    log.debug('Running %s' % command_string(cmd))
    subprocess.check_call(cmd)
Beispiel #3
0
def ikos_analyzer(db_path, pp_path, opt):
    if settings.BUILD_MODE == 'Debug':
        log.warning('ikos was built in debug mode, the analysis might be slow')

    # Fix huge slow down when ikos-analyzer uses DROP TABLE on an existing db
    if os.path.isfile(db_path):
        os.remove(db_path)

    cmd = [settings.ikos_analyzer()]

    # analysis options
    cmd += [
        '-a=%s' % ','.join(opt.analyses),
        '-d=%s' % opt.domain,
        '-entry-points=%s' % ','.join(opt.entry_points),
        '-globals-init=%s' % opt.globals_init,
        '-proc=%s' % opt.procedural,
        '-j=%d' % opt.jobs,
        '-widening-strategy=%s' % opt.widening_strategy,
        '-widening-delay=%d' % opt.widening_delay,
        '-widening-period=%d' % opt.widening_period
    ]

    if opt.narrowing_strategy == 'auto':
        if opt.domain in domains_without_narrowing:
            cmd.append('-narrowing-strategy=meet')
        else:
            cmd.append('-narrowing-strategy=narrow')
    else:
        cmd.append('-narrowing-strategy=%s' % opt.narrowing_strategy)

    if opt.narrowing_iterations is not None:
        cmd.append('-narrowing-iterations=%d' % opt.narrowing_iterations)
    elif (opt.narrowing_strategy == 'auto'
          and opt.domain in domains_without_narrowing):
        cmd.append('-narrowing-iterations=%d' %
                   args.meet_iterations_if_no_narrowing)

    if opt.widening_delay_functions:
        cmd.append('-widening-delay-functions=%s' %
                   ','.join(opt.widening_delay_functions))

    if opt.no_init_globals:
        cmd.append('-no-init-globals=%s' % ','.join(opt.no_init_globals))
    if opt.no_liveness:
        cmd.append('-no-liveness')
    if opt.no_pointer:
        cmd.append('-no-pointer')
    if opt.no_widening_hints:
        cmd.append('-no-widening-hints')
    if opt.partitioning != 'no':
        cmd.append('-enable-partitioning-domain')
    if opt.no_fixpoint_cache:
        cmd.append('-no-fixpoint-cache')
    if opt.no_checks:
        cmd.append('-no-checks')
    if opt.hardware_addresses:
        cmd.append('-hardware-addresses=%s' % ','.join(opt.hardware_addresses))
    if opt.hardware_addresses_file:
        cmd.append('-hardware-addresses-file=%s' % opt.hardware_addresses_file)
    if opt.argc is not None:
        cmd.append('-argc=%d' % opt.argc)

    # import options
    cmd.append('-allow-dbg-mismatch')
    if opt.no_bc_verify:
        cmd.append('-no-verify')
    if opt.no_libc:
        cmd.append('-no-libc')
    if opt.no_libcpp:
        cmd.append('-no-libcpp')
    if opt.no_libikos:
        cmd.append('-no-libikos')

    # AR passes options
    if opt.no_type_check:
        cmd.append('-no-type-check')
    if opt.no_simplify_cfg:
        cmd.append('-no-simplify-cfg')
    if opt.no_simplify_upcast_comparison:
        cmd.append('-no-simplify-upcast-comparison')
    if 'gauge' in opt.domain:
        cmd.append('-add-loop-counters')
    if opt.partitioning == 'return':
        cmd.append('-add-partitioning-variables')

    # debug options
    cmd += [
        '-display-checks=%s' % opt.display_checks,
        '-display-inv=%s' % opt.display_inv
    ]

    if opt.display_ar:
        cmd.append('-display-ar')
    if opt.display_liveness:
        cmd.append('-display-liveness')
    if opt.display_function_pointer:
        cmd.append('-display-function-pointer')
    if opt.display_pointer:
        cmd.append('-display-pointer')
    if opt.display_fixpoint_parameters:
        cmd.append('-display-fixpoint-parameters')
    if opt.generate_dot:
        cmd += ['-generate-dot', '-generate-dot-dir', opt.generate_dot_dir]

    # add -name-values if necessary
    if (opt.display_checks in ('all', 'fail')
            or opt.display_inv in ('all', 'fail') or opt.display_liveness
            or opt.display_fixpoint_parameters or opt.display_function_pointer
            or opt.display_pointer or opt.display_raw_checks):
        cmd.append('-name-values')

    # misc. options
    if opt.color == 'yes':
        cmd.append('-color=1')
    elif opt.color == 'no':
        cmd.append('-color=0')

    cmd.append('-log=%s' % opt.log_level)
    cmd.append('-progress=%s' % opt.progress)

    # input/output
    cmd += [pp_path, '-o', db_path]

    # set resource limit, if requested
    if opt.mem:
        import resource  # fails on Windows

        def set_limits():
            mem_bytes = opt.mem * 1024 * 1024
            resource.setrlimit(resource.RLIMIT_AS, [mem_bytes, mem_bytes])
    else:
        set_limits = None

    # called after timeout
    def kill(p):
        try:
            log.error('Timeout')
            p.send_signal(signal.SIGALRM)
        except OSError:
            pass

    log.info('Running ikos analyzer')
    log.debug('Running %s' % command_string(cmd))
    p = subprocess.Popen(cmd, preexec_fn=set_limits)
    timer = threading.Timer(opt.cpu, kill, [p])

    if opt.cpu:
        timer.start()

    try:
        if sys.platform.startswith('win'):
            return_status = p.wait()
        else:
            _, return_status = os.waitpid(p.pid, 0)
    finally:
        # kill the timer if the process has terminated already
        if timer.isAlive():
            timer.cancel()

    # special case for Windows, since it does not define WIFEXITED & co.
    if sys.platform.startswith('win'):
        if return_status != 0:
            raise AnalyzerError('a run-time error occurred', cmd,
                                return_status)
        else:
            return

    # if it did not terminate properly, propagate this error code
    if os.WIFEXITED(return_status) and os.WEXITSTATUS(return_status) != 0:
        exit_status = os.WEXITSTATUS(return_status)
        raise AnalyzerError('a run-time error occurred', cmd, exit_status)

    if os.WIFSIGNALED(return_status):
        signum = os.WTERMSIG(return_status)
        raise AnalyzerError('exited with signal %s' % signal_name(signum), cmd,
                            signum)

    if os.WIFSTOPPED(return_status):
        signum = os.WSTOPSIG(return_status)
        raise AnalyzerError('exited with signal %d' % signal_name(signum), cmd,
                            signum)
Beispiel #4
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 #5
0
        pass

    def get_style_defs(self, cl):
        return ''

    def wrap(self, src, out):
        pass


def dummy_highlight(data, lexer, formatter):
    lines = ((1, html.escape(line)) for line in data.split('\n'))
    code = ''
    for _, line in formatter.wrap(lines, None):
        code += line
    return code


try:
    from pygments.lexers import CLexer, CppLexer
    from pygments.formatters import HtmlFormatter
    from pygments import highlight
except ImportError as e:
    log.warning("Syntax highlighting is not available:"
                " module `pygments` is not installed.")
    log.warning("Note: use `pip install --user pygments`"
                " to install `pygments`")
    CLexer = DummyLexer
    CppLexer = DummyLexer
    HtmlFormatter = DummyHtmlFormatter
    highlight = dummy_highlight
Beispiel #6
0
 def _warning_link_unary(self, flag):
     log.warning("Flag '%s' cannot be used with ikos-scan, ignored." % flag)
Beispiel #7
0
 def serve(self):
     log.info("Pre-processing...")
     self.report.pre_process()
     log.info("Starting ikos-view at http://localhost:%d" % self.port)
     log.warning("Use Ctrl-C to exit")
     self.httpd.serve_forever()