150 likes | 281 Views
DynC : High Level Instrumentation With Dyninst. Emily Jacobson. Motivation: Dyninst vs. DynC. DynC API. int main( int argc , char * argv []) { BPatch_process * proc = bpatch.processCreate (“ myMutatee ”); BPatch_image *image = proc -> getImage ();
E N D
DynC: High Level Instrumentation With Dyninst Emily Jacobson DynC and DynC API
Motivation: Dyninst vs. DynC DynC API intmain(intargc, 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; } Dyninst API int main(intargc, 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); } } DynC and DynC API
Evolution of DynC Mutator Interactive Shell User Code Dyner C CodeGen Dyninst API DynC API DynC and DynC API
Runtime Compilation Dyninst API DynC API int i = 0 inf`foo += 5 DynC Snippet if(inf`foo > i++){ inf`printf(“Done”); } DynC and DynC API
Runtime Compilation Dyninst API DynC API int i = 0 inf`foo += 5 DynC Snippet if(inf`foo > i++){ inf`printf(“Done”); } DynC and DynC API
Runtime Compilation Dyninst API DynC API DynC Snippet DynC and DynC API
Runtime Compilation Dyninst API DynC API DynC Snippet incl %eax mov %eax,.. addis r1,.. stw r1,... BPatch Snippet DynC and DynC API
DynC API BPatch_Snippet *createSnippet(<snippet>, <location>) <snippet> char * std::string FILE * <location> BPatch_Point BPatch_AddressSpace DynC and DynC API
Tracing Execution with DynC • Print out: • Globals: tick_count • Locals: local_iter • Parameters and return values • Function names, addresses, and execution counts • Call stack depth ... (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. ... DynC and DynC API
Naming Functions and Variables Mutatee • DynC uses naming rather than lookup • Domains specify naming scope • Global domain • Local domain • Parameter domain • Inferior domain • Dyninst domain // Global variables inttick_count = 0; // Functions intfoo(char *str) { intstr_length = strlen(str); int hash = 0; for (inti = 0; i < str_length; ++i) { bar(...); } return hash; } int bar(char *str) { ... } // Library functions intprintf(char *format, ...); DynC and DynC API
Example: DynC Entry Instrumentation • Access information about the instrumented point • Function name • Original address • Effective address of a memory operation • Thread ID or index • Target of indirect control flow // global_level is a variable we allocated char *funcName = dyninst`function_name; void *funcAddr = dyninst`original_address; inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs); static intentryCounter = 0; inf`printf(“count = %d”, entryCounter++); char *funcParam = param`0; inf`printf(“param = \”%s\””, funcParam); intlocalVar = local`str_length; inf`printf(“local_iter = %d”, str_length); intglobalVar = global`tick_count; inf`printf(“tick_count = %d\n”, globalVar); DynC and DynC API
Example: DynC Entry Instrumentation • Declare and access variables // global_level is a variable we allocated char *funcName = dyninst`function_name; void *funcAddr = dyninst`original_address; inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs); static intentryCounter = 0; inf`printf(“count = %d”, entryCounter++); char *funcParam = param`0; inf`printf(“param = \”%s\””, funcParam); intlocalVar = local`str_length; inf`printf(“local_iter = %d”, str_length); intglobalVar = global`tick_count; inf`printf(“tick_count = %d\n”, globalVar); DynC and DynC API
Example: DynC Entry Instrumentation • Access parameters • By number or name // global_level is a variable we allocated char *funcName = dyninst`function_name; void *funcAddr = dyninst`original_address; inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs); static intentryCounter = 0; inf`printf(“count = %d”, entryCounter++); char *funcParam = param`0; inf`printf(“param = \”%s\””, funcParam); intlocalVar = local`str_length; inf`printf(“local_iter = %d”, str_length); intglobalVar = global`tick_count; inf`printf(“tick_count = %d\n”, globalVar); DynC and DynC API
Example: DynC Entry Instrumentation • Access local and global variables // global_level is a variable we allocated char *funcName = dyninst`function_name; void *funcAddr = dyninst`original_address; inf`printf(“(level %d) Entering %s[%p]”, global`global_level++, funcName, funcAddrs); static intentryCounter = 0; inf`printf(“count = %d”, entryCounter++); char *funcParam = param`0; inf`printf(“param = \”%s\””, funcParam); intlocalVar = local`str_length; inf`printf(“local_iter = %d”, str_length); intglobalVar = global`tick_count; inf`printf(“tick_count = %d\n”, globalVar); DynC and DynC API
Summary and Status • C-style instrumentation interface • Domains identify functions and variables • Beta in Dyninst 7 • Interface feedback welcomed • Demo: 2:00 – 3:00, Room 1170 • Tutorial: Tomorrow 9:00 – 12:00, Room 1260 DynC and DynC API