static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { // Pin does not support issuing an RTN_ReplaceSignature from the TRACE instrumentation callback // This will cause Pin to terminate with an error PROTO proto_watch_rtn = PROTO_Allocate(PIN_PARG(void), CALLINGSTD_DEFAULT, "watch_rtn", PIN_PARG(int), PIN_PARG_END()); RTN_ReplaceSignature(rtn, AFUNPTR(WatchRtnReplacement), IARG_PROTOTYPE, proto_watch_rtn, IARG_CONST_CONTEXT, IARG_THREAD_ID, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); }
VOID Trace(TRACE trace, VOID *v) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); if( INS_IsCall(tail) ) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } else { // sometimes code is not in an image RTN rtn = TRACE_Rtn(trace); // also track stup jumps into share libraries if( RTN_Valid(rtn) && !INS_IsDirectBranchOrCall(tail) && ".plt" == SEC_Name( RTN_Sec( rtn ) )) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } } } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); ADDRINT version = TRACE_Version(trace); // If we are not in watch_rtn, switch back to base version if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { if (version != VERSION_BASE) BBL_SetTargetVersion(TRACE_BblHead(trace), VERSION_BASE); return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { INS ins = BBL_InsHead(TRACE_BblHead(trace)); if (version == VERSION_BASE) { // version_reg is used to select the version, use the first // argument of watch_rtn to set it INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(select_version), IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_RETURN_REGS, version_reg, IARG_END); // IF we are in the base version, decide if we should go to the // other versions // Note that the version instrumentation will occur before any // following instrumentation done on this ins INS_InsertVersionCase(ins, version_reg, 10, VERSION_1, IARG_END); INS_InsertVersionCase(ins, version_reg, 20, VERSION_2, IARG_END); printf ("Instrumentation at %p\n", reinterpret_cast<void *>(INS_Address(ins))); } } INS ins = BBL_InsHead(TRACE_BblHead(trace)); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Instrumentation depends on version // These instrumentations occur after the preceeding version instrumentation // (i.e. the instrumentation inserted by the above INS_InsertVersionCase calls switch(version) { case VERSION_BASE: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version base", IARG_END); break; case VERSION_1: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 1", IARG_END); break; case VERSION_2: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 2", IARG_END); break; default: assert(0); break; } } }
IMG GetImgByTrace(TRACE trace) { IMG img = IMG_Invalid(); RTN rtn = TRACE_Rtn(trace); if (RTN_Valid(rtn)) { SEC sec = RTN_Sec(rtn); if (SEC_Valid(sec)) { img = SEC_Img(sec); } } return img; }
static BOOL IsPLT(TRACE trace) { RTN rtn = TRACE_Rtn(trace); // All .plt thunks have a valid RTN if (!RTN_Valid(rtn)) return FALSE; if (".plt" == SEC_Name(RTN_Sec(rtn))) return TRUE; return FALSE; }
static BOOL traceFromExecutable(TRACE trace) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn)) return FALSE; SEC sec = RTN_Sec(rtn); if (!SEC_Valid(sec)) return FALSE; IMG img = SEC_Img(sec); if (!IMG_Valid(img)) return FALSE; return IMG_IsMainExecutable(img); }
VOID Trace(TRACE trace, VOID *v) { if ( KnobNoSharedLibs.Value() && IMG_Type(SEC_Img(RTN_Sec(TRACE_Rtn(trace)))) == IMG_TYPE_SHAREDLIB) return; for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Insert instrumentation to count the number of times the bbl is executed BBLSTATS * bblstats = new BBLSTATS(BBL_Address(bbl), BBL_Size(bbl)); INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(bblstats->_executed), IARG_END); // Remember the counter and stats so we can compute a summary at the end statsList.push_back(bblstats); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { BBL_InsertCall(TRACE_BblHead(trace), IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace_BBL instrumentation", IARG_CALL_ORDER, CALL_ORDER_FIRST+2, IARG_END); printf("Trace Instrumenting %s\n", watch_rtn); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { // Pin does not support issuing an RTN_Replace from the TRACE instrumentation callback // This will cause Pin to terminate with an error RTN_Replace(rtn, AFUNPTR(WatchRtnReplacement)); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { // Pin does not support issuing an RTN_InsertCall from the TRACE instrumentation callback // This will cause Pin to terminate with an error RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Ins instrumentation1", IARG_END); RTN_Close(rtn); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); ADDRINT version = TRACE_Version(trace); // If we are not in watch_rtn, switch back to base version if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { if (version != VERSION_BASE) BBL_SetTargetVersion(TRACE_BblHead(trace), VERSION_BASE); return; } INS ins = BBL_InsHead(TRACE_BblHead(trace)); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Instrumentation depends on version // These instrumentations occur after the following version instrumentation // (i.e. the instrumentation inserted by the below INS_InsertVersionCase calls // from within the image load callback - because image load callback // instrumentation occurs before trace and before instruction callback instrumentation switch(version) { case VERSION_BASE: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version base", IARG_END); break; case VERSION_1: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 1", IARG_END); break; case VERSION_2: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 2", IARG_END); break; default: assert(0); break; } } }
VOID Trace(TRACE trace, VOID *v) { const RTN rtn = TRACE_Rtn(trace); if (! RTN_Valid(rtn)) return; const SEC sec = RTN_Sec(rtn); ASSERTX(SEC_Valid(sec)); const IMG img = SEC_Img(sec); ASSERTX(IMG_Valid(img)); if ( KnobNoSharedLibs.Value() && IMG_Type(img) == IMG_TYPE_SHAREDLIB) return; for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Record the registers into a dummy buffer so we can count them #define MAX_STATS_PER_BLOCK (128*1024) UINT16 buffer[MAX_STATS_PER_BLOCK]; INT32 count = RecordRegisters(bbl, buffer, MAX_STATS_PER_BLOCK); ASSERTX(count < MAX_STATS_PER_BLOCK); // Summarize the stats for the bbl in a 0 terminated list // This is done at instrumentation time UINT16 * stats = new UINT16[count]; memcpy(stats, buffer, count * sizeof(UINT16)); // Insert instrumentation to count the number of times the bbl is executed BBLSTATS * bblstats = new BBLSTATS(stats); INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, bblstats->_counter, IARG_THREAD_ID, IARG_END); // Remember the counter and stats so we can compute a summary at the end statsList.push_back(bblstats); } }
VOID Trace(TRACE trace, VOID *v) { if ( KnobNoSharedLibs.Value() && IMG_Type(SEC_Img(RTN_Sec(TRACE_Rtn(trace)))) == IMG_TYPE_SHAREDLIB) return; const BOOL accurate_handling_of_predicates = KnobProfilePredicated.Value(); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Summarize the stats for the bbl in a 0 terminated list // This is done at instrumentation time UINT16 * stats = new UINT16[BBL_NumIns(bbl) + 1]; INT32 index = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { // Count the number of times a predicated instruction is actually executed // this is expensive and hence disabled by default if( INS_IsPredicated(ins) && accurate_handling_of_predicates ) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(GlobalStatsDynamic.predicated_true[INS_Category(ins)]), IARG_END); } stats[index++] = INS_GetStatsIndex(ins); } stats[index] = 0; // Insert instrumentation to count the number of times the bbl is executed BBLSTATS * bblstats = new BBLSTATS(stats); INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(bblstats->_counter), IARG_END); // Remember the counter and stats so we can compute a summary at the end statsList.push_back(bblstats); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { INS ins = BBL_InsHead(TRACE_BblHead(trace)); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace instrumentation3", IARG_END); BBL_InsertCall(TRACE_BblHead(trace), IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace instrumentation2", IARG_END); TRACE_InsertCall(trace, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace instrumentation1", IARG_END); printf("Trace Instrumenting %s\n", watch_rtn); } }
VOID Trace(TRACE trace, VOID *v) { const BOOL print_args = KnobPrintArgs.Value(); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); if( INS_IsCall(tail) ) { if( INS_IsDirectBranchOrCall(tail) ) { const ADDRINT target = INS_DirectBranchOrCallTargetAddress(tail); if( print_args ) { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args), IARG_PTR, Target2String(target), IARG_G_ARG0_CALLER, IARG_END); } else { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, AFUNPTR(do_call), IARG_PTR, Target2String(target), IARG_END); } } else { if( print_args ) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_G_ARG0_CALLER, IARG_END); } else { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } } } else { // sometimes code is not in an image RTN rtn = TRACE_Rtn(trace); // also track stup jumps into share libraries if( RTN_Valid(rtn) && !INS_IsDirectBranchOrCall(tail) && ".plt" == SEC_Name( RTN_Sec( rtn ) )) { if( print_args ) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_G_ARG0_CALLER, IARG_END); } else { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } } } } }
// ------------------------------------------------------------- // Trace instrumentation function // ------------------------------------------------------------- void I_Trace(TRACE trace, void *v) { BOOL isPLT = IsPLT(TRACE_Rtn(trace)); #if DEBUG_INS printf("-- Instrumenting trace %X of function %s\n", TRACE_Address(trace), RTN_Valid(TRACE_Rtn(trace)) ? RTN_Name(TRACE_Rtn(trace)).c_str() : "<unknown_routine>"); #endif // scan BBLs within the current trace for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // instrument memory reads and writes for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) Instruction(ins); INS tail = BBL_InsTail(bbl); // skip system calls if ( INS_IsSyscall(tail) ) continue; // instrument .plt stub calls if ( isPLT ) { #if DEBUG_INS printf(" > .plt stub call\n"); #endif if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } continue; } // instrument all calls and returns if ( INS_IsCall(tail) ) { // direct call if( INS_IsDirectBranchOrCall(tail) ) { // get target address ADDRINT target = Target2FunAddr(INS_DirectBranchOrCallTargetAddress(tail)); #if DEBUG_INS printf(" > Direct call to %s\n", Target2RtnName(target).c_str()); #endif // instrument direct call: target address determined here if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCall, IARG_FAST_ANALYSIS_CALL, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } // indirect call: target address determined at call time else { #if DEBUG_INS printf(" > Indirect call\n"); #endif // instrument indirect call if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } continue; } if ( INS_IsRet(tail) ) { #if DEBUG_INS printf(" > return\n"); #endif if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturnBuf, IARG_FAST_ANALYSIS_CALL, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturn, IARG_FAST_ANALYSIS_CALL, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } }
Routine Trace::routine (void) const { return TRACE_Rtn (this->trace_); }
int trace_rtn (lua_State *L) { TRACE* v1 = check_trace(L,1); RTN_to_lua(L, TRACE_Rtn(*v1)); return 1; }