static void GetThreadCount(ADDRINT threadCount) { // Capture the number of worker threads in the application. // This is the number of threads that will execute DoLockTest(). // RunningWorkers = threadCount; if (TestType == TEST_SEMAPHORE) { if (threadCount != 2) { std::cout << "Test 'semaphore' requires exactly two worker threads" << std::endl; PIN_ExitProcess(1); } } if (TestType == TEST_TRYLOCKS) { if (threadCount != 1) { std::cout << "Test 'trylocks' requires exactly one worker thread" << std::endl; PIN_ExitProcess(1); } } }
static void OnExit(INT32, VOID *) { if (!instrumentedMovdqa) { fprintf (fp, "***Error tool did not instrument the movdqa instruction of DoXmm\n"); fflush (fp); PIN_ExitProcess(1); } else { fprintf (fp, "instrumented the movdqa instruction of DoXmm\n"); fflush (fp); } if (!gotOurCommand) { fprintf (fp, "***Error tool did NOT get the expected gdb command\n"); fflush (fp); PIN_ExitProcess(1); } else { fprintf (fp, "tool got the expected gdb command\n"); fflush (fp); } }
static void DoTestLockIntegrity(THREADID tid, THREAD_INFO *info, UINT32 *done) { // This test checks to see if two threads can be in the PIN_LOCK mutex // simultaneously. PIN_GetLock(&Lock, tid); THREADID owner = HasLock; HasLock = tid; if (owner != INVALID_THREADID) { std::cout << "Two theads in lock simultaneously: " << std::dec << tid << " and " << owner << std::endl; PIN_ExitProcess(1); } ATOMIC::OPS::Delay(DELAY_COUNT); HasLock = INVALID_THREADID; THREADID ret = PIN_ReleaseLock(&Lock); if (ret != tid) { std::cout << "PIN_ReleaseLock returned unexpected value " << std::dec << ret << " (expected " << tid << ")" << std::endl; PIN_ExitProcess(1); } CheckIfDone(info, done); }
static void OnExit(INT32, VOID *) { if (!GotOurCommand) { std::cerr << "Did not receive \"mycommand\"\n"; PIN_ExitProcess(1); } if (GotPinCommand) { PIN_ExitProcess(1); } }
// This function is called when the application exits VOID Fini(INT32 code, VOID *v) { if (numFpsInstrumented == 0) { fprintf (stderr, "**Error No instrumented fp instructions\n"); PIN_ExitProcess(1); } if (numFpsExecuted == 0) { fprintf (stderr, "**Error No executed fp instructions\n"); PIN_ExitProcess(1); } }
static VOID ThreadCreateCallback(THREADID tid, CONTEXT * ctxt, INT32 flags, VOID * v) { if (KnobVerbose) cerr << "Thread create callback for " << tid << "\n"; // First thread is static, we don't want to mangle it, but we do create a new thread // from the callback. if (KnobFromCallback) { ADDRINT * stack = new ADDRINT [1024]; CONTEXT context; ctxt = &context; if (!threadFunction) { cerr << "Cannot find 'doNothing()' in application\n"; PIN_ExitProcess(-1); } // Fill in sensible values for critical registers. PIN_SetContextReg(ctxt, REG_STACK_PTR,ADDRINT (&stack[1023])); PIN_SetContextReg(ctxt, REG_INST_PTR, threadFunction); PIN_SetContextReg(ctxt, REG_GFLAGS, 0); cloneThread(ctxt); } if (tid >= (MAXTHREADS-1)) { cerr << "Created all threads OK\n"; PIN_ExitProcess(0); } // First thread is created statically, we don't want to mess with it. if (tid == 0 || KnobFromCallback) return; if (!threadFunction) { cerr << "Cannot find 'doNothing()' in application\n"; PIN_ExitProcess(-1); } ADDRINT * stack = new ADDRINT [1024]; // Fill in sensible values for critical registers. PIN_SetContextReg(ctxt, REG_STACK_PTR,ADDRINT (&stack[1023])); PIN_SetContextReg(ctxt, REG_INST_PTR, ADDRINT (&threadFunction)); PIN_SetContextReg(ctxt, REG_GFLAGS, 0); }
static bool OnCommand(THREADID tid, CONTEXT *context, const std::string &cmd, std::string *reply, VOID *) { fprintf (fp, "OnCommand %s\n", cmd.c_str()); fflush (fp); if (cmd == "set_xmm3") { gotOurCommand = true; CHAR fpContextSpaceForFpConextFromPin[FPSTATE_SIZE]; FPSTATE *fpContextFromPin = reinterpret_cast<FPSTATE *>(fpContextSpaceForFpConextFromPin); PIN_GetContextFPState(context, fpContextFromPin); for (int j=0; j<16; j++) { fpContextFromPin->fxsave_legacy._xmms[3]._vec8[j] = 0x5a; } PIN_SetContextFPState(context, fpContextFromPin); CHAR fpContextSpaceForFpConextFromPin1[FPSTATE_SIZE]; fpContextFromPin = reinterpret_cast<FPSTATE *>(fpContextSpaceForFpConextFromPin1); PIN_GetContextFPState(context, fpContextFromPin); for (int j=0; j<16; j++) { if (fpContextFromPin->fxsave_legacy._xmms[3]._vec8[j] != 0x5a) { fprintf (fp, "***Error tool did not properly set xmm3\n"); fflush (fp); PIN_ExitProcess(1); } } fprintf (fp, "tool properly set xmm3\n"); fflush (fp); return true; } return false; }
static void OnExit(INT32, VOID *) { if (!instrumentedMovdqa) { fprintf (fp, "***Error tool did not instrument the movdqa instruction of DoXmm\n"); fflush (fp); PIN_ExitProcess(1); } else { fprintf (fp, "instrumented the movdqa instruction of DoXmm\n"); fflush (fp); } if (!instrumentedIpAfterMovdqa) { fprintf (fp, "***Error tool did not instrument the ret instruction after the movdqa instruction of DoXmm\n"); fflush (fp); } else { fprintf (fp, "instrumented the ret instruction after the movdqa instruction of DoXmm\n"); fflush (fp); } if (!setApplicationBreakpoint) { fprintf (fp, "***Error tool did not setApplicationBreakpoint at the ret instruction after the movdqa instruction of DoXmm\n"); fflush (fp); } else { fprintf (fp, "did setApplicationBreakpoint at the ret instruction after the movdqa instruction of DoXmm\n"); fflush (fp); } }
static VOID cloneThread(CONTEXT * ctxt) { // Should maybe use atomic increment here, but if we create a few bonus ones, it // doesn't really matter! UINT32 threadId = ++threadsCreated; if (threadId >= MAXTHREADS) return; CONTEXT localContext; if (!ctxt) { ctxt = &localContext; PIN_SetContextReg(ctxt, REG_GFLAGS, 0); } if (!PIN_SpawnApplicationThread(ctxt)) { cerr << "PIN_SpawnApplicationThread failed\n"; PIN_ExitProcess(-1); } if (KnobVerbose) cerr << "Spawned a new thread (" << threadId << ")\n"; }
VOID DebugInit(char *pFilename) { _dbgLogFd = fopen(pFilename, "w"); if(!_dbgLogFd) { PIN_WriteErrorMessage("Failed to open Debug Log File", 0, PIN_ERR_FATAL, 0); PIN_ExitProcess(1); } }
static void DoTestSemaphore(THREAD_INFO *info, UINT32 *done) { // This test assumes exactly two threads. The two threads take turns pinging // each other's semaphore. We make sure that a thread does not wake up from // the semaphore unless it is set. We also check for deadlocks due to missing // wakeups. if (info->_workerId == 0) { PIN_SemaphoreWait(&Sem1); if (!PIN_SemaphoreIsSet(&Sem1)) { std::cout << "SemaphoreWait returned, but semaphore is not set" << std::endl; PIN_ExitProcess(1); } PIN_MutexLock(&Mutex); PIN_SemaphoreClear(&Sem1); PIN_SemaphoreSet(&Sem2); PIN_MutexUnlock(&Mutex); } else { PIN_SemaphoreWait(&Sem2); if (!PIN_SemaphoreIsSet(&Sem2)) { std::cout << "SemaphoreWait returned, but semaphore is not set" << std::endl; PIN_ExitProcess(1); } PIN_MutexLock(&Mutex); PIN_SemaphoreClear(&Sem2); PIN_SemaphoreSet(&Sem1); PIN_MutexUnlock(&Mutex); } if (CheckIfDone(info, done)) { PIN_SemaphoreSet(&Sem1); PIN_SemaphoreSet(&Sem2); } }
static VOID OnFoo(CONTEXT *ctxt, THREADID tid) { if (!FoundBar) { fprintf(stderr, "Unable to find PIN_TEST_BAR()\n"); PIN_ExitProcess(1); } PIN_CallApplicationFunction(ctxt, tid, CALLINGSTD_DEFAULT, AFUNPTR(BarAddr), PIN_PARG_END()); PIN_CallApplicationFunction(ctxt, tid, CALLINGSTD_DEFAULT, AFUNPTR(BarAddr), PIN_PARG_END()); }
static void DoTestReaderWriterIntegrity(THREAD_INFO *info, UINT32 *done) { // This test checks that a "writer" thread can never hold the lock while // there is an active reader. if (info->_workerId & 1) { // Reader thread. // PIN_RWMutexReadLock(&RWMutex); ATOMIC::OPS::Increment(&ActiveReaders, 1); if (ATOMIC::OPS::Load(&IsActiveWriter)) { std::cout << "Reader got lock while there is an active writer" << std::endl; PIN_ExitProcess(1); } ATOMIC::OPS::Delay(DELAY_COUNT); ATOMIC::OPS::Increment(&ActiveReaders, -1); PIN_RWMutexUnlock(&RWMutex); } else { // Writer thread. // PIN_RWMutexWriteLock(&RWMutex); ATOMIC::OPS::Store<BOOL>(&IsActiveWriter, TRUE); if (ATOMIC::OPS::Load(&ActiveReaders) != 0) { std::cout << "Writer has lock while there are active readers" << std::endl; PIN_ExitProcess(1); } ATOMIC::OPS::Delay(DELAY_COUNT); ATOMIC::OPS::Store<BOOL>(&IsActiveWriter, FALSE); PIN_RWMutexUnlock(&RWMutex); } CheckIfDone(info, done); }
// This is done under the Pin client lock so there is no race on the global variables. VOID onThreadAttach(VOID *sigset, VOID *v) { pid_t tid = GetTid(); // The master thread's tid is the same as the pid of the entire process. if (tid == masterPid) { // This is the master thread which should be first. fprintf(generated, "3\n"); } else { // This is the second thread which should be last, therefore close the file and exit. // If this happens before the master thread then there is a problem and the test should fail. // This failure will be discovered while comparing the two files. fprintf(generated, "4\n"); fclose(generated); PIN_ExitProcess(0); } }
static void OnExit(INT32, VOID *) { if (!instrumented) { fprintf (fp, "***Error tool did not instrument the movdqa instruction of DoXmm\n"); fflush (fp); PIN_ExitProcess(1); } else { fprintf (fp, "instrumented the movdqa instruction of DoXmm\n"); fflush (fp); } }
int main(int argc, char * argv[]) { ADDRINT dummy = 0xa5a5a5a5; // Initialize pin if (PIN_Init(argc, argv)) return Usage(); OutFile.open(KnobOutputFile.Value().c_str()); // Register Instruction to be called to instrument instructions INS_AddInstrumentFunction(Instruction, 0); // Verify that the PIN API is null before registration if (PIN_GetMemoryAddressTransFunction()) { cout << "Test memory_addr_callback found PIN API callback not null before registration " << endl; PIN_ExitProcess(-1); } // Register memory callback PIN_AddMemoryAddressTransFunction(memoryCallback,(VOID*)dummy); // Verify that the PIN API is not null after registration if (!PIN_GetMemoryAddressTransFunction()) { cout << "Test memory_addr_callback found PIN API callback null after registration " << endl; PIN_ExitProcess(-1); } // Register Fini to be called when the application exits PIN_AddFiniFunction(Fini, 0); // Start the program, never returns PIN_StartProgram(); return errors; }
static void OnExit(INT32, VOID *) { if (!instrumented) { fprintf (fp, "***Error tool did not instrument the vmovdqu instruction of LoadYmm0\n"); fflush (fp); PIN_ExitProcess(1); } else { fprintf (fp, "instrumented the vmovdqu instruction of LoadYmm0\n"); fflush (fp); } fclose (fp); }
static VOID ImageLoad(IMG img, VOID *v) { outFile << IMG_Name(img) << endl; if (IMG_IsMainExecutable(img)) { RTN doReleaseRtn = RTN_FindByName(img, "DoRelease"); if (!RTN_Valid(doReleaseRtn)) { cerr << "TOOL ERROR: Unable to find the DoRelease function in the application." << endl; PIN_ExitProcess(1); } RTN_Open(doReleaseRtn); RTN_InsertCall(doReleaseRtn, IPOINT_BEFORE, AFUNPTR(OnDoRelease), IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_Close(doReleaseRtn); } }
static void OnExit(INT32, VOID *) { if (!FoundTestFunc || !FoundThreadCountFunc) { std::cout << "Couldn't find instrumentation routine(s)" << std::endl; PIN_ExitProcess(1); } // Destroy the lock variable. // switch (TestType) { case TEST_LOCK_INTEGRITY: case TEST_LOCK_STRESS: /* nothing to do */ break; case TEST_MUTEX_INTEGRITY: case TEST_MUTEX_STRESS: case TEST_MUTEX_TRYSTRESS: PIN_MutexFini(&Mutex); break; case TEST_WRITER_INTEGRITY: case TEST_WRITER_STRESS: case TEST_WRITER_TRYSTRESS: case TEST_READER_STRESS: case TEST_READER_TRYSTRESS: case TEST_RW_INTEGRITY: case TEST_RW_STRESS: case TEST_RW_TRYSTRESS: PIN_RWMutexFini(&RWMutex); break; case TEST_SEMAPHORE: PIN_SemaphoreFini(&Sem1); PIN_SemaphoreFini(&Sem2); PIN_MutexFini(&Mutex); break; case TEST_TRYLOCKS: PIN_MutexFini(&Mutex); PIN_RWMutexFini(&RWMutex); PIN_SemaphoreFini(&Sem1); break; default: ASSERTX(0); } }
REG GetScratchReg(UINT32 index) { static std::vector<REG> regs; while (index >= regs.size()) { REG reg = PIN_ClaimToolRegister(); if (reg == REG_INVALID()) { std::cerr << "*** Ran out of tool registers" << std::endl; PIN_ExitProcess(1); /* does not return */ } regs.push_back(reg); } return regs[index]; }
// This function is called when the application exits VOID Fini(INT32 code, VOID *v) { // Write to a file since cout and cerr maybe closed by the application OutFile.setf(ios::showbase); OutFile << "Count Mem Reads " << icountMemRead << endl; OutFile << "Count Mem Read2s " << icountMemRead2 << endl; OutFile << "Count Mem Writes " << icountMemWrite << endl; OutFile << "Count Mem Ops " << icountMemOp << endl; OutFile << "Count Mem callbacks " << icountMemCall << endl; OutFile << "Errors " << errors << endl; OutFile.close(); // If we have errors then terminate abnormally if (errors) { cout << "Test memory_addr_callback is terminated cause found " << errors << " errors " << endl; PIN_ExitProcess(errors); } }
static void OnSig(THREADID threadIndex, CONTEXT_CHANGE_REASON reason, const CONTEXT *ctxtFrom, CONTEXT *ctxtTo, INT32 sig, VOID *v) { switch (reason) { case CONTEXT_CHANGE_REASON_FATALSIGNAL: Out << "Received fatal signal " << StrSig(sig) << " on thread " << threadIndex << std::endl; break; case CONTEXT_CHANGE_REASON_SIGNAL: Out << "About to handle signal " << StrSig(sig) << " on thread " << threadIndex << std::endl; break; case CONTEXT_CHANGE_REASON_SIGRETURN: Out << "Returning from handler on thread " << threadIndex << std::endl; break; default: Out << "Unexpected CONTEXT_CHANGE_REASON " << reason << ", exiting the test." << std::endl; PIN_ExitProcess(1); break; } }
static void DoTestWriterIntegrity(THREADID tid, THREAD_INFO *info, UINT32 *done) { // This test checks to see if two writer threads can be in the PIN_RWMUTEX mutex // simultaneously. PIN_RWMutexWriteLock(&RWMutex); THREADID owner = HasLock; HasLock = tid; if (owner != INVALID_THREADID) { std::cout << "Two writer theads in rwmutex simultaneously: " << std::dec << tid << " and " << owner << std::endl; PIN_ExitProcess(1); } ATOMIC::OPS::Delay(DELAY_COUNT); HasLock = INVALID_THREADID; PIN_RWMutexUnlock(&RWMutex); CheckIfDone(info, done); }
int main( INT32 argc, CHAR *argv[] ) { // Initialization. PIN_InitSymbols(); PIN_Init(argc, argv); // Open the tool's output file for printing the loaded images. outFile.open(KnobImagesLog.Value().c_str()); if(!outFile.is_open() || outFile.fail()) { cerr << "TOOL ERROR: Unable to open the images file." << endl; PIN_ExitProcess(1); } // Add instrumentation. IMG_AddInstrumentFunction(ImageLoad, 0); PIN_AddApplicationStartFunction(OnAppStart, 0); PIN_AddFiniFunction(Fini, 0); // Start the program. PIN_StartProgram(); // never returns return 0; }
// Called just before the application ends VOID pin_is_detached(VOID *v) { save_instrumentation_infos(); PIN_ExitProcess(0); }
static void DoTestTryLocks(UINT32 *done) { // This is a collection of single-thread tests that make sure that the // various "try" operations succeed or fail as expected. BOOL gotLock = PIN_MutexTryLock(&Mutex); if (!gotLock) { std::cout << "Failure on uncontended PIN_MutexTryLock" << std::endl; PIN_ExitProcess(1); } gotLock = PIN_MutexTryLock(&Mutex); if (gotLock) { std::cout << "PIN_MutexTryLock was able to get a lock twice" << std::endl; PIN_ExitProcess(1); } gotLock = PIN_RWMutexTryWriteLock(&RWMutex); if (!gotLock) { std::cout << "Failure on uncontended PIN_RWMutexTryWriteLock" << std::endl; PIN_ExitProcess(1); } gotLock = PIN_RWMutexTryWriteLock(&RWMutex); if (gotLock) { std::cout << "PIN_RWMutexTryWriteLock was able to get a lock twice" << std::endl; PIN_ExitProcess(1); } gotLock = PIN_RWMutexTryReadLock(&RWMutex); if (gotLock) { std::cout << "PIN_RWMutexTryReadLock was able to get a lock when writer owns it" << std::endl; PIN_ExitProcess(1); } PIN_RWMutexUnlock(&RWMutex); gotLock = PIN_RWMutexTryReadLock(&RWMutex); if (!gotLock) { std::cout << "Failure on uncontended PIN_RWMutexTryReadLock" << std::endl; PIN_ExitProcess(1); } gotLock = PIN_RWMutexTryReadLock(&RWMutex); if (!gotLock) { std::cout << "Unable to get a reader lock twice" << std::endl; PIN_ExitProcess(1); } PIN_SemaphoreSet(&Sem1); if (!PIN_SemaphoreIsSet(&Sem1)) { std::cout << "Expected 'set' status from PIN_SemaphoreIsSet" << std::endl; PIN_ExitProcess(1); } PIN_SemaphoreClear(&Sem1); if (PIN_SemaphoreIsSet(&Sem1)) { std::cout << "Expected 'clear' status from PIN_SemaphoreIsSet" << std::endl; PIN_ExitProcess(1); } if (PIN_SemaphoreTimedWait(&Sem1, 1)) { std::cout << "Expected PIN_SemaphoreTimedWait to time-out" << std::endl; PIN_ExitProcess(1); } *done = 1; }
/* ========================================================================== */ VOID MOLECOOL_Init() { lk_init(&ildjit_lock); ifstream warm_loop_file, start_loop_file, end_loop_file; warm_loop_file.open("phase_warm_loop", ifstream::in); start_loop_file.open("phase_start_loop", ifstream::in); end_loop_file.open("phase_end_loop", ifstream::in); if (start_loop_file.fail()) { cerr << "Couldn't open loop id files: phase_start_loop" << endl; PIN_ExitProcess(1); } if (end_loop_file.fail()) { cerr << "Couldn't open loop id files: phase_end_loop" << endl; PIN_ExitProcess(1); } readLoop(start_loop_file, &start_loop, &start_loop_invocation, &start_loop_iteration); readLoop(end_loop_file, &end_loop, &end_loop_invocation, &end_loop_iteration); if (KnobWarmLLC.Value()) { if (warm_loop_file.fail()) { cerr << "Couldn't open loop id files: phase_warm_loop" << endl; cerr << "Warming from start" << endl; reached_warm_invocation = true; } else { readLoop(warm_loop_file, &warm_loop, &warm_loop_invocation, &warm_loop_iteration); } } disable_wait_signal = KnobDisableWaitSignal.Value(); coupled_waits = KnobCoupledWaits.Value(); insert_light_waits = KnobInsertLightWaits.Value(); last_time = time(NULL); cerr << warm_loop << endl; cerr << warm_loop_invocation << endl; cerr << warm_loop_iteration << endl << endl; cerr << start_loop << endl; cerr << start_loop_invocation << endl; cerr << start_loop_iteration << endl << endl; cerr << end_loop << endl; cerr << end_loop_invocation << endl; cerr << end_loop_iteration << endl << endl; if (KnobWaitsAsLoads.Value()) { wait_template_1 = wait_template_1_ld; wait_template_1_size = sizeof(wait_template_1_ld); wait_template_1_addr_offset = 1; // 1 opcode byte wait_template_2 = wait_template_2_lfence; wait_template_2_size = sizeof(wait_template_2_lfence); *waits_as_loads = true; } else { wait_template_1 = wait_template_1_st; wait_template_1_size = sizeof(wait_template_1_st); wait_template_1_addr_offset = 2; // 1 opcode byte, 1 ModRM byte wait_template_2 = wait_template_2_mfence; wait_template_2_size = sizeof(wait_template_2_mfence); *waits_as_loads = false; } *ss_curr = 100000; *ss_prev = 100000; if (!KnobPredictedSpeedupFile.Value().empty()) LoadHelixSpeedupModelData(KnobPredictedSpeedupFile.Value().c_str()); }
int main(int argc, char * argv[]) { PIN_Init(argc, argv); PIN_InitSymbols(); RegThreadInfo = PIN_ClaimToolRegister(); if (RegThreadInfo == REG_INVALID()) { std::cout << "Out of tool registers" << std::endl; PIN_ExitProcess(1); } // Get the test type and initialize the corresponding lock variable. // TestType = GetTestType(KnobTest.Value()); switch (TestType) { case TEST_NONE: std::cout << "Must specify a test to run with the '-test' knob" << std::endl; PIN_ExitProcess(1); break; case TEST_INVALID: std::cout << "Invalid test name: " << KnobTest.Value() << std::endl; PIN_ExitProcess(1); break; case TEST_LOCK_INTEGRITY: case TEST_LOCK_STRESS: PIN_InitLock(&Lock); break; case TEST_MUTEX_INTEGRITY: case TEST_MUTEX_STRESS: case TEST_MUTEX_TRYSTRESS: PIN_MutexInit(&Mutex); break; case TEST_WRITER_INTEGRITY: case TEST_WRITER_STRESS: case TEST_WRITER_TRYSTRESS: case TEST_READER_STRESS: case TEST_READER_TRYSTRESS: case TEST_RW_INTEGRITY: case TEST_RW_STRESS: case TEST_RW_TRYSTRESS: PIN_RWMutexInit(&RWMutex); break; case TEST_SEMAPHORE: PIN_SemaphoreInit(&Sem1); PIN_SemaphoreInit(&Sem2); PIN_SemaphoreSet(&Sem1); PIN_MutexInit(&Mutex); break; case TEST_TRYLOCKS: PIN_MutexInit(&Mutex); PIN_RWMutexInit(&RWMutex); PIN_SemaphoreInit(&Sem1); break; default: ASSERTX(0); } PIN_AddThreadStartFunction(OnThreadStart, 0); PIN_AddThreadFiniFunction(OnThreadFini, 0); RTN_AddInstrumentFunction(InstrumentRtn, 0); PIN_AddFiniFunction(OnExit, 0); PIN_StartProgram(); return 0; }