static BOOL Intercept(THREADID tid, DEBUGGING_EVENT eventType, CONTEXT *ctxt, VOID *) { if (eventType == DEBUGGING_EVENT_BREAKPOINT) { // When the child thread reaches the breakpoint in Breakpoint(), wait for the main // thread to reach the One() function. If the main thread is not there yet, squash the // breakpoint and move the PC back to the start of the Breakpoint() function. This will // delay a while and then re-trigger the breakpoint. // ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); if (pc == BreakpointLocation && !AllowBreakpoint) { PIN_SetContextReg(ctxt, REG_INST_PTR, BreakpointFunction); PIN_GetLock(&Lock, 1); std::cout << "Squashing breakpoint at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl; PIN_ReleaseLock(&Lock); return FALSE; } PIN_GetLock(&Lock, 1); std::cout << "Stopping at breakpoint at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl; PIN_ReleaseLock(&Lock); return TRUE; } if (eventType == DEBUGGING_EVENT_ASYNC_BREAK) { // When the child thread triggers the breakpoint, we should be at the One() function. // Change the PC to the Two() function, which is the point of this test. We want to // make sure Pin properly handles the change of PC in this case. // ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); if (pc == OneFunction) { PIN_SetContextReg(ctxt, REG_INST_PTR, TwoFunction); PIN_GetLock(&Lock, 1); std::cout << "Changing ASYNC BREAK PC to Two() on thread " << std::dec << tid << std::endl; PIN_ReleaseLock(&Lock); return TRUE; } // If the PC is not at the One() function, the child thread has probably hit some breakpoint // other than the one at Breakpoint(). (E.g. an internal breakpoint set by GDB.) Don't // change the PC in such a case. // PIN_GetLock(&Lock, 1); std::cout << "ASYNC_BREAK at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl; PIN_ReleaseLock(&Lock); return TRUE; } PIN_GetLock(&Lock, 1); std::cout << "FAILURE: Unexpected debugging event type" << std::endl; PIN_ReleaseLock(&Lock); std::exit(1); }
/*! * Print out analysis results. * This function is called when the application exits. * @param[in] code exit code of the application * @param[in] v value specified by the tool in the * PIN_AddFiniFunction function call */ VOID Fini(INT32 code, VOID *v) { PIN_GetLock(&fileLock, 1); fclose(outfile); printf("outfile closed\n"); PIN_ReleaseLock(&fileLock); }
// Note that opening a file in a callback is only supported on Linux systems. // See buffer-win.cpp for how to work around this issue on Windows. // // This routine is executed every time a thread is created. VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, threadid+1); fprintf(out, "thread begin %d\n",threadid); fflush(out); PIN_ReleaseLock(&lock); }
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); }
VOID Error(std::string where, THREADID tid, UINT32 r, ADDRINT expect, ADDRINT val) { PIN_GetLock(&Lock, 1); Out << "Mismatch " << where << ": tid=" << std::dec << tid << " (G" << r << ")" << ", Expect " << std::hex << expect << ", Got " << std::hex << val << std::endl; PIN_ReleaseLock(&Lock); }
// This routine is executed every time a thread is destroyed. VOID ThreadFini(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v) { PIN_GetLock(&lock, threadid+1); fprintf(out, "thread end %d code %d\n",threadid, code); fflush(out); PIN_ReleaseLock(&lock); }
// This routine is executed each time malloc is called. VOID BeforeMalloc( int size, THREADID threadid ) { PIN_GetLock(&lock, threadid+1); fprintf(out, "thread %d entered malloc(%d)\n", threadid, size); fflush(out); PIN_ReleaseLock(&lock); }
static bool address_mapped(void *addr) { int i; PIN_GetLock(&globalLock, 1); i = _find_overlap(addr, addr); PIN_ReleaseLock(&globalLock); return (i != -1); }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, threadid+1); numThreads++; PIN_ReleaseLock(&lock); ASSERT(numThreads <= MaxNumThreads, "Maximum number of threads exceeded\n"); }
static VOID GetToolLock(THREADID tid) { PIN_GetLock(&ToolLock, tid+1); // The loop opens the timing hole, making the deadlock more likely. for(int i=0;i<10000000;i++); PIN_ReleaseLock(&ToolLock); }
static void DoTestLockStress(THREADID tid, THREAD_INFO *info, UINT32 *done) { // This test just tries to acquire and release PIN_LOCK as fast as possible // to see if we can provoke a deadlock due to missing a wakeup. PIN_GetLock(&Lock, tid); PIN_ReleaseLock(&Lock); CheckIfDone(info, done); }
VOID ThreadFini(THREADID tid, const CONTEXT *ctxt, INT32 code, VOID *v) { // When the thread exits, accumulate the thread's dynamic instruction // count into the total. // PIN_GetLock(&Lock, tid+1); TotalCount += PIN_GetContextReg(ctxt, ScratchReg); PIN_ReleaseLock(&Lock); }
// Print a memory write record VOID RecordMemWrite(VOID * ip, VOID * addr, THREADID threadid) { PIN_GetLock(&lock, 0); bool dl1hit = dl1cache->AccessSingleLine((ADDRINT)addr, CACHE_BASE::ACCESS_TYPE_STORE); bool dl3hit = dl3cache->AccessSingleLine((ADDRINT)addr, CACHE_BASE::ACCESS_TYPE_STORE); PIN_ReleaseLock(&lock); thread_data *td = get_tls(threadid); td->record_mem_write(ip, addr, dl1hit || dl3hit); }
static void UseLocksScheduler() { UseLockSchedulerCount++; // The scheduler thread executes this after it has lowered the priority of // the worker thread. The hope is that we will try to acquire the lock while // the worker already has it. // PIN_GetLock(&Lock, 2); PIN_ReleaseLock(&Lock); }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { if(threadid!=0)return; PIN_GetLock(&lock, threadid+1); numThreads++; PIN_ReleaseLock(&lock); tdata = new thread_data_t (threadid); PIN_SetThreadData(tls_key, tdata, threadid); }
VOID Call(THREADID tid, ADDRINT sp, ADDRINT target, ADDRINT eip, ADDRINT nxtIns ) { thread_data_t *tdata = get_tls(tid); PIN_GetLock(&lock, tid+1); tdata->data_sp.push_front(sp); // Pushing SP register tdata->data_ret.push_front(nxtIns); // Pushing return address for the call ins tdata->tuplist.push_front(boost::tuple<ADDRINT, ADDRINT>(eip, nxtIns)); depth++; PIN_ReleaseLock(&lock); }
static void UseLocksWorker() { UseLockWorkerCount++; // The worker thread executes this in a loop. We do sched_yield() to // encourage the kernel to switch the thread off the CPU while it holds // the lock. This would be possible even without the sched_yield(), though. // PIN_GetLock(&Lock, 1); sched_yield(); PIN_ReleaseLock(&Lock); }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, threadid+1); numThreads++; PIN_ReleaseLock(&lock); thread_data_t* tdata = new thread_data_t; clock_gettime(CLOCK_MONOTONIC, &tdata->tstart); PIN_SetThreadData(tls_key, tdata, threadid); }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, 0); thread_data *td = new thread_data; PIN_SetThreadData(tls_key, td, threadid); all_thread_data.push_back(td); PIN_ReleaseLock(&lock); }
VOID Call(THREADID tid, ADDRINT sp, ADDRINT target, ADDRINT eip, ADDRINT nxtIns ) { thread_data_t *tdata = get_tls(tid); PIN_GetLock(&lock, tid+1); tdata->data_sp.push_front(sp); // Pushing SP register tdata->data_ret.push_front(nxtIns); // Pushing return address for the call ins tdata->tuplist.push_front(boost::tuple<ADDRINT, ADDRINT>(eip, nxtIns)); depth++; PIN_ReleaseLock(&lock); if ( eip == 12 ) // cout << hex << (nxtIns - eip ) << " : " << nxtIns << " : " << eip << endl; cout << hex << tdata->tuplist.begin()->get<0>() << " " <<tdata->tuplist.begin()->get<1>() << endl; }
static VOID AtOne() { if (!AllowBreakpoint) { PIN_GetLock(&Lock, 1); std::cout << "Breakpoint is allowed" << std::endl; PIN_ReleaseLock(&Lock); } // When the main thread reaches the One() function, allow the child thread to trigger // the breakpoint. The main thread will continue executing this instruction in a loop // until we intercept the DEBUGGING_EVENT_ASYNC_BREAK event below. // AllowBreakpoint = TRUE; }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_InitLock(&lock); PIN_GetLock(&lock, threadid+1); numThreads++; if (threadid > maxThreads) maxThreads = threadid; OS_THREAD_ID oid = PIN_GetTid(); OSTID_ITER iter = tidMap.find(oid); if (iter == tidMap.end()) { // new threads numSysThreads++; tidMap.insert(oid); } PIN_ReleaseLock(&lock); }
/*! * Called when a buffer fills up, or the thread exits, so we can process it or pass it off * as we see fit. * @param[in] id buffer handle * @param[in] tid id of owning thread * @param[in] ctxt application context when the buffer filled * @param[in] buf actual pointer to buffer * @param[in] numElements number of records * @param[in] v callback value * @return A pointer to the buffer to resume filling. */ VOID * BufferFull(BUFFER_ID bid, THREADID tid, const CONTEXT *ctxt, VOID *buf, UINT64 numElements, VOID *v) { PIN_GetLock(&fileLock, 1); ASSERTX(buf == PIN_GetThreadData(buf_key, tid)); struct MEMREF* reference=(struct MEMREF*)buf; UINT64 i; for(i=0; i<numElements; i++, reference++){ fprintf(outfile, "%lx %lx %u %u\n", (unsigned long)reference->pc, (unsigned long)reference->address, reference->size, reference->load); } fflush(outfile); PIN_ReleaseLock(&fileLock); return buf; }
/*! * Called when a buffer fills up, or the thread exits, so we can process it or pass it off * as we see fit. * @param[in] id buffer handle * @param[in] tid id of owning thread * @param[in] ctxt application context when the buffer filled * @param[in] buf actual pointer to buffer * @param[in] numElements number of records * @param[in] v callback value * @return A pointer to the buffer to resume filling. */ VOID * BufferFull2(BUFFER_ID id, THREADID tid, const CONTEXT *ctxt, VOID *buf, UINT64 numElements, VOID *v) { PIN_GetLock(&fileLock, 1); struct MEMREF* reference=(struct MEMREF*)buf; unsigned int i; fprintf( outfile, "Dumping buffer 2 at address %lx\n", (unsigned long)buf); for(i=0; i<numElements; i++, reference++){ fprintf(outfile, "%lx %lx %u %u\n", (unsigned long)reference->pc, (unsigned long)reference->address, reference->size, reference->load); } fflush(outfile); PIN_ReleaseLock(&fileLock); return buf; }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_InitLock(&lock); PIN_GetLock(&lock, threadid+1); fprintf(trace, "thread begin %x %x\n",threadid, numThreads); numThreads++; if (threadid < MAX_THREADS) { #ifndef TARGET_LINUX threadData[threadid].threadTeb = InitializeThreadData(); #endif } else { fprintf (trace, "ERROR - maximum #threads exceeded\n"); } fflush(trace); PIN_ReleaseLock(&lock); }
VOID ThreadStart( THREADID tid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, tid+1); tIds[numThreads] = tid; stringstream fn; if ( tid != numThreads ) { cout << " TID NOT SAME AS NUMTHREADS " << tid << " " << numThreads << endl; } fn.str(""); fn << OUT_FILE << "_" << numThreads; OutFile[numThreads].open(fn.str().c_str(), ios::out); ++numThreads; PIN_ReleaseLock(&lock); thread_data_t *tdata = new thread_data_t(numThreads-1); PIN_SetThreadData(tls_key, tdata, tid); }
VOID ThreadStart( THREADID tid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, tid+1); tIds[numThreads] = tid; stringstream fn; /* If you ever see this then change the logic in code which uses tid to index into open File streams to do File I/O */ if ( tid != numThreads ) { cout << " TID NOT SAME AS NUMTHREADS " << tid << " " << numThreads << endl; } fn.str(""); fn << OUT_FILE << "_" << numThreads; OutFile[numThreads].open(fn.str().c_str(), ios::out); ++numThreads; PIN_ReleaseLock(&lock); thread_data_t *tdata = new thread_data_t(numThreads-1); PIN_SetThreadData(tls_key, tdata, tid); }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, threadid+1); fprintf(trace, "thread begin %x %x\n",threadid, numThreads); numThreads++; if (threadid < MAX_THREADS) { #ifdef TARGET_WINDOWS threadData[threadid].threadTeb = InitializeThreadData(); if ((ADDRINT)PIN_GetContextReg( ctxt, TESTED_SEG_REG_BASE ) != InitializeThreadData()) { fprintf (trace, "ERROR - Initial value of tested segment base does not match TEB\n"); hadError = TRUE; } #endif } else { fprintf (trace, "ERROR - maximum #threads exceeded\n"); } fflush(trace); PIN_ReleaseLock(&lock); }
VOID ThreadFini(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v) { PIN_GetLock(&lock, PIN_GetTid()); threadEnded++; PIN_ReleaseLock(&lock); }
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_GetLock(&lock, PIN_GetTid()); threadCreated++; PIN_ReleaseLock(&lock); }