DynC : High Level Instrumentation With Dyninst

15
Paradyn Project Paradyn / Dyninst Week Madison, Wisconsin April 29 - May 1, 2013 DynC: High Level Instrumentation With Dyninst Emily Jacobson DynC and DynC API

description

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 (); - PowerPoint PPT Presentation

Transcript of DynC : High Level Instrumentation With Dyninst

Page 1: 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

Page 2: DynC :  High Level Instrumentation With  Dyninst

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

Page 3: DynC :  High Level Instrumentation With  Dyninst

3

Dyninst API

Evolution of DynC

DynC and DynC API

Interactive ShellDyner

C CodeGenDynC API

User Code

Mutator

Page 4: DynC :  High Level Instrumentation With  Dyninst

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

Page 5: DynC :  High Level Instrumentation With  Dyninst

5

if(inf`foo > i++){inf`printf(“Done”);DynC Snippetint i = 0inf`foo += 5

}

Runtime Compilation

DynC and DynC API

Dyninst API

DynC API

Page 6: DynC :  High Level Instrumentation With  Dyninst

6

DynC Snippet

Runtime Compilation

DynC and DynC API

Dyninst API

DynC API

Page 7: DynC :  High Level Instrumentation With  Dyninst

7

DynC Snippet

Runtime Compilation

DynC and DynC API

Dyninst API

DynC APIincl %eaxmov %eax,..

addis r1,..stw r1,...

BPatch Snippet

Page 8: DynC :  High Level Instrumentation With  Dyninst

8

DynC API

BPatch_Snippet *createSnippet(<snippet>, <location>)

DynC and DynC API

<snippet>char *

std::stringFILE *

<location>BPatch_Point

BPatch_AddressSpace

Page 9: DynC :  High Level Instrumentation With  Dyninst

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. ...

Page 10: DynC :  High Level Instrumentation With  Dyninst

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

Page 11: DynC :  High Level Instrumentation With  Dyninst

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

Page 12: DynC :  High Level Instrumentation With  Dyninst

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

Page 13: DynC :  High Level Instrumentation With  Dyninst

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

Page 14: DynC :  High Level Instrumentation With  Dyninst

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

Page 15: DynC :  High Level Instrumentation With  Dyninst

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