// ------------------------------------------------------------- // Roll back shadow stack if we got here from a longjmp // (Runtime stack grows down and register stack grows up) // ------------------------------------------------------------- static inline VOID AdjustStackBuf(_STool_TThreadRec* tdata, ADDRINT currentSP, CONTEXT *ctxt) { // roll back stack while ( tdata->stackTop > 0 && currentSP >= _ActivationAt(tdata, tdata->stackTop-1).currentSP ) { // if using memory operations buffering, call trace buffer processing callback // and reset buffer if (gSetup.memBuf) { void * curr_buf_pointer = PIN_GetBufferPointer(ctxt, buf_id); UINT64 numElements = ((ADDRINT)curr_buf_pointer - (ADDRINT)tdata->buf_addr) / sizeof(STool_TMemRec); gSetup.memBuf(tdata+1, static_cast<STool_TMemRec*>(tdata->buf_addr), numElements); tdata->buf_addr = curr_buf_pointer; } // call routine exit callback (if any was specified by the analysis tool) if (gSetup.rtnExit) gSetup.rtnExit(tdata + 1); // pop activation tdata->stackTop--; #if DEBUG printf("[TID=%u] <<< longjmp: popping activation of %s\n", tdata->threadID, Target2RtnName(_ActivationAt(tdata, tdata->stackTop).target).c_str()); #endif } }
// ------------------------------------------------------------- // Thread start function // ------------------------------------------------------------- VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v) { // create local thread data _STool_TThreadRec* tdata = (_STool_TThreadRec*)malloc(sizeof(_STool_TThreadRec) + gSetup.threadRecSize); if (tdata == NULL) panic(threadid, "Can't allocate thread specific info"); // init local thread data tdata->threadID = threadid; tdata->stackTop = 0; tdata->stackMaxSize = INIT_STACK; // create initial shadow activation stack tdata->activationStack = (_STool_TActivationRec*)malloc(tdata->stackMaxSize*sizeof(_STool_TActivationRec)); if (tdata->activationStack == NULL) panic(threadid, "Can't allocate shadow activation stack"); // create initial user stack (if any was requested by the analysis tool) if (gSetup.activationRecSize > 0) { tdata->userStack = (char*)malloc(tdata->stackMaxSize*gSetup.activationRecSize); if (tdata->userStack == NULL) panic(threadid, "Can't allocate user stack"); } else tdata->userStack = NULL; // if using memory operations buffering, initialize trace buffer pointer if (gSetup.memBuf) tdata->buf_addr = PIN_GetBufferPointer(ctxt, buf_id); // call thread start callback (if any was specified by the analysis tool) if (gSetup.threadStart) gSetup.threadStart(tdata + 1); // associate thread-specific data to thread PIN_SetThreadData(gTlsKey, tdata, threadid); }
// ------------------------------------------------------------- // Function exit event // ------------------------------------------------------------- VOID PIN_FAST_ANALYSIS_CALL A_ProcessReturnBuf(ADDRINT sp, THREADID threadid, CONTEXT *ctxt) { _STool_TThreadRec* tdata = getTLS(threadid); // roll back stack in case of longjmp AdjustStackBuf(tdata, sp, ctxt); if ( tdata->stackTop < 1 ) graceful_exit(threadid, "Internal error: stack bottomed out"); // if using memory operations buffering, call trace buffer processing callback // and reset buffer if (gSetup.memBuf) { void * curr_buf_pointer = PIN_GetBufferPointer(ctxt, buf_id); UINT64 numElements = ((ADDRINT)curr_buf_pointer - (ADDRINT)tdata->buf_addr) / sizeof(STool_TMemRec); gSetup.memBuf(tdata+1, static_cast<STool_TMemRec*>(tdata->buf_addr), numElements); tdata->buf_addr = curr_buf_pointer; } // call routine exit callback (if any was specified by the analysis tool) if (gSetup.rtnExit) gSetup.rtnExit(tdata + 1); // pop activation tdata->stackTop--; #if DEBUG printf("[TID=%u] Leaving %s\n", threadid, Target2RtnName(tdata->activationStack[tdata->stackTop].target).c_str()); #endif #if DEBUG if (tdata->stackTop > 0) printf("[TID=%u] Back to %s - # activations = %d - stack size = %d\n", threadid, Target2RtnName(tdata->activationStack[tdata->stackTop-1].target).c_str(), tdata->stackTop, tdata->stackSize); else printf("[TID=%u] Back to stack bottom\n", threadid); #endif }
void ThreadStart(THREADID tid, CONTEXT * context, int flags, void * v) { // We check that we got the right thing in the buffer full callback PIN_SetThreadData(buf_key, PIN_GetBufferPointer(context, bufId), tid); }