Example #1
0
def test_ControlFlowGraphFromDotSource_is_valid():
    """Test that CFG is valid."""
    g = llvm_util.ControlFlowGraphFromDotSource(SIMPLE_C_DOT)
    # Control flow graphs are not guaranteed to be valid. That is, the may contain
    # fusible basic blocks. This can happen if the creating the graph from
    # unoptimized bytecode.
    assert g.ValidateControlFlowGraph()
Example #2
0
def test_ControlFlowGraphFromDotSource_edges():
    """Test that CFG edges are as expected."""
    g = llvm_util.ControlFlowGraphFromDotSource(SIMPLE_C_DOT)
    node_name_to_index_map = {g.nodes[n]["name"]: n for n in g.nodes}
    edges = set(g.edges)

    assert (node_name_to_index_map['%2'],
            node_name_to_index_map['%9']) in edges
    assert (node_name_to_index_map['%2'],
            node_name_to_index_map['%12']) in edges
    assert (node_name_to_index_map['%9'],
            node_name_to_index_map['%18']) in edges
    assert (node_name_to_index_map['%12'],
            node_name_to_index_map['%18']) in edges
Example #3
0
def TryToCreateControlFlowGraphsFromLinuxSrc(
        path: pathlib.Path) -> typing.Optional[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)
    except clang.ClangException:
        return graphs

    # Extract a dot sources from the bytecode.
    dot_generator = llvm_util.DotCfgsFromBytecode(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
Example #4
0
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)

    # Extract a single dot source from the bytecode.
    dot_generator = llvm_util.DotCfgsFromBytecode(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
Example #5
0
def test_ControlFlowGraphFromDotSource_node_names():
    """Test that CFG names are as expected."""
    g = llvm_util.ControlFlowGraphFromDotSource(SIMPLE_C_DOT)
    node_names = sorted([g.nodes[n]['name'] for n in g.nodes],
                        key=lambda x: int(x[1:]))
    assert node_names == ['%2', '%9', '%12', '%18']
Example #6
0
def test_ControlFlowGraphFromDotSource_num_edges():
    """Test that CFG has correct number of edges."""
    g = llvm_util.ControlFlowGraphFromDotSource(SIMPLE_C_DOT)
    assert g.number_of_edges() == 4
Example #7
0
def test_ControlFlowGraphFromDotSource_graph_name():
    """Test that CFG has correct name."""
    g = llvm_util.ControlFlowGraphFromDotSource(SIMPLE_C_DOT)
    assert g.graph['name'] == 'DoSomething'
Example #8
0
def test_ControlFlowGraphFromDotSource_invalid_source():
    """Test that exception is raised if dot can't be parsed."""
    with pytest.raises(pyparsing.ParseException):
        llvm_util.ControlFlowGraphFromDotSource("invalid dot source!")