DynC : High Level Instrumentation With Dyninst
description
Transcript of DynC : High Level Instrumentation With Dyninst
Paradyn Project
Paradyn / Dyninst WeekMadison, Wisconsin
April 29 - May 1, 2013
DynC: High Level Instrumentation With
DyninstEmily Jacobson
DynC and DynC API
2
int main(int argc, char *argv[]){ BPatch_process * proc = bpatch.processCreate(“myMutatee”); BPatch_image *image = proc->getImage(); bpatch.registerExitCallback( readMaxArg );
//Create level variable BPatch_variableExpr *globalLevel = process->malloc(image->findType("int"));
// Entry Snippet BPatch_variableExpr *globalVar = image->findVariable("a_global_var"); BPatch_paramExpr *paramVar = new BPatch_paramExpr(0); BPatch_localVar *localVar = NULL; // Cannot be built independantly
BPatch_retExpr *ret = new BPatch_retExpr(); BPatch_variableExpr *entryCounter = NULL; BPatch_variableExpr *exitCounter = NULL;
std::vector<BPatch_function *> *funcs; BPatch_function *printfFunc = image->findFunction("printf", funcs);
std::vector<BPatch_function *> allFunctions; image->getProcedures(allFunctions);
for (FuncVector::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) {
// Assign our local variable entryCounter = process->malloc(image->findType("int")); local = (*iter)->findLocalVar("a_local_var");
// Allocate a counter entryCounter = proc->malloc(image->findType("int")); exitCounter = proc->malloc(image->findType("int")); std::vector<BPatch_snippet *> args;
args.push_back(BPatch_constExpr("(level %d) Entering %s[at %p] for the %d time: parameter = %s, local = %d, global = %d.\n")); args.push_back(globalLevel);
char fname[512]; args.push_back((iter*)->getName(fName, 512)); args.push_back(new BPatch_originalAddressExpr()); args.push_back(entryCounter); args.push_back(paramVar); args.push_back(localVar); args.push_back(globalVar);
//build printf BPatch_funcCallExpr *printfExprEntry = new BPatch_funcCallExpr(printfFunc, args);
args = std::vector(); args.push_back(BPatch_constExpr("(level %d) Exiting %s: returning = %d, global = %d.\n")); args.push_back(globalLevel);
char fname[512]; args.push_back((iter*)->getName(fName, 512)); args.push_back(BPatch_retExpr()); args.push_back(globalVar);
BPatch_funcCallExpr *printfExprExit = new BPatch_funcCallExpr(exitFunc, args);
// Now that we have the snippets, get points and instrument std::vector<BPatch_points *> *entryPs = (*iter)->findPoint(BPatch_locEntry); std::vector<BPatch_points *> *exitPs = (*iter)->findPoint(BPatch_locExit); proc->insertSnippet(*entry, *entryPs); proc->insertSnippet(*exit, *exitPs); }}
Motivation: Dyninst vs. DynCDyninst API DynC API
int main(int argc, char *argv[]){ BPatch_process * proc = bpatch.processCreate(“myMutatee”); BPatch_image *image = proc->getImage(); bpatch.registerExitCallback( readMaxArg ); proc->malloc(*image->findType("int"), “mallocCounter”);
FILE *dynCEntryFile = fopen( “entryDynC.txt”, “r”); FILE *dynCExitFile = fopen( “exitDynC.txt”, “r”);
std::vector<BPatch_function *> allFunctions; image->getProcedures(allFunctions);
for (FuncVector::iterator iter = funcs.begin(); iter != funcs.end(); ++iter) { PointVector *entryPts = (*iter)->findPoint(Bpatch_Entry); PointVector *exitPts = (*iter)->findPoint(BPatch_locExit); BPatch_snippet *entrySnippet = DynC_API::createSnippet(dynCEntryFile, (iter*)->entryPts[0]); BPatch_snippet *exitSnippet = DynC_API::createSnippet(dynCExitFile, (iter*)->exitPts[0]); proc->insertSnippet(*entrySnippet, *entryPts); proc->insertSnippet(*exitSnippet, *exitPts); }
proc->continueExecution(); while (!proc->isTerminated()) bpatch.waitForStatusChange(); return 0;}
DynC and DynC API
3
Dyninst API
Evolution of DynC
DynC and DynC API
Interactive ShellDyner
C CodeGenDynC API
User Code
Mutator
4
int i = 0inf`foo += 5
Runtime Compilation
DynC and DynC API
if(inf`foo > i++){
}inf`printf(“Done”);DynC Snippet
Dyninst API
DynC API
5
if(inf`foo > i++){inf`printf(“Done”);DynC Snippetint i = 0inf`foo += 5
}
Runtime Compilation
DynC and DynC API
Dyninst API
DynC API
6
DynC Snippet
Runtime Compilation
DynC and DynC API
Dyninst API
DynC API
7
DynC Snippet
Runtime Compilation
DynC and DynC API
Dyninst API
DynC APIincl %eaxmov %eax,..
addis r1,..stw r1,...
BPatch Snippet
8
DynC API
BPatch_Snippet *createSnippet(<snippet>, <location>)
DynC and DynC API
<snippet>char *
std::stringFILE *
<location>BPatch_Point
BPatch_AddressSpace
10
Tracing Execution with DynCo Print out:
oGlobals: tick_counto Locals: local_itero Parameters and return valueso Function names, addresses, and execution
countsoCall stack depth
DynC and DynC API
... (level 1) Entering funcFoo[0x010], count 1: param = “sim”, str_length = 3, tick_count = 3.(level 2) Entering funcBar[0x080], count 3: param = “emul”, str_length = 4, tick_count = 42.(level 2) Exiting funcBar: returning 320, tick_count = 80. (level 1) Exiting funcFoo: returning 1000, tick_count = 110. ...
11DynC and DynC API
Naming Functions and VariablesMutatee
// Global variablesint tick_count = 0;
// Functionsint foo(char *str) { int str_length = strlen(str); int hash = 0; for (int i = 0; i < str_length; ++i) { bar(...); } return hash;}
int bar(char *str) { ... }
// Library functionsint printf(char *format, ...);
o DynC uses naming rather than lookup
o Domains specify naming scopeo Global domaino Local domaino Parameter domaino Inferior domaino Dyninst domain
12
Example: DynC Entry Instrumentation
DynC and DynC API
// global_level is a variable we allocatedchar *funcName = dyninst`function_name;void *funcAddr = dyninst`original_address;inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs);
static int entryCounter = 0;inf`printf(“count = %d”, entryCounter++);
char *funcParam = param`0;inf`printf(“param = \”%s\””, funcParam);
int localVar = local`str_length;inf`printf(“local_iter = %d”, str_length);
int globalVar = global`tick_count;inf`printf(“tick_count = %d\n”, globalVar);
o Access information about the instrumented pointo Function nameo Original addresso Effective address of a
memory operationo Thread ID or indexo Target of indirect control flow
13
Example: DynC Entry Instrumentation
DynC and DynC API
// global_level is a variable we allocatedchar *funcName = dyninst`function_name;void *funcAddr = dyninst`original_address;inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs);
static int entryCounter = 0;inf`printf(“count = %d”, entryCounter++);
char *funcParam = param`0;inf`printf(“param = \”%s\””, funcParam);
int localVar = local`str_length;inf`printf(“local_iter = %d”, str_length);
int globalVar = global`tick_count;inf`printf(“tick_count = %d\n”, globalVar);
o Declare and access variables
14
Example: DynC Entry Instrumentation
DynC and DynC API
// global_level is a variable we allocatedchar *funcName = dyninst`function_name;void *funcAddr = dyninst`original_address;inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs);
static int entryCounter = 0;inf`printf(“count = %d”, entryCounter++);
char *funcParam = param`0;inf`printf(“param = \”%s\””, funcParam);
int localVar = local`str_length;inf`printf(“local_iter = %d”, str_length);
int globalVar = global`tick_count;inf`printf(“tick_count = %d\n”, globalVar);
o Access parameterso By number or name
15
Example: DynC Entry Instrumentation
DynC and DynC API
// global_level is a variable we allocatedchar *funcName = dyninst`function_name;void *funcAddr = dyninst`original_address;inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs);
static int entryCounter = 0;inf`printf(“count = %d”, entryCounter++);
char *funcParam = param`0;inf`printf(“param = \”%s\””, funcParam);
int localVar = local`str_length;inf`printf(“local_iter = %d”, str_length);
int globalVar = global`tick_count;inf`printf(“tick_count = %d\n”, globalVar);
o Access local and global variables
16DynC and DynC API
Summary and Statuso C-style instrumentation interface
oDomains identify functions and variables
o Beta in Dyninst 7o Interface feedback welcomedo Demo: 2:00 – 3:00, Room 1170o Tutorial: Tomorrow 9:00 – 12:00, Room
1260