def test_DotControlFlowGraphsFromBytecode_simple_c_program(): """Test that simple C program produces two Dot CFGs.""" dot_cfgs = list( opt_util.DotControlFlowGraphsFromBytecode(SIMPLE_C_BYTECODE)) assert len(dot_cfgs) == 2 assert "CFG for 'DoSomething' function" in "\n".join(dot_cfgs) assert "CFG for 'main' function" in "\n".join(dot_cfgs)
def _DotControlFlowGraphsFromBytecodeToQueue( bytecode: str, queue: multiprocessing.Queue) -> None: """Process a bytecode and submit the dot source or the exception.""" try: queue.put(list(opt_util.DotControlFlowGraphsFromBytecode(bytecode))) except Exception as e: queue.put(DotControlFlowGraphsFromBytecodeError(bytecode, e))
def _ExtractGraphBatchOrDie( src_file_paths: typing.List[pathlib.Path], headers_dir: pathlib.Path ) -> typing.List[typing.Tuple[pathlib.Path, llvm_util.LlvmControlFlowGraph]]: """Process a patch of OpenCL sources to graphs. Args: src_file_paths: A list of source code paths. headers_dir: The directory containing header files. Returns: A list of <path,cfg> tuples. """ batch = [] for src_file_path in src_file_paths: app.Log(1, "Compiling %s", src_file_path.name) bytecode = ncc.ExtractLlvmByteCodeOrDie(src_file_path, headers_dir) dot_strings = list(opt_util.DotControlFlowGraphsFromBytecode(bytecode)) cfgs = [llvm_util.ControlFlowGraphFromDotSource(dot) for dot in dot_strings] if len(cfgs) != 1: app.Fatal( "Found %d CFGs in %s: %s", len(dot_strings), src_file_path.name, [c.graph["name"] for c in cfgs], ) ffg = cfgs[0].BuildFullFlowGraph() # Set the input bytecode as a graph property. ffg.graph["llvm_bytecode"] = bytecode batch.append((src_file_path, ffg)) return batch
def TryToCreateControlFlowGraphsFromLinuxSrc( path: pathlib.Path, ) -> typing.List[cfg.ControlFlowGraph]: """Try to create CFGs from a Linux C source file. On failure, an empty list is returned. Args: path: The path of the source file. Returns: A list of ControlFlowGraph instances. Raises: ClangException: If compiling to bytecode fails. """ graphs = [] try: bytecode, _ = BytecodeFromLinuxSrc(path, "-O0") except clang.ClangException: return graphs # Extract a dot sources from the bytecode. dot_generator = opt_util.DotControlFlowGraphsFromBytecode(bytecode) while True: try: dot = next(dot_generator) # Instantiate a CFG from the dot source. graph = llvm_util.ControlFlowGraphFromDotSource(dot) graph.ValidateControlFlowGraph(strict=False) graphs.append(graph) except ( UnicodeDecodeError, cfg.MalformedControlFlowGraphError, ValueError, opt.OptException, pyparsing.ParseException, ): pass except StopIteration: break return graphs
def CreateControlFlowGraphFromOpenClKernel( kernel_name: str, opencl_kernel: str) -> typing.Optional[cfg.ControlFlowGraph]: """Try to create a CFG proto from an opencl kernel. Args: kernel_name: The name of the OpenCL kernel defined in opencl_kernel. opencl_kernel: A string of OpenCL. This should contain a single kernel definition. Returns: A ControlFlowGraph instance, or None if compilation to bytecode fails. Raises: ClangException: If compiling to bytecode fails. ValueError: If opencl_kernel contains multiple functions. """ bytecode, _ = BytecodeFromOpenClString(opencl_kernel, "-O0") # Extract a single dot source from the bytecode. dot_generator = opt_util.DotControlFlowGraphsFromBytecode(bytecode) dot = next(dot_generator) try: next(dot_generator) raise ValueError("Bytecode produced more than one dot source!") except StopIteration: pass # Instantiate a CFG from the dot source. graph = llvm_util.ControlFlowGraphFromDotSource(dot) # Set the name of the graph to the kernel name. This is because the src code # has been preprocessed, so that each kernel is named 'A'. graph.graph["name"] = kernel_name return graph
Returns: A list of ControlFlowGraph instances. Raises: ClangException: If compiling to bytecode fails. """ graphs = [] try: bytecode, _ = BytecodeFromLinuxSrc(path, "-O0") except clang.ClangException: return graphs # Extract a dot sources from the bytecode. dot_generator = opt_util.DotControlFlowGraphsFromBytecode(bytecode) while True: try: dot = next(dot_generator) # Instantiate a CFG from the dot source. graph = llvm_util.ControlFlowGraphFromDotSource(dot) graph.ValidateControlFlowGraph(strict=False) graphs.append(graph) except ( UnicodeDecodeError, cfg.MalformedControlFlowGraphError, ValueError, opt.OptException, pyparsing.ParseException, ): pass
def test_DotControlFlowGraphsFromBytecode_invalid_bytecode(): """Test that exception is raised if bytecode is invalid.""" with test.Raises(opt.OptException) as e_ctx: next(opt_util.DotControlFlowGraphsFromBytecode("invalid bytecode!")) assert e_ctx.value.returncode assert e_ctx.value.stderr