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)
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)
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)
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
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
def _warning_link_unary(self, flag): log.warning("Flag '%s' cannot be used with ikos-scan, ignored." % flag)
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()