def BytecodeFromOpenClString(opencl_string: str, optimization_level: str) -> str: """Create bytecode from OpenCL source string. Args: opencl_string: A string of OpenCL code. optimization_level: The optimization level to use, one of {-O0,-O1,-O2,-O3,-Ofast,-Os,-Oz}. Returns: A tuple of the arguments to clang, and the bytecode as a string. Raises: ClangException: If compiling to bytecode fails. """ # Use -O3 to reduce CFGs. clang_args = opencl.GetClangArgs(use_shim=False) + [ clang.ValidateOptimizationLevel(optimization_level), "-S", "-emit-llvm", "-o", "-", "-i", "-", "-Wno-everything", # No warnings please. ] process = clang.Exec(clang_args, stdin=opencl_string) if process.returncode: raise clang.ClangException( "clang failed", returncode=process.returncode, stderr=process.stderr, command=clang_args, ) return process.stdout, clang_args
def ExtractLlvmByteCodeOrDie(src_file_path: pathlib.Path, datafolder: pathlib.Path): """Read and compile to bytecode or die.""" # Read the source file and strip any non-ascii characters. with open(src_file_path, "rb") as f: src = f.read().decode("unicode_escape") src = src.encode("ascii", "ignore").decode("ascii") # Compile src to bytecode. clang_args = opencl.GetClangArgs(use_shim=True) + [ "-O0", "-S", "-emit-llvm", "-o", "-", "-i", "-", # No warnings, and fail immediately on error. "-Wno-everything", "-ferror-limit=1", # Kernels have headers. "-I", str(datafolder / "kernels_cl"), # We don't need the full shim header, just the common constants: "-DCLGEN_OPENCL_SHIM_NO_COMMON_TYPES", "-DCLGEN_OPENCL_SHIM_NO_UNSUPPORTED_STORAGE_CLASSES_AND_QUALIFIERS", ] process = clang.Exec(clang_args, stdin=src, log=False) if process.returncode: app.Error("Failed to compile %s", src_file_path) app.Error("stderr: %s", process.stderr) app.Fatal(f"clang failed with returncode {process.returncode}") return process.stdout
def generate_IR_mutants( src: str, incl: str, timeout_seconds: int = 45 ) -> typing.Set[typing.Tuple[pathlib.Path, str]]: """ Collect all mutants from src and return them """ if incl: with open(SRCIROR_BASE / "incl.h", 'w') as f: f.write(incl) f.flush() with open(SRCIROR_BASE / "test.c", 'w') as f: try: f.write(src) f.flush() except UnicodeDecodeError: return [] except UnicodeEncodeError: return [] # Construct and execute mutec command srciror_cmd = ([ "timeout", "-s9", str(timeout_seconds), "bash", SRCIROR_IR ] + opencl.GetClangArgs( use_shim=False, use_aux_headers=False, extra_args=[ "-include{}".format(pathlib.Path(CLSMITH_INCLUDE) / "CLSmith.h") ] if incl else [""]) + ["-include/tmp/mutec_src_temp_header.h" if incl else ""]) process = subprocess.Popen( srciror_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) try: stdout, stderr = process.communicate() except TimeoutError: pass os.remove(str(SRCIROR_BASE / "test.c")) os.remove(str(SRCIROR_BASE / "incl.h")) srciror_ir_paths = glob.glob(str(SRCIROR_BASE / "test-*.ll")) mutants = set() for path in srciror_ir_paths[:PER_INPUT_HARD_LIMIT]: try: mutants.add((opencl.HumanReadableBytecode(path), incl)) except ValueError: continue return mutants
def BytecodeFromOpenClString(opencl_string: str) -> str: """Create bytecode from OpenCL source string. Args: opencl_string: A string of OpenCL code. Returns: The bytecode as a string. Raises: ClangException: If compiling to bytecode fails. """ # Use -O3 to reduce CFGs. clang_args = opencl.GetClangArgs( use_shim=False) + ['-O3', '-S', '-emit-llvm', '-o', '-', '-i', '-'] process = clang.Exec(clang_args, stdin=opencl_string) if process.returncode: raise clang.ClangException("clang failed with returncode " f"{process.returncode}:\n{process.stderr}") return process.stdout
def test_GetClangArgs_with_shim(): args = opencl.GetClangArgs(use_shim=True) assert str(SHIMFILE) in args
def test_GetClangArgs_no_shim(): args = opencl.GetClangArgs(use_shim=False) assert str(SHIMFILE) not in args
from labm8.py import humanize from labm8.py import lockfile from labm8.py import sqlutil FLAGS = app.FLAGS # A dictionary mapping language name to a list of language-specific arguments # to pass to clang. LANGUAGE_TO_CLANG_ARGS = { "c": [ "-xc", "-O0", "-ferror-limit=1", "-Wno-everything", # No warnings please. ], "opencl": opencl.GetClangArgs(use_shim=True), # These languages are handled separately without using clang, but they still # need entries in this table: "swift": [], "haskell": [], } app.DEFINE_string("db", None, "Path of database to populate.") app.DEFINE_string("cf", None, "Path of contentfiles database.") app.DEFINE_string( "lang", None, "Name of the language to process. One of: " f"{set(LANGUAGE_TO_CLANG_ARGS.keys())}.", ) app.DEFINE_integer("batch_size", 32, "The size of batches to process.")
def generate_mutants( src: str, incl: str, timeout_seconds: int = 45) -> typing.Set[typing.Tuple[str, str]]: """ Collect all mutants from src and return them """ try: tdir = pathlib.Path(FLAGS.local_filesystem).resolve() except Exception: tdir = None with tempfile.NamedTemporaryFile("w", prefix="mutec_src", suffix='.cl', dir=tdir) as f: try: f.write(src) f.flush() except UnicodeDecodeError: return [] except UnicodeEncodeError: return [] if incl: with open("/tmp/mutec_src_temp_header.h", 'w') as f: f.write(incl) f.flush() # Fix compile_commands.json for source file. base_path = pathlib.Path(f.name).resolve().parent compile_command = { 'directory': str(base_path), 'arguments': [str(clang.CLANG), f.name] + ["-S", "-emit-llvm", "-o", "-"] + opencl.GetClangArgs( use_shim=False, use_aux_headers=False, extra_args=[ "-include{}".format( pathlib.Path(CLSMITH_INCLUDE) / "CLSmith.h") ] if incl else [""]) + ["-include/tmp/mutec_src_temp_header.h" if incl else ""], 'file': str(f.name) } with open(base_path / "compile_commands.json", 'w') as ccf: json.dump([compile_command], ccf) # Construct and execute mutec command mutec_cmd = [ "timeout", "-s9", str(timeout_seconds), MUTEC, str(f.name), "-o", str(base_path) ] process = subprocess.Popen( mutec_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) try: stdout, stderr = process.communicate() except TimeoutError: pass os.remove(str(base_path / "compile_commands.json")) mutec_paths = glob.glob("{}.mutec*".format(f.name)) templates = glob.glob("{}.code_template".format(f.name)) mutants = set([(open(x, 'r').read(), incl) for x in mutec_paths[:PER_INPUT_HARD_LIMIT]]) for m in mutec_paths: os.remove(m) for m in templates: os.remove(m) os.remove("/tmp/mutec_src_temp_header.h") return mutants