Parametric Regular Path Queries
Prev |  | Next

## Parametric Regular Path Queries

Kaveri now includes an implementation of the parametric regular path query engine. Regular path queries are regular expression based queries that are matched against graph paths. The result of the query is a graph path that satisfies the properties specified by the query. Parametric regular path queries extend the regular expression pattern with variables called parameters. These parameters are bound to special values in the path as the property is satisfied. They are useful in finding paths with interesting properties or for verifying properties along all paths between two nodes in the graph. For details about the parametric regular queries please refer to [PEQ]. There are two kinds of queries that are supported:

- Existential Queries: These determine if there exist paths in the graph that satisfy a given property. The query is run from a starting node and the result of the query is all the paths leading out from that node that satisfy the given property.
- Universal Queries: These determine if all the paths from a given node satisfy the given property. They are used for verifying properties along paths in the graph.

In Kaveri, the queries are run on the program dependency graph as calculated by Indus. The graph is constructed as follows:

- Node: Nodes are linked to Jimple program points.
- Edges: Edges connect program points with each edge having a label. The label indicates the dependency relation between the two program points.

The query is thus a program dependency based parametric regular expression. The BNF for the input query language is as follows:

> Query := ("Equery" | "Uquery") Name { union };
> Name := ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
> union := repterm repterm*
> repterm := term repetition?
> repetition := ? | * | +
> term := group | atom
> group := '(' union ')'
> atom := < constructor >
> constructor := constructor-name '(' var-name ')'
> var-name := ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*

The constructors are defined as follows: (x is the variable name).

1. cdepd(x) : Follow the control dependence edge from the current node and reach the point that the current node is control dependent on. x binds to current node.
2. cdept(x) : Follow the control dependence edge from the current node and reach the point that control dependent on the current node. x binds to current node.
3. idef(x) : Follow the identifier data dependence edge from the current node and reach the point where the variable used in the current node is defined. x binds to local variable.
4. iuse(x) : Follow the identifier data dependence edge from the current node and reach the point where the variable defined in the current node is used. x binds to local variable.
5. idepd(x) : Follow the interference dependence edge from the current node and reach the point that the current node is interference depedent on. x binds to soot field that causes the interference.
6. idept(x) : Follow the interference dependence edge from the current node and reach the point that the node that is interference dependent on the current node. x binds to soot field that causes the interference.
7. rdepd(x) : Follow the ready dependence edge from the current node and reach the point that the current node is ready dependent on. x binds to current node.
8. rdept(x) : Follow the ready dependence edge from the current node and reach the point that ready dependent on the current node. x binds to current node.
9. sdepd(x) : Follow the synchronization dependence edge from the current node and reach the point that the current node is synchronization dependent on. x binds to current node.
10. sdept(x) : Follow the synchronization dependence edge from the current node and reach the point that synchronization dependent on the current node. x binds to current node.
11. ddepd(x) : Follow the divergence dependence edge from the current node and reach the point that the current node is divergence dependent on. x binds to current node.
12. ddept(x) : Follow the divergence dependence edge from the current node and reach the point that divergence dependent on the current node. x binds to current node.
13. rdef(x) : Follow the reference data dependence edge from the current node and reach the point where the variable used in the current node is defined. x binds to reference variable.
14. ruse(x) : Follow the reference data dependence edge from the current node and reach the point where the variable defined in the current node is used. x binds to reference variable.

Examples of valid queries are:

- Equery q1 { <idept(x)> (<sdepd(y)>)}; - This existential query finds a path where the first edge in the path is a interference dependent edge on the starting node and the second edge is a synchronization dependee edge. So it matches the following code:

          Thread 1:

          if (a>b) {
           t = s + 10;
          }
          ............
          Thread 2:
          synchronized(obj) {
          System.out.printtln(t);
          }
          ......
          System.out.println("t = " + t);

  As per the query, x binds to the reference variable t and y binds to the program point System.out.println(t).
- Uquery q2 { <cdept(x)> (<iuse(y)>)*}; This query matches the paths from the starting point where all the paths have one contol dependent edge and zero or more variable usage edges. No other type of edges are allowed between the points. This matches the following fragment:

       if (a > b) {
           e = 10;
            f = 20;
       }

       r = e * 10;

  According to the query in the first result , x binds to if (a>b) and y binds to e. In the second result x binds to if (a>b) following the control dependence between if(a>b) and f=20;.

To run the parametric queries, the peq view has to be activated. This can be done from Window -> Show View -> Others -> Kaveri -> Peq View. Before using the peq view, a slice must already have been performed. Also a point to be noted is that the dependence information available from peq depends on the configuration used by the slice. If the particular configuration disables a dependence and the query uses it, the result will be empty even though edges might exist in reality. So before using the peq engine, please use a slice configuration with all the dependencies turned on. The following toolbar buttons are present in the view:

- Tracking: Switches the view on/off like the Jimple view.
- Add a query: Opens a text box where the query can be entered. A default template is provided.
- Run the query :Runs the query and populates the result tab..
- Update the statement: Updates the location from which to run the query. To use it, navigate to a different program point in the Java editor and press Update to change the starting location of the query..
- Remove the query: Deletes the currently selected query from the combo box.

Steps to use the query engine:

1. Switch the view to on state by toggling the tracking toolbar button.
2. Naviate to the desired program point in the Java editor.
3. Press update to refresh the view.
4. Press add to add a new query or pick a query from the combo box.
5. Press run to run the query. The result pane is populated with the results of the query. The result nodes can be expaned to view the graph edge that was matched. Double clicking on the edge source and destination nodes highlights the corressponding Java statement in the editor. The substitutions that were made till that point are displayed on the right pane. Click on the result node to get the complete substitution map.

Figure 9. Peq View

Using PEQ requires that the ANTLR eclipse plugin is installed. It can be obtained from http://antlreclipse.sourceforge.net/ . Also the peq eclipse plugin has to be installed separately. Install procedure for the peq plugin is similar to that of Kaveri.

Prev | Up | Next
Dependence Chasing | Home | Features