VOID Image(IMG img, void *v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); numRtnsFoundInImageCallback++; INS ins = RTN_InsHeadOnly(rtn); if (INS_Invalid() == ins) { // no instruction found - assert that RTN_InsHead(rtn) also doesn't find any INS ASSERTX (INS_Invalid() == RTN_InsHead(rtn)); RTN_Close(rtn); continue; } if (INS_HasFallThrough(ins)) { ADDRINT insAddress = INS_Address(ins); numRtnsInstrumentedFromImageCallback++; RTN_InsertCall( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn), IARG_ADDRINT, RTN_Address(rtn), IARG_END); INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_END); INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_END); ins = RTN_InsHead(rtn); ASSERTX(INS_Invalid() != ins); ASSERTX(INS_Address(ins)==insAddress); INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHead), IARG_ADDRINT, insAddress, IARG_END); INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHead), IARG_ADDRINT, insAddress, IARG_END); } RTN_Close(rtn); } } }
VOID ImageLoad(IMG img, VOID *v) { printf ("ImageLoad %s\n", IMG_Name(img).c_str()); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (strcmp(RTN_Name(rtn).c_str(), "_dl_debug_state") == 0) { printf (" RTN %s at %p\n", RTN_Name(rtn).c_str(), reinterpret_cast<void *>(RTN_Address(rtn))); printf (" ** found _dl_debug_state\n"); dl_debug_state_Addr = RTN_Address(rtn); justFoundDlDebugState = TRUE; } else if (justFoundDlDebugState) { printf (" RTN %s at %p\n", RTN_Name(rtn).c_str(), reinterpret_cast<void *>(RTN_Address(rtn))); dl_debug_state_AddrEnd = RTN_Address(rtn); justFoundDlDebugState = FALSE; printf (" ** _dl_debug_state from %p to %p\n", reinterpret_cast<void *>(dl_debug_state_Addr), reinterpret_cast<void *>(dl_debug_state_AddrEnd)); } } } }
// When an image is loaded, check for a MyAlloc function VOID Image(IMG img, VOID *v) { //fprintf(stderr, "Loading %s\n",IMG_name(img)); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { //fprintf(stderr, " sec %s\n", SEC_name(sec).c_str()); for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { //fprintf(stderr, " rtn %s\n", RTN_Name(rtn).c_str()); if (RTN_Name(rtn) == STRESSTEST_FN_NAME) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)StressTestConstContextToolFunc, IARG_FUNCARG_ENTRYPOINT_REFERENCE, 0, IARG_FUNCARG_ENTRYPOINT_REFERENCE, 1, IARG_FUNCARG_ENTRYPOINT_REFERENCE, 2, IARG_FUNCARG_ENTRYPOINT_REFERENCE, 3, IARG_FUNCARG_ENTRYPOINT_REFERENCE, 4, IARG_FUNCARG_ENTRYPOINT_REFERENCE, 5, IARG_RETURN_IP, // address of inst after caller IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_VALUE, REG_THREAD_ID, IARG_CONST_CONTEXT, IARG_END); RTN_Close(rtn); } } } }
// When an image is loaded, check for a MyAlloc function VOID Image(IMG img, VOID *v) { //fprintf(stderr, "Loading %s\n",IMG_name(img)); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { //fprintf(stderr, " sec %s\n", SEC_name(sec).c_str()); for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { //fprintf(stderr, " rtn %s\n", RTN_name(rtn).c_str()); // Swizzle the return value of MyAlloc if (RTN_Name(rtn) == "MyAlloc") { RTN_Open(rtn); fprintf(stderr, "Adding Swizzle to %s\n", "MyAlloc"); RTN_InsertCall(rtn, IPOINT_AFTER, AFUNPTR(SwizzleRef), IARG_FUNCRET_EXITPOINT_REFERENCE, IARG_END); RTN_Close(rtn); } if (RTN_Name(rtn) == "MyFree") { RTN_Open(rtn); fprintf(stderr, "Adding SwizzleArg to %s\n", "MyFree"); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(UnswizzleRef), IARG_FUNCARG_ENTRYPOINT_REFERENCE, 0, IARG_END); RTN_Close(rtn); } } } }
VOID Image(IMG img, VOID * v) { if ( (IMG_Name(img).find("ntdll.dll") != string::npos) || (IMG_Name(img).find("NTDLL.DLL") != string::npos) || (IMG_Name(img).find("NTDLL.dll") != string::npos) ) { return; } if ( (IMG_Name(img).find("MSVCR") != string::npos) || (IMG_Name(img).find("msvcr") != string::npos) ) { // _NLG_Return2 causes problems return; } for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (RTN_Name(rtn).find(".text") != string::npos) { continue; } BOOL canBeProbed = RTN_IsSafeForProbedInsertion(rtn); if (canBeProbed && RTN_Name(rtn)[0] != '_' && RTN_Name(rtn)[0] != '.') { RTN_InsertCallProbed( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn), IARG_PTR, RTN_Name(rtn).c_str(), IARG_TSC, IARG_END); } } } }
// Writes the image load event to the file "imgLog" static void LogImageLoad(IMG img, void *v) { // Ensure that we can't overflow when we read it back. ASSERTX (IMG_Name(img).length() < MAX_FILENAME_LENGTH); ADDRESS_RANGE range = FindImageTextMargin(img); // Log the data needed to restore it fprintf(imgLog, "L '%s' %llx %lx %llx %d \n", IMG_Name(img).c_str(), (unsigned long long)range._low, (long)(range._high - range._low), (unsigned long long)IMG_LoadOffset(img), (int)IMG_IsMainExecutable(img)); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { if (SEC_Type(sec) != SEC_TYPE_EXEC) { continue; } for (RTN rtn=SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (RTN_IsArtificial(rtn)) { continue; } fprintf(imgLog, "\t'%s' %llx\n", RTN_Name(rtn).c_str(), (unsigned long long)RTN_Address(rtn)); } } fprintf(imgLog, "%s", END_RTN_LIST); }
RTN RTN_FindLoop(IMG img, string rtn_name) { SEC temp=IMG_SecHead(img); while(SEC_Valid(temp)) { //we pick only executable code segment if(SEC_Type(temp)==SEC_TYPE_EXEC){ RTN myrtn=SEC_RtnHead(temp); DBG_TRACE("RTNs to be instrumented"); while(RTN_Valid(myrtn)) { cerr<<RTN_Name(myrtn)<<endl; if(RTN_Name(myrtn)==rtn_name) { cerr<<"Rtn Found:"<<rtn_name<<endl; return myrtn; } myrtn=RTN_Next(myrtn); } } temp=SEC_Next(temp); } RTN empty; return empty; }
VOID Image(IMG img, VOID * v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if( INS_IsPredicated(ins) ) GlobalStatsStatic.predicated[ INS_Category(ins) ]++; else GlobalStatsStatic.unpredicated[ INS_Category(ins) ]++; } RTN_Close(rtn); } } if( KnobProfileStaticOnly.Value() ) { Fini(0,0); exit(0); } }
PyObject* Python_RTN_Next(PyObject* self, PyObject* args) { PyObject* x; PyArg_ParseTuple(args, "L", &x); RTN x_object = *(RTN*) x; RTN* rtn_return = (RTN*) malloc(sizeof(RTN)); *rtn_return = RTN_Next(x_object); return Py_BuildValue("L", rtn_return); }
void DoReplacementFunc( IMG img, char * funcName) { RTN rtnToReplace; printf ("Image %s\n", IMG_Name(img).c_str()); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { printf (" Rtn: %s %s\n", RTN_Name(rtn).c_str(), funcName); if (strstr( RTN_Name(rtn).c_str(), funcName)) { //printf (" found\n"); foundFunc = true; rtnToReplace = rtn; break; } } if (foundFunc) { break; } } if (!foundFunc) { return; } printf ( "Found %s %x\n", funcName, RTN_Address(rtnToReplace)); // commented out so that absence of pdb file will not cause failure if (RTN_IsSafeForProbedReplacement(rtnToReplace)) { printf ( "RTN_ReplaceSignatureProbed on %s\n", funcName); foundFunc = true; PROTO protoOfStdCallFunction1ToBeReplacedByPin = PROTO_Allocate( PIN_PARG(void *), CALLINGSTD_STDCALL, "protoOfStdCallFunction1ToBeReplacedByPin", PIN_PARG(char), PIN_PARG(int), PIN_PARG(char), PIN_PARG(int), PIN_PARG_END() ); RTN_ReplaceSignatureProbed(rtnToReplace, AFUNPTR(ReplacementFunc), IARG_PROTOTYPE, protoOfStdCallFunction1ToBeReplacedByPin, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_FUNCARG_ENTRYPOINT_VALUE, 3, IARG_END); PROTO_Free( protoOfStdCallFunction1ToBeReplacedByPin ); } }
VOID Image(IMG img, void * v) { cout << "IMG = " << IMG_Name(img) << endl; for( SEC sec=IMG_SecHead(img); SEC_Valid(sec) ; sec=SEC_Next(sec) ) { if ( SEC_IsExecutable(sec) ) { for( RTN rtn=SEC_RtnHead(sec); RTN_Valid(rtn) ; rtn=RTN_Next(rtn) ) Routine(rtn,v); } } }
// Pin calls this function every time a new img is loaded VOID ImageLoad(IMG img, VOID *v) { if (!IMG_IsMainExecutable(img)) return; printf("%s loaded\n", IMG_Name(img).c_str()); fflush(stdout); ADDRINT imageBase = IMG_LowAddress(img); WINDOWS::PIMAGE_DATA_DIRECTORY pExpDir = GetExportDirectory(imageBase); if ((pExpDir == 0) || (pExpDir->Size == 0)) { // Failure: Executable image lacks export directory. printf("ERROR: No export directory in executable image\n"); fflush(stdout); exit(3); } ADDRINT exportBase = imageBase + pExpDir->VirtualAddress; // First check that bytes in export directory range do not belong to a RTN for (ADDRINT addr = exportBase; addr < exportBase + pExpDir->Size; ++addr) { if (RTN_FindByAddress(addr) != RTN_Invalid()) { // Test failure. Byte in export directory belongs to a RTN. printf("ERROR: Data from export directory included in RTN\n"); fflush(stdout); exit(1); } } // Second check RTN size. RTN range should not overlap with export directory range. for (SEC sec = IMG_SecHead(img); sec != SEC_Invalid(); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); rtn != RTN_Invalid(); rtn = RTN_Next(rtn)) { if (((RTN_Address(rtn) <= exportBase) && (RTN_Address(rtn) + RTN_Size(rtn) > exportBase)) || ((RTN_Address(rtn) > exportBase) && (exportBase + pExpDir->Size > RTN_Address(rtn)))) { // Test failure. RTN overlaps with export directory. printf("ERROR: RTN overlaps with export directory\n"); fflush(stdout); exit(2); } } } return; }
VOID Image(IMG img, VOID * v) { if (strstr (IMG_Name(img).c_str(), "flags_at_analysis_app")==NULL) { return; } for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { // Prepare for processing of RTN, an RTN is not broken up into BBLs, // it is merely a sequence of INSs RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_Opcode(ins)==XED_ICLASS_POPF || INS_Opcode(ins)==XED_ICLASS_POPFD || INS_Opcode(ins)==XED_ICLASS_POPFQ) { // popf is the marker printf ("found popf in rtn %s\n", RTN_Name(rtn).c_str()); if (!INS_Valid(INS_Next(ins)) || !INS_Valid(INS_Next(INS_Next(ins)))) { printf ("wrong popf marker found\n"); exit (-1); } printf ("next ins should be cmp al, 0x81 it is %s\n", INS_Disassemble(INS_Next(ins)).c_str()); printf ("next ins should be xor ecx, ecx it is %s\n", INS_Disassemble(INS_Next(INS_Next(ins))).c_str()); // Insert analysis calls to read the value of the flags register just after the cmp al, 0x81 - the OF flag should be set INS_InsertIfCall(INS_Next(INS_Next(ins)), IPOINT_BEFORE, (AFUNPTR)IfReturnTrue, IARG_INST_PTR, IARG_END); INS_InsertThenCall(INS_Next(INS_Next(ins)), IPOINT_BEFORE, (AFUNPTR)ThenFunc, IARG_REG_VALUE, REG_GFLAGS, IARG_END); INS_InsertCall(INS_Next(INS_Next(ins)), IPOINT_BEFORE, (AFUNPTR)AnalysisFunc, IARG_REG_VALUE, REG_GFLAGS, IARG_END); } } // to preserve space, release data associated with RTN after we have processed it RTN_Close(rtn); } } }
VOID Image(IMG img, void *v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); RTN_InsertCall( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn1), IARG_PTR, RTN_Name(rtn).c_str(), IARG_TSC, IARG_INST_PTR , IARG_END); RTN_InsertCall( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn2), IARG_FAST_ANALYSIS_CALL, IARG_PTR, RTN_Name(rtn).c_str(), IARG_TSC, IARG_INST_PTR , IARG_END); RTN_Close(rtn); } } }
// Grab some detailed information about the image, the number of SECs and RTNs static VOID CountImageSecsAndRtns (IMG img, int *nSecs, int *nRtns) { int numSecs = 0; int numRtns = 0; for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { numSecs++; for (RTN rtn=SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { numRtns++; } } *nSecs = numSecs; *nRtns = numRtns; }
VOID Image(IMG img, VOID * v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { sandbox.RecordIns(ins); } RTN_Close(rtn); } } }
// Prints all RTNs in a given IMG to the trace file. // We use that file later on to see if the record and replay went the same static VOID PrintRTNs(IMG img) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { if (SEC_Type(sec) != SEC_TYPE_EXEC) { continue; } for (RTN rtn=SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (RTN_IsArtificial(rtn)) { continue; } fprintf(trace, "Function '%s' loaded at %llx\n", RTN_Name(rtn).c_str(), (unsigned long long)RTN_Address(rtn)); } } }
VOID Image(IMG img, VOID *v) { if(IMG_IsMainExecutable(img)) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (RTN_Name(rtn) == "_NotifyPinAfterMmap" || RTN_Name(rtn) == "NotifyPinAfterMmap") { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)MmapAfter, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_Close(rtn); } } } } }
static VOID imageLoad(IMG img, VOID *v) { // Just instrument the main image. if (!IMG_IsMainExecutable(img)) return; for (SEC sec=IMG_SecHead(img); SEC_Valid(sec); sec=SEC_Next(sec)) { for (RTN rtn=SEC_RtnHead(sec); RTN_Valid(rtn); rtn=RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins=RTN_InsHead(rtn); INS_Valid(ins); ins=INS_Next(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)incCount, IARG_END); } RTN_Close(rtn); } } }
// When an image is loaded, check for a MyAlloc function VOID Image(IMG img, VOID *v) { //fprintf(stderr, "Loading %s\n",IMG_name(img)); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { //fprintf(stderr, " sec %s\n", SEC_name(sec).c_str()); for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { //fprintf(stderr, " rtn %s\n", RTN_name(rtn).c_str()); // Swizzle the return value of MyAlloc #if defined(TARGET_MAC) if (RTN_Name(rtn) == "_MyAlloc") #else if (RTN_Name(rtn) == "MyAlloc") #endif { RTN_Open(rtn); fprintf(stderr, "Adding swizzle to %s\n", "MyAlloc"); RTN_InsertCall(rtn, IPOINT_AFTER, AFUNPTR(Swizzle), IARG_REG_VALUE, REG_GAX, IARG_RETURN_REGS, REG_GAX, IARG_END); RTN_Close(rtn); } #if defined(TARGET_MAC) if (RTN_Name(rtn) == "_MyFree") #else if (RTN_Name(rtn) == "MyFree") #endif { RTN_Open(rtn); fprintf(stderr, "Adding unswizzle to %s\n", "MyFree"); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(SwizzleArg), IARG_FUNCARG_ENTRYPOINT_REFERENCE, 0, IARG_END); RTN_Close(rtn); } } } }
// Count the number of RTN objects inside an IMG static int CountImageRtns(IMG img) { int numRtns = 0; for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { if (SEC_Type(sec) != SEC_TYPE_EXEC) { continue; } for (RTN rtn=SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (RTN_IsArtificial(rtn)) { continue; } numRtns++; } } return numRtns; }
VOID Image(IMG img, VOID *v) { #ifdef HEAP // Instrument the malloc() and free() functions. Print the input argument // of each malloc() or free(), and the return value of malloc(). // // 1. Find the malloc() function. RTN mallocRtn = RTN_FindByName(img, MALLOC); if (RTN_Valid(mallocRtn)) { RTN_Open(mallocRtn); // Instrument malloc() to print the input argument value and the return value. RTN_InsertCall(mallocRtn, IPOINT_BEFORE, (AFUNPTR)AllocSize, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_InsertCall(mallocRtn, IPOINT_AFTER, (AFUNPTR)AllocAddress, IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); RTN_Close(mallocRtn); } // 2. Find the free() function. RTN freeRtn = RTN_FindByName(img, FREE); if (RTN_Valid(freeRtn)) { RTN_Open(freeRtn); // Instrument free() to print the input argument value. RTN_InsertCall(freeRtn, IPOINT_BEFORE, (AFUNPTR)DeallocAddress, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_Close(freeRtn); } #endif #ifdef STACK // 3. Visit all routines to collect frame size for( SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec) ) { for( RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn) ) { RTN_Open(rtn); // collect user functions as well as their addresses ADDRINT fAddr = RTN_Address(rtn); string szFunc = RTN_Name(rtn); g_hAddr2Name[fAddr] = szFunc; //cerr << fAddr << ":\t" << szFunc << endl; //bool bFound = false; for(INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins) ) { // collecting stack size according to "SUB 0x20, %esp" or "ADD 0xffffffe0, %esp" if( INS_Opcode(ins) == XED_ICLASS_SUB && INS_OperandIsReg(ins, 0 ) && INS_OperandReg(ins, 0) == REG_STACK_PTR && INS_OperandIsImmediate(ins, 1) ) { int nOffset = INS_OperandImmediate(ins, 1); if(nOffset < 0 ) { nOffset = -nOffset; } g_hFunc2FrameSize[fAddr] = nOffset; //bFound = true; break; } if( INS_Opcode(ins) == XED_ICLASS_ADD && INS_OperandIsReg(ins, 0 ) && INS_OperandReg(ins, 0) == REG_STACK_PTR && INS_OperandIsImmediate(ins, 1) ) { int nOffset = INS_OperandImmediate(ins, 1); if(nOffset < 0 ) { nOffset = -nOffset; } g_hFunc2FrameSize[fAddr] = nOffset; //bFound = true; break; } } //if( !bFound ) // g_hFunc2FrameSize[fAddr] = 0; RTN_Close(rtn); } } #endif }
/* ===================================================================== */ VOID Image(IMG img, VOID *v){ for (UINT16 i = 0; i < n_excluded_lib_names; i++) { if (IMG_Name(img).find(excluded_lib_names[i]) != string::npos){ cout << "Excluded module: " << IMG_Name(img) << endl; return; } } for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)){ for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { // Avoid instrumenting the instrumentation if (!INS_IsOriginal(ins)) continue; if(!SeqProgram) { if ((INS_IsMemoryWrite(ins) || INS_IsMemoryRead(ins)) && INS_HasFallThrough(ins)) { if (INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && !INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYREAD_EA, IARG_ADDRINT, 0, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && !INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_ADDRINT, 0, IARG_ADDRINT, 0, IARG_INST_PTR, IARG_END); } else if (!INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_ADDRINT, 0, IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_INST_PTR, IARG_END); } else if (!INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && !INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_ADDRINT, 0, IARG_MEMORYREAD_EA, IARG_ADDRINT,0, IARG_INST_PTR, IARG_END); } else { //not a memory opeartion ASSERTX(0); } } } else { if(INS_IsBranch(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessBranch, IARG_BRANCH_TAKEN, IARG_INST_PTR, IARG_END); } } } RTN_Close(rtn); } } }
int rtn_next (lua_State *L) { RTN* v1 = check_rtn(L,1); RTN_to_lua(L, RTN_Next(*v1)); return 1; }
int main(INT32 argc, CHAR **argv) { PIN_InitSymbols(); if( PIN_Init(argc,argv) ) { return Usage(); } IMG img = IMG_Open(KnobInputFile); if (!IMG_Valid(img)) { std::cout << "Could not open " << KnobInputFile.Value() << endl; exit(1); } std::cout << hex; rtnInternalRangeList.clear(); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { std::cout << "Section: " << setw(8) << SEC_Address(sec) << " " << SEC_Name(sec) << endl; for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { std::cout << " Rtn: " << setw(8) << hex << RTN_Address(rtn) << " " << RTN_Name(rtn) << endl; string path; INT32 line; PIN_GetSourceLocation(RTN_Address(rtn), NULL, &line, &path); if (path != "") { std::cout << "File " << path << " Line " << line << endl; } RTN_Open(rtn); if (!INS_Valid(RTN_InsHead(rtn))) { RTN_Close(rtn); continue; } RTN_INTERNAL_RANGE rtnInternalRange; rtnInternalRange.start = INS_Address(RTN_InsHead(rtn)); rtnInternalRange.end = INS_Address(RTN_InsHead(rtn)) + INS_Size(RTN_InsHead(rtn)); INS lastIns = INS_Invalid(); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { std::cout << " " << setw(8) << hex << INS_Address(ins) << " " << INS_Disassemble(ins) << endl; if (INS_Valid(lastIns)) { if ((INS_Address(lastIns) + INS_Size(lastIns)) == INS_Address(ins)) { rtnInternalRange.end = INS_Address(ins)+INS_Size(ins); } else { rtnInternalRangeList.push_back(rtnInternalRange); std::cout << " rtnInternalRangeList.push_back " << setw(8) << hex << rtnInternalRange.start << " " << setw(8) << hex << rtnInternalRange.end << endl; // make sure this ins has not already appeared in this RTN for (vector<RTN_INTERNAL_RANGE>::iterator ri = rtnInternalRangeList.begin(); ri != rtnInternalRangeList.end(); ri++) { if ((INS_Address(ins) >= ri->start) && (INS_Address(ins)<ri->end)) { std::cout << "***Error - above instruction already appeared in this RTN\n"; std::cout << " in rtnInternalRangeList " << setw(8) << hex << ri->start << " " << setw(8) << hex << ri->end << endl; exit (1); } } rtnInternalRange.start = INS_Address(ins); rtnInternalRange.end = INS_Address(ins) + INS_Size(ins); } } lastIns = ins; } RTN_Close(rtn); rtnInternalRangeList.clear(); } } IMG_Close(img); }
VOID instrumentImage( IMG img, VOID *v ) { for ( SEC sec = IMG_SecHead( img ); SEC_Valid( sec ); sec = SEC_Next( sec ) ) { for ( RTN rtn = SEC_RtnHead( sec ); RTN_Valid( rtn ); rtn = RTN_Next( rtn ) ) { const char *rtnName = RTN_Name( rtn ).c_str(); if ( strstr( rtnName, "__parsec_roi_begin" ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) setStartReached, IARG_THREAD_ID, IARG_END ); RTN_Close( rtn ); } else if ( strstr( rtnName, "__parsec_roi_end" ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) setEndReached, IARG_THREAD_ID, IARG_END ); RTN_Close( rtn ); } else if ( RTN_Name( rtn ) == "malloc" ) { // in g++, new does not call malloc() RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeMalloc, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // size requested IARG_END ); RTN_InsertCall( rtn, IPOINT_AFTER, (AFUNPTR) afterMalloc, IARG_THREAD_ID, IARG_FUNCRET_EXITPOINT_VALUE, // pointer to allocation IARG_END ); RTN_Close( rtn ); } else if ( RTN_Name( rtn ) == "_Znwm" ) { // g++'s new RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeMalloc, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // size requested IARG_END ); RTN_InsertCall( rtn, IPOINT_AFTER, (AFUNPTR) afterMalloc, IARG_THREAD_ID, IARG_FUNCRET_EXITPOINT_VALUE, // pointer to allocation IARG_END ); RTN_Close( rtn ); } else if ( RTN_Name( rtn ) == "free" ) { // in g++, delete does not call free() RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeFree, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // pointer to free IARG_END ); RTN_Close( rtn ); } else if ( RTN_Name( rtn ) == "_ZdlPv" ) { // g++'s delete RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeFree, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // pointer to free IARG_END ); RTN_Close( rtn ); } else if ( strstr( rtnName, "pthread_self" ) ) { assert( RTN_Valid(rtn) ); realPthreadSelf = (AFUNPTR) RTN_Address( rtn ); } else if ( strstr( rtnName, "pthread_create" ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforePthreadCreate, IARG_THREAD_ID, // IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // the pthread_t* IARG_END ); RTN_InsertCall( rtn, IPOINT_AFTER, (AFUNPTR) afterPthreadCreate, IARG_THREAD_ID, IARG_END ); RTN_Close( rtn ); } else if ( strstr( rtnName, "pthread_join" ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeJoin, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END ); RTN_InsertCall( rtn, IPOINT_AFTER, (AFUNPTR) afterJoin, IARG_THREAD_ID, IARG_END ); RTN_Close( rtn ); } else if ( isLikeLockAcquire( rtnName ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeLockAcquire, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END ); RTN_InsertCall( rtn, IPOINT_AFTER, (AFUNPTR) afterLockAcquire, IARG_THREAD_ID, IARG_END ); RTN_Close( rtn ); } else if ( strstr( rtnName, "pthread_mutex_trylock" ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeTrylock, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END ); RTN_InsertCall( rtn, IPOINT_AFTER, (AFUNPTR) afterTrylock, IARG_THREAD_ID, IARG_FUNCRET_EXITPOINT_VALUE, IARG_END ); RTN_Close( rtn ); } else if ( isLikeLockRelease( rtnName ) ) { RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) beforeLockRelease, IARG_THREAD_ID, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END ); RTN_Close( rtn ); } else { // see threadBegin() for why we need to instrument all function calls RTN_Open( rtn ); RTN_InsertCall( rtn, IPOINT_BEFORE, (AFUNPTR) startFunctionCall, IARG_THREAD_ID, IARG_CONTEXT, IARG_END ); RTN_Close( rtn ); } // TODO: pthread_mutex_timedlock, reader-writer locks } // for RTN } // for SEC } // end instrumentImage()
VOID Image(IMG img, VOID *v) { // Find main. We won't do anything before main starts. RTN rtn = RTN_FindByName(img, "main"); if (RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)callBeforeMain, IARG_END); // RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)callAfterMain, IARG_END); RTN_Close(rtn); } // iterate all rtn for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { // printf (" Rtn: %s\n", RTN_Name(rtn).c_str()); RTN_Open(rtn); const char * rtnName = StripPath(RTN_Name(rtn).c_str()); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)RTNEntry, IARG_ADDRINT, rtnName, IARG_END); RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)RTNExit, IARG_ADDRINT, rtnName, IARG_END); RTN_Close(rtn); } } // Instrument the malloc() and free() functions. Print the input argument // of each malloc() or free(), and the return value of malloc(). // // Find the malloc() function. RTN mallocRtn = RTN_FindByName(img, MALLOC); if (RTN_Valid(mallocRtn)) { RTN_Open(mallocRtn); const char * imageName = StripPath(IMG_Name(SEC_Img(RTN_Sec(mallocRtn))).c_str()); // Instrument malloc() to print the input argument value and the return value. RTN_InsertCall(mallocRtn, IPOINT_BEFORE, (AFUNPTR)MallocBefore, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_ADDRINT, imageName, IARG_END); RTN_InsertCall(mallocRtn, IPOINT_AFTER, (AFUNPTR)MallocAfter, IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); RTN_Close(mallocRtn); } // Find the free() function. RTN freeRtn = RTN_FindByName(img, FREE); if (RTN_Valid(freeRtn)) { RTN_Open(freeRtn); // Instrument free() to print the input argument value. RTN_InsertCall(freeRtn, IPOINT_BEFORE, (AFUNPTR)FreeBefore, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_Close(freeRtn); } }
VOID PrintUntouchedRanges(SEC sec) { // Make a bool vector big enough to describe the whole section, 1 bool per byte vector<bool> touched(SEC_Size(sec)); // Put the rtn's that are touched in a set set<RTN> rtnSet; // Mark the ranges for bbls that have been executed for (list<const BBLSTATS*>::const_iterator bi = statsList.begin(); bi != statsList.end(); bi++) { const BBLSTATS * stats = *bi; // Is this bbl contained in the section? if (stats->_start < SEC_Address(sec) || stats->_start >= SEC_Address(sec) + SEC_Size(sec)) continue; // Is the bbl executed? if (!stats->_executed) continue; RTN rtn = RTN_FindByAddress(stats->_start); if (RTN_Valid(rtn)) rtnSet.insert(rtn); // Mark all the bytes of the bbl as executed for (ADDRINT i = stats->_start - SEC_Address(sec); i < stats->_start + stats->_size - SEC_Address(sec); i++) { ASSERTX(i < SEC_Size(sec)); touched[i] = true; } } // Print the routines that are not touched out << " Routines that are not executed" << endl; for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { if (rtnSet.find(rtn) == rtnSet.end()) { out << " " << RTN_Name(rtn) << endl; } } // Print the ranges of untouched addresses out << " Code ranges that are not executed" << endl; string rtnName = ""; for (UINT32 i = 0; i < SEC_Size(sec);) { // Find the first not touched address while(touched[i]) { i++; if (i == SEC_Size(sec)) return; } UINT32 start = i; // Find the first touched address while(!touched[i] && i < SEC_Size(sec)) i++; ADDRINT startAddress = SEC_Address(sec) + start; // Print the rtn name, if it has changed IMG img = IMG_FindByAddress(startAddress); string imgName = (IMG_Valid(img) ? IMG_Name(img) : "InvalidImg"); RTN rtn = RTN_FindByAddress(startAddress); string newName = (RTN_Valid(rtn) ? RTN_Name(rtn) : "InvalidRtn"); if (rtnName != newName) { out << " Image: " << imgName << " Rtn: " << newName << endl; rtnName = newName; } out << " " << SEC_Address(sec) + start << ":" << SEC_Address(sec) + i - 1 << endl; } }
VOID ImageLoad(IMG img, VOID *v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec) ) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn) ) { string rtnName = RTN_Name(rtn); if (rtnName.find("method") != string::npos || rtnName.find("foo") != string::npos || rtnName.find("my_operator") != string::npos) { // The tested application has class "A" with interface "method" // We just check that A::method is successfully demangled string demangledName = PIN_UndecorateSymbolName(rtnName, UNDECORATION_COMPLETE); string demangledNameNoParams = PIN_UndecorateSymbolName(rtnName, UNDECORATION_NAME_ONLY); out << "Mangled name: " << rtnName << endl; out << "Full demangled name: " << demangledName << endl; out << "Demangled name w/o parameters: " << demangledNameNoParams << endl; BOOL matched = FALSE; for (UINT32 i=0; i<sizeof(testNames)/sizeof(testNames[0]); i++) { if (demangledName == testNames[i].fullName && demangledNameNoParams == testNames[i].noArgsName) { matched = TRUE; break; } } if (!matched) { cout << "Error in demangling: " << endl; cout << "Mangled name: " << rtnName << endl; cout << "Demangled name: " << demangledName << endl; cout << "Demangled name, no parameters: " << demangledNameNoParams << endl; exit(-1); } continue; } if (rtnName.find("@@") != string::npos) { // Check C and C++ names demangling with version (Linux) // Like // _ZNSt11char_traitsIcE2eqERKcS2_@@GLIBCXX_3.4.5 // localeconv@@GLIBC_2.2 string name = PIN_UndecorateSymbolName(rtnName, UNDECORATION_COMPLETE); if (rtnName.find("_Z") == 0) { out << "C++ name with version: " << rtnName << endl; out << "Demangled name: " << name << endl; } else { out << "C name with version: " << rtnName << endl; out << "Demangled name: " << name << endl; } if (name.find("@@") != string::npos) { printf("Error: undecorated name should not include \"@@\"\n"); exit(-1); } continue; } // Otherwise just demangle the name both ways but normally don't bother to print them. // We can't easily tell what the results should be, but throwing a lot more // names at our demangler must be a good thng to do, and this should include // all the names from the standard C++ runtime, is a reasonable stress test. string complete = PIN_UndecorateSymbolName(rtnName, UNDECORATION_COMPLETE); string nameOnly = PIN_UndecorateSymbolName(rtnName, UNDECORATION_NAME_ONLY); if (KnobVerbose) { out << rtnName << " => " << endl; out << " " << complete << endl; out << " " << nameOnly << endl; } } } }
void report_section_structure(SEC sec, int depth ){ BOOL S1 = LEVEL_PINCLIENT::SEC_Valid (sec); string S2 = LEVEL_PINCLIENT::SEC_Name (sec); SEC_TYPE S3 = LEVEL_PINCLIENT::SEC_Type (sec); BOOL S4 = LEVEL_PINCLIENT::SEC_Mapped (sec); ADDRINT S5 = LEVEL_PINCLIENT::SEC_Address (sec); BOOL S6 = LEVEL_PINCLIENT::SEC_IsReadable (sec); BOOL S7 = LEVEL_PINCLIENT::SEC_IsWriteable (sec); BOOL S8 = LEVEL_PINCLIENT::SEC_IsExecutable (sec); USIZE S9 = LEVEL_PINCLIENT::SEC_Size (sec); char sec_type[128]; int k; switch ( S3 ){ case SEC_TYPE_REGREL : strcpy( sec_type, "relocations" ); break; case SEC_TYPE_DYNREL: strcpy( sec_type, "dynamic-relocations" ); break; case SEC_TYPE_EXEC: strcpy( sec_type, "contains-code" ); break; case SEC_TYPE_DATA: strcpy( sec_type, "contains-initialized-data" ); break; case SEC_TYPE_LSDA: strcpy( sec_type, "old-exception_info-obsolete" ); break; case SEC_TYPE_BSS: strcpy( sec_type, "contains-uninitialized-data" ); break; case SEC_TYPE_LOOS: strcpy( sec_type, "OS-specific" ); break; case SEC_TYPE_USER: strcpy( sec_type, "Application-specific" ); break; default: strcpy( sec_type, "UNKNOWN" ); break; } for ( k = 0; k< depth ; k ++ ) TraceFile << "\t" ; TraceFile << "<SECTION>S1:" << S1 << " S2:" << S2 << " S3:" << S3 << " S4:" << S4 << " S5:" << S5 << " S6:" << S6 << " S7:" << S7 << " S8:" << S8 << " S9:" << S9 << " Stype:" << sec_type << endl; for( RTN rtn= SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn) ){ report_routine_structure( rtn, depth + 1 ); string R1 = LEVEL_PINCLIENT::RTN_Name (rtn ); /* string undFuncName = PIN_UndecorateSymbolName(SYM_Name(R2), UNDECORATION_NAME_ONLY);*/ //RTN allocRtn = RTN_FindByAddress(IMG_LowAddress(img) + SYM_Value(sym)); if (R1 == "_printf"){ /* have to check '__' entry for symbols */ RTN_Open( rtn ); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)pre_printf, IARG_ADDRINT, "THECALL:::printf", IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_END); RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)post_printf, IARG_ADDRINT, "THECALL:::printf", IARG_FUNCRET_EXITPOINT_VALUE, //REFERENCE, IARG_END); RTN_Close( rtn ); printf( ">>>>>>>>>>>>>>>>>>>>>>>> printf" );} if (R1 == "_fopen"){ /* have to check '__' entry for symbols */ RTN_Open( rtn ); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)pre_fopen, IARG_ADDRINT, "THECALL:::fopen", IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_END); RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)post_fopen, IARG_ADDRINT, "THECALL:::fopen", IARG_FUNCRET_EXITPOINT_VALUE, //REFERENCE, IARG_END); RTN_Close( rtn ); printf( ">>>>>>>>>>>>>>>>>>>>>>>> fopen" );} } for ( k = 0; k< depth ; k ++ ) TraceFile << "\t" ; TraceFile << "</SECTION>" << endl; }