Skip to content

API Examples

João Bispo edited this page Jul 13, 2022 · 9 revisions

Graphs

The LARA framework provides a base API for graphs based on Cytoscape.js, available in the package lara.graphs.

Outputting DOT from graph

The utility class lara.graphs.Graphs contains the method .toDot(graph, formatter) that can be used to output the graph in the Graphviz DOT format.

The formatter is optional, and is an instance of lara.graphs.DotFormatter.

Using a Clava static call graph as an example, the formatter below makes a node with a dashed line if the corresponding function does not have an implementation, and fills the node if it has an implementation but was not visited:

const dotFormatter = new DotFormatter();
dotFormatter.addNodeAttribute("style=dashed", node => Graphs.isLeafNode(node) && !node.data().hasImplementation());
dotFormatter.addNodeAttribute("style=filled", node => Graphs.isLeafNode(node) && node.data().hasCalls());

To generate the graph in DOT format from the static call graph:

var staticCallGraph = StaticCallGraph.build();
println(Graphs.toDot(staticCallGraph.graph, dotFormatter));

Alternatively you could write staticCallGraph.toDot(), this is the default formatter used by the StaticCallGraph instance.

Static Call Graph

We will be using the clava.graphs.StaticCallGraph, with the C code in this file as example.

StaticCallGraph contains a static build() method with two optional parameters, $jp and visitCalls. $jp is the point in code where the static call graph will be built from and its default value is the root of the AST. visitCalls is a boolean that indicates if the graph construction should proceed inside functions of the calls if finds, even if they are not part of the code represented by $jp.

Example 1 - Full Application Graph

To generate the static call graph for the available code of the application, we can write the following Clava snippet:

laraImport("clava.graphs.StaticCallGraph");

var fullGraph = StaticCallGraph.build();
println(fullGraph.toDot());

Which will generate this graph:

image

Each node represents a function of the source code, and an edge represents a call from the source function to the target function, and the label of the edge the number of times the function was called inside the function (statically).

Example 2 - Single Function Graph

Now consider we only want the static call graph of the code relative to a single function (e.g. foo1), we can write the following:

var functionGraph = StaticCallGraph.build(Query.search("function", "foo1").first(), false);

Which will generate this graph:

image

In this graph we only have code related to the provided function. Notice that since the implementation of foo2() has calls to other functions but it was not visited, it appears as a grey node.

Example 3 - Full Single Function Graph

To go beyond the code of the function, we can enable the option visitCalls (which is true by default):

var functionGraphFull = StaticCallGraph.build(Query.search("function", "foo1").first(), true);

This way, we are able to see the full call graph, starting from the given function:

image

Since foo3() does not have an implementation, only a declaration, its box appears dashed.

We can also provide a call as the starting point of the graph, the following code produces the same graph above:

var functionGraphFull = StaticCallGraph.build(Query.search("function", "main").search("call", "foo1").first());

Static Call Graph API

The method StaticCallGraph.build() returns a StaticCallGraph instance, which contains:

  • .graph, which returns a Cytoscape version of the call graph;
  • .functions, an object which maps functions (using $function.astId as key) to graph nodes;
  • .getNode($function), which returns the corresponding node of the given function (if a node was created for that function);

Each node contains a data object, that you can obtain by calling the function .data(), which contains:

  • .function, the $function AST node that corresponds to this graph node;

Each edge contains a data object, that you can obtain by calling the function .data(), which contains:

  • .calls, an array of $call AST nodes that corresponds to each call that contributed to this edge;