Skip to content

Instantly share code, notes, and snippets.

@arpith20
Created May 7, 2016 10:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arpith20/d4ccb3476e71a2e2bedd1258c6a5c3f6 to your computer and use it in GitHub Desktop.
Save arpith20/d4ccb3476e71a2e2bedd1258c6a5c3f6 to your computer and use it in GitHub Desktop.
/**
* Inserts instrumentation in a manner such that the resulting control flow
* graph (CFG) of the program will contain <code>toInsert</code> on an edge
* that is defined by <code>point_source</code> and <code>point_target</code>.
*
* @param toInsert the instrumentation to be added in the Chain
* @param point_src the source point of an edge in CFG
* @param point_tgt the target point of an edge
*/
public void insertOnEdge(E toInsert, E point_src, E point_tgt) {
if (toInsert == null)
throw new RuntimeException("Bad idea! You tried to insert " + "a null object into a Chain!");
if (map.containsKey(toInsert))
throw new RuntimeException("Chain already contains object.");
// Insert 'toInsert' before 'target' point in chain if the source point is null
if (point_src == null && point_tgt != null) {
((Unit) point_tgt).redirectJumpsToThisTo((Unit) toInsert);
insertBefore(toInsert, point_tgt);
return;
}
// Insert 'toInsert' after 'source' point in chain if the target point is null
if (point_src != null && point_tgt == null) {
insertAfter(toInsert, point_src);
return;
}
// Throw an exception if both source and target is null
if (point_src == null && point_tgt == null) {
throw new RuntimeException("insertOnEdge failed! Both source and target points are null");
}
// If target is right after the source in the Chain
// 1- Redirect all jumps (if any) from 'source' to 'target', to 'toInsert'
// (source->target) ==> (source->toInsert)
// 2- Insert 'toInsert' after 'source' in Chain
if (getSuccOf(point_src) == point_tgt) {
List<UnitBox> boxes = ((Unit) point_src).getUnitBoxes();
for (UnitBox box : boxes) {
if (box.getUnit() == point_tgt) {
box.setUnit((Unit) toInsert);
}
}
insertAfter(toInsert, point_src);
return;
}
// If the target is not right after the source in chain then,
// 1- Redirect all jumps (if any) from 'source' to 'target', to 'toInsert'
// (source->target) ==> (source->toInsert)
// 1.1- if there are no jumps from source to target, then such an edge does not exist. Throw an exception.
// 2- Insert 'toInsert' before 'target' in Chain
// 3- If required, add a 'goto target' statement so that no other edge executes 'toInsert'
boolean validEdgeFound = false;
E originalPred = getPredOf(point_tgt);
List<UnitBox> boxes = ((Unit) point_src).getUnitBoxes();
for (UnitBox box : boxes) {
if (box.getUnit() == point_tgt) {
if (point_src instanceof GotoStmt) {
box.setUnit((Unit) toInsert);
insertAfter(toInsert, point_src);
E goto_unit = (E) new JGotoStmt((Unit) point_tgt);
insertAfter(goto_unit, toInsert);
return;
}
box.setUnit((Unit) toInsert);
validEdgeFound = true;
}
}
if (validEdgeFound) {
insertBefore(toInsert, point_tgt);
if (originalPred != point_src) {
if (originalPred instanceof GotoStmt)
return;
E goto_unit = (E) new JGotoStmt((Unit) point_tgt);
insertBefore(goto_unit, (E) toInsert);
}
return;
}
// In certain scenarios, the above code can add extra 'goto' units on a different edge
// So, an edge [src --> tgt] becomes [src -> goto tgt -> tgt].
// When this happens, the original edge [src -> tgt] ceases to exist.
// The following code handles such scenarios.
if (getSuccOf(point_src) instanceof GotoStmt) {
if (((Unit) getSuccOf(point_src)).getUnitBoxes().get(0).getUnit() == point_tgt) {
((Unit) getSuccOf(point_src)).redirectJumpsToThisTo((Unit) toInsert);
insertBefore(toInsert, getSuccOf(point_src));
return;
}
}
// If the control reaches this point, it means that an edge [stc -> tgt] as specified by user does not exist and is thus invalid
// Return an exception.
throw new RuntimeException(
"insertOnEdge failed! No such edge found. The edge on which you want to insert an instrumentation is invalid.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment