DYNINST

The figure above shows an instrumented application. The boxes on the left represent pieces of code inserted by Dyninst, which are referred to as snippets. The text on the right is the original application code. The first snippet increments a counter when we enter the function foo, and the second decrements it when we exit foo. The bottom snippet uses this counter to determine whether or not a call to SengMsg came from inside an invocation of foo, and if so, it adds the number of bytes being sent to another counter.
Code snippets in Dyninst are defined by creating objects of various child classes of the class BPatch_snippet. Each object represents a piece of data or an operation to perform. The constructors for many snippet types take other snippets as arguments, which are used as the operands for the operation that the snippet represents.
BPatch_variableExpr *fooCnt = appThread->malloc(appImage->findType("int"));
BPatch_variableExpr *bytes = appThread->malloc(appImage->findType("int"));
int zero = 0;
fooCnt.writeValue(&zero);
bytes.writeValue(&zero);
To create the snippets shown in the diagram, the first thing we need to do is to allocate memory for the two counters. We do this as shown in the code above, by calling the malloc method of the BPatch_thread object representing the application to be instrumented (in this case, appThread). We pass malloc the type of variable we want to allocate. We get the object that we need to identify the type by calling findType. After allocating the counters, we then initialize them to zero using the method "writeValue."
BPatch_arithExpr fooCntPlusOne(BPatch_plus, *fooCnt, BPatch_constExpr(1))
BPatch_arithExpr addCounter(BPatch_assign, *fooCnt, fooCntPlusOne)
Next we need to create a snippet that will increment fooCnt. First, we perform the addition,
using a BPatch_arithExpr object with a parameter indicating addition, and the value of fooCnt and the
constant one as the quantities to be added. We then assign the result back to
fooCnt, again using a
BPatch_arithExpr, this time with a parameter indicating assignment.
BPatch_arithExpr fooCntMinusOne(BPatch_minus, *fooCnt, BPatch_constExpr(1))
BPatch_assign subCounter(BPatch_assign, *fooCnt, fooCntMinusOne)
The subCounter snippet is almost exactly the same as addCounter, with BPatch_minus substituted for
BPatch_plus.
BPatch_paramExpr cntParam(2), sizeParam(3);
BPatch_arithExpr calcBytes(BPatch_times, cntParam, sizeParam);
BPatch_arithExpr addBytes(BPatch_plus, *bytes, calcBytes);
BPatch_arithExpr addCounter(BPatch_assign, *bytes, addBytes);
We next need to build the snippet that will be inserted into sengMsg. The first line above declares
objects that represent the third and fourth parameters of a procedure (the index begins at zero).
For the sendMsg procedure, these are the cnt and sz parameters.
In the second line, we multiply these
together to get the number of bytes being written. The third and fourth lines add the calculated value
to the bytes counter, and assign the new value to it.
BPatch_boolExpr fooCntCheck(BPatch_gt, *fooCnt, BPatch_constExpr(0));
BPatch_ifExpr addCounterIfInFoo(fooCntCheck, addCounter);
Finally we will create the conditional statement. We only want to execute the addCounter snippet if
the value of fooCnt is greater than zero. We test this using a BPatch_boolExpr.
As shown in the first line above, we pass the constructor for this class an argument that
specifies the comparison we want to make,
BPatch_gt for "greater than." We also pass the two expressions we want to compare,
our counter fooCnt and the constant zero. In the second line, we create the
conditional statement by declaring a BPatch_ifExpr object, passing it our boolean
expression as the condition, and the addCounter snippet
as the code to execute if the boolean evaluates to true.