Information Technology Reference
In-Depth Information
chies effectively represent the scope of the current
tracing functionality.
Buck and Hollingsworth expanded the dy-
namic instrumentation element of Paradyn in
their Dyninst work (Buck & Hollingsworth,
2000). Dyninst provides a C++ API and a set of
run-time libraries that allow users to build tools
for modifying dynamic binary code. It attaches
to loaded binaries that are either already run-
ning or that are explicitly loaded by the Dyninst
run-time. Once attached to an executable, tools
written using the Dyninst API (termed mutators)
can be used to modify the binary image directly
in memory.
Dyninst works by adding “trampolines” into
the target binary at selected positions, shown in
D. Branch instructions are inserted into the target
program, at user-defined positions, to redirect
control flow into the base trampoline. Base tram-
polines are instantiated for each instrumentation
point in the target code. Each contains pre- and
post- branching to global primitives (called for
all processes) and local instrumentation primi-
tives (called only for the specific instrumentation
point). Base trampolines also include the original
code that was displaced from the target, which
is also executed.
Dyninst's thread abstraction allows developers
to associate instrumentation with specific threads
that are running in the system, which is a neces-
sary part of their selective profiling scheme. With
this approach the overhead of instrumentation is
incurred up-front in modifying the binary im-
age. After the image has been modified, the only
overhead is the cost of trampolining and the ad-
ditional instructions imposed by the instrumented
primitives.
Snippet code (the code which is being added to
the target image) is created using the DyninstAPI
to dynamically assemble variable declarations,
expressions, and so forth. The following excerpt
illustrates how the Dyninst API can be used to
create a global counter variable and an expression
that increments it. (Box 6)
Dyninst is designed to target the native pro-
cessor; the modified instructions target the actual
underlying hardware. Other work, such as Pin
(Luk et al., 2005), Dixie (Fernandez, Ramirez,
Cernuda, & Espasa, 1999), DynamoRIO (Bru-
ening, 2004), and Valgrind (Nethercote, 2004),
have pursued the use of JIT cross-compilation so
that the modified binary code can be executed on
an emulated (i.e., virtual) machine architecture.
Targeting a virtual machine provides more con-
trol and the ability to inspect low-level details of
behavior, such as register and cache activity. It
also does not necessarily imply translation across
different instruction set architectures (ISA). In
most instances, the virtual machine uses the
same ISA as the underlying host, so that while
hooks and interceptors can be put in place, the
bulk of the code can simply be passed through
and executed by the host.
The Pin program analysis system (Luk et al.
2005) is an example of dynamic compilation
targeting a virtual machine architecture using
Box 6.
// create a global int variable in the address space of the application
//
BPatch_variableExpr * intCounter = appThread->malloc(*appImage->indType(“int”));
// create an expression that increments counter variable
//
BPatch_arithExpr addOne(BPatch_assign, *intCounter, BPatch_constExpr(1));
 
Search WWH ::




Custom Search