// this function verifies that the xmm regs in the ctxtFrom are as they were set in the app just before the // exception occurs. Then it sets the xmm regs in the ctxtTo to a different value, finally it causes the // execution to continue in the application function DumpXmmRegsAtException static void OnException(THREADID threadIndex, CONTEXT_CHANGE_REASON reason, const CONTEXT *ctxtFrom, CONTEXT *ctxtTo, INT32 info, VOID *v) { if (CONTEXT_CHANGE_REASON_SIGRETURN == reason || CONTEXT_CHANGE_REASON_APC == reason || CONTEXT_CHANGE_REASON_CALLBACK == reason || CONTEXT_CHANGE_REASON_FATALSIGNAL == reason || ctxtTo == NULL) { // don't want to handle these return; } fprintf (stdout, "TOOL OnException callback\n"); fflush (stdout); //PIN_SaveContext(ctxtFrom, ctxtTo); CheckAndSetFpContextXmmRegs(ctxtFrom, ctxtTo); // call the application function with the ctxtTo context #ifdef TARGET_IA32E PIN_SetContextReg(ctxtTo, REG_RIP, dumpXmmRegsAtExceptionAddr); // take care of stack alignment since tool is redirecting execution flow to function ADDRINT curSp = PIN_GetContextReg(ctxtTo, REG_RSP); INT32 currentAlignment = curSp % 16; PIN_SetContextReg(ctxtTo, REG_RSP, curSp - GetStackAdjustmentForRedirectionToFunction(currentAlignment)); #else PIN_SetContextReg(ctxtTo, REG_EIP, dumpXmmRegsAtExceptionAddr); #endif }
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); GetLock(&Lock, 1); std::cout << "Squashing breakpoint at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl; ReleaseLock(&Lock); return FALSE; } GetLock(&Lock, 1); std::cout << "Stopping at breakpoint at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl; 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); GetLock(&Lock, 1); std::cout << "Changing ASYNC BREAK PC to Two() on thread " << std::dec << tid << std::endl; 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. // GetLock(&Lock, 1); std::cout << "ASYNC_BREAK at 0x" << std::hex << pc << " on thread " << std::dec << tid << std::endl; ReleaseLock(&Lock); return TRUE; } GetLock(&Lock, 1); std::cout << "FAILURE: Unexpected debugging event type" << std::endl; ReleaseLock(&Lock); std::exit(1); }
static VOID SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) { if (PIN_GetSyscallNumber(ctxt, std) != SYS_sysarch) return; ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); ADDRINT op = PIN_GetSyscallArgument(ctxt, std, 0); ADDRINT addr = PIN_GetSyscallArgument(ctxt, std, 1); ADDRINT value = 0; if (op == AMD64_SET_FSBASE || op == AMD64_SET_GSBASE) { if (PIN_SafeCopy(&value, Addrint2VoidStar(addr), sizeof(ADDRINT)) != sizeof(ADDRINT)) { Out << Header(threadIndex, pc) << "Failed to read actual TLS pointer" << endl; } } else { // Remember the location where to write the segment register in REG_INST_G0 PIN_SetContextReg(ctxt, REG_INST_G0, addr); value = addr; } Out << Header(threadIndex, pc) << "sysarch(" << SysArchFunc(op) << ", 0x" << std::hex << value << ")" << std::endl; }
/* * thread start callback (analysis function) * * allocate space for the syscall context and VCPUs * (i.e., thread context), and set the TLS-like pointer * (i.e., thread_ctx_ptr) accordingly * * @tid: thread id * @ctx: CPU context * @flags: OS specific flags for the new thread * @v: callback value */ static void thread_alloc(THREADID tid, CONTEXT *ctx, INT32 flags, VOID *v) { /* thread context pointer (ptr) */ thread_ctx_t *tctx = NULL; /* allocate space for the thread context; optimized branch */ if (unlikely((tctx = (thread_ctx_t *)calloc(1, sizeof(thread_ctx_t))) == NULL)) { /* error message */ LOG(string(__func__) + ": thread_ctx_t allocation failed (" + string(strerror(errno)) + ")\n"); /* die */ libdft_die(); } /* save the address of the per-thread context to the spilled register */ PIN_SetContextReg(ctx, thread_ctx_ptr, (ADDRINT)tctx); char fileName[256]; sprintf(fileName, "C:\\itrace_thread%u.txt", tid); thread_local *t_local = new thread_local; t_local->insaddr = 0; t_local->logfile = fopen(fileName, "w"); PIN_SetThreadData(trace_tls_key, t_local, tid); }
int REPLACE_Replaced(CONTEXT *context, THREADID tid, AFUNPTR func) { int ret; printf("Calling replaced Replaced()\n"); CONTEXT writableContext, *ctxt; if (KnobUseIargConstContext) { // need to copy the ctxt into a writable context PIN_SaveContext(context, &writableContext); ctxt = &writableContext; } else { ctxt = context; } PIN_SetContextReg(ctxt, scratchReg, 1); printf("REPLACE_Replaced: REG_INST_G0=0x%x\n", PIN_GetContextReg(ctxt, scratchReg)); PIN_CallApplicationFunction(ctxt, tid, CALLINGSTD_DEFAULT, func, PIN_PARG(int), &ret, PIN_PARG_END()); printf("REPLACE_Replaced: REG_INST_G0=0x%x\n", PIN_GetContextReg(ctxt, scratchReg)); printf("Returning from replaced Replaced()\n"); return ret; }
VOID ThreadStart(THREADID tid, CONTEXT *ctxt, INT32 flags, VOID *v) { // When the thread starts, zero the virtual register that holds the // dynamic instruction count. // PIN_SetContextReg(ctxt, ScratchReg, 0); }
static VOID printRegisterDiffs(THREADID tid, CONTEXT *ctx, UINT32 where) { threadState * s = &threadStates[tid]; UINT32 seqNo = s->iCount; CONTEXT * savedCtx = &s->context; // Save the context if this was the first instruction if (seqNo == 0) PIN_SaveContext(ctx, savedCtx); else { for (UINT32 i=0; i<sizeof(checkedRegisters)/sizeof(checkedRegisters[0]); i++) { REG r = checkedRegisters[i].regnum; ADDRINT newValue = PIN_GetContextReg(ctx, r); if (PIN_GetContextReg(savedCtx, r) != newValue) { if (where != 0) { out << "*** Instrumentation (" << dec << where << ") caused a change "; } out << dec << seqNo << ": " << checkedRegisters[i].name << " = " << hex << UINT32(newValue) << endl; PIN_SetContextReg(savedCtx, r, newValue); } } } }
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"; }
/* * Pin calls this function to set the value of an emulated register. */ static VOID SetReg(unsigned toolRegId, THREADID tid, CONTEXT *ctxt, const VOID *data, VOID *) { PrintEmulated(); switch (toolRegId) { case EMULATED_REG_RCX: { const ADDRINT *val = static_cast<const ADDRINT *>(data); PIN_SetContextReg(ctxt, REG_RCX, *val); break; } case EMULATED_REG_RSP: { const ADDRINT *val = static_cast<const ADDRINT *>(data); PIN_SetContextReg(ctxt, REG_RSP, *val); break; } case EMULATED_REG_FPSW: { const UINT32 *val = static_cast<const UINT32 *>(data); PIN_SetContextReg(ctxt, REG_FPSW, static_cast<ADDRINT>(*val)); break; } case EMULATED_REG_ST0: { FPSTATE fpstate; PIN_GetContextFPState(ctxt, &fpstate); std::memcpy(&fpstate.fxsave_legacy._sts[0], data, 10); PIN_SetContextFPState(ctxt, &fpstate); break; } case EMULATED_REG_XMM0: { FPSTATE fpstate; PIN_GetContextFPState(ctxt, &fpstate); std::memcpy(&fpstate.fxsave_legacy._xmms[0], data, 16); PIN_SetContextFPState(ctxt, &fpstate); break; } default: { ASSERTX(0); break; } } }
// There is no verification on the validity of the ID. void PINContextHandler::setRegisterValue(uint64 TritRegID, uint64 value) const { REG reg = safecast(PINConverter::convertTritonReg2DBIReg(TritRegID)); if (!REG_valid(reg) || (TritRegID >= ID_XMM0 && TritRegID <= ID_XMM15)) throw std::runtime_error("Error: setRegisterValue() - Invalid PIN register id."); PIN_SetContextReg(this->_ctx, reg, value); PIN_ExecuteAt(this->_ctx); }
static bool OnCommand(THREADID, CONTEXT *ctxt, const std::string &cmd, std::string *reply, VOID *) { if (cmd == "clear-sp") { PIN_SetContextReg(ctxt, REG_STACK_PTR, 0); *reply = "Changed $SP to 0\n"; return true; } return false; }
unsigned int PinExecutionContext::setRegisterValue(enum eRegister reg, unsigned long value) { REG pin_register; unsigned int result; result = mapRegisterToPin(reg, &pin_register); if (result == 0) { PIN_SetContextReg(pin_context, pin_register, (ADDRINT) value); return 0; } else { return result; } }
// This function is called whenever Pin wants to report a breakpoint event to the // debugger. // static BOOL InterceptBreakpoint(THREADID tid, DEBUGGING_EVENT eventType, CONTEXT *ctxt, VOID *) { if (eventType != DEBUGGING_EVENT_BREAKPOINT) { std::cout << "FAILURE: Wrong event type in InterceptBreakpoint()" << std::endl; std::exit(1); } ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); RTN rtn = RTN_FindByAddress(pc); // When the application triggers the breakpoint in Breakpoint1(), squash the breakpoint // and roll the application back to the Checkpoint() call. The application will NOT stop // at the breakpoint, and it will immediately resume from Checkpoint(). // if (rtn != RTN_Invalid() && RTN_Name(rtn) == "Breakpoint1") { std::cout << "Intercepting breakpoint #1 at 0x" << std::hex << pc << std::endl; PIN_SaveContext(&SavedContext, ctxt); PIN_SetContextReg(ctxt, REG_GAX, 1); MemLog.Restore(); IsCheckpointing = FALSE; return FALSE; } // When the application triggers the breakpoint in Breakpoint2(), do not squash the // breakpoint, but change the return value from Breakpoint2(). The application will stop // in the debugger, and the debugger should see the modified return value. // if (rtn != RTN_Invalid() && (RTN_Name(rtn) == "Breakpoint2" || RTN_Name(rtn) == "Breakpoint2Label")) { std::cout << "Intercepting breakpoint #2 at 0x" << std::hex << pc << std::endl; std::cout << "RTN=" << RTN_Name(rtn) << std::endl; PIN_SetContextReg(ctxt, REG_GAX, 1); return TRUE; } std::cout << "Skipping breakpoint at 0x" << std::hex << pc << ", RTN=" << RTN_Name(rtn) << std::endl; return TRUE; }
static bool PostPatchTimeoutSyscall(uint32_t tid, CONTEXT* ctxt, SYSCALL_STANDARD std, int syscall, ADDRINT prevIp, ADDRINT timeoutArgVal) { assert(inFakeTimeoutMode[tid]); int res = (int)PIN_GetSyscallNumber(ctxt, std); // Decide if it timed out bool timedOut; if (syscall == SYS_futex) { timedOut = (res == -ETIMEDOUT); } else { timedOut = (res == 0); } bool isSleeping = zinfo->sched->isSleeping(procIdx, tid); // Decide whether to retry bool retrySyscall; if (!timedOut) { if (isSleeping) zinfo->sched->notifySleepEnd(procIdx, tid); retrySyscall = false; } else { retrySyscall = isSleeping; } if (retrySyscall && zinfo->procArray[procIdx]->isInFastForward()) { warn("[%d] Fast-forwarding started, not retrying timeout syscall (%s)", tid, GetSyscallName(syscall)); retrySyscall = false; assert(isSleeping); zinfo->sched->notifySleepEnd(procIdx, tid); } if (retrySyscall) { // ADDRINT curIp = PIN_GetContextReg(ctxt, REG_INST_PTR); //info("[%d] post-patch, retrying, IP: 0x%lx -> 0x%lx", tid, curIp, prevIp); PIN_SetContextReg(ctxt, REG_INST_PTR, prevIp); PIN_SetSyscallNumber(ctxt, std, syscall); } else { // Restore timeout arg PIN_SetSyscallArgument(ctxt, std, getTimeoutArg(syscall), timeoutArgVal); inFakeTimeoutMode[tid] = false; // Restore arg? I don't think we need this! /*if (syscall == SYS_futex) { PIN_SetSyscallNumber(ctxt, std, -ETIMEDOUT); } else { assert(syscall == SYS_epoll_wait || syscall == SYS_epoll_pwait || syscall == SYS_poll); PIN_SetSyscallNumber(ctxt, std, 0); //no events returned }*/ } //info("[%d] post-patch %s (%d), timedOut %d, sleeping (orig) %d, retrying %d, orig res %d, patched res %d", tid, GetSyscallName(syscall), syscall, timedOut, isSleeping, retrySyscall, res, (int)PIN_GetSyscallNumber(ctxt, std)); return retrySyscall; }
// check if the address that has to be executed has been written by anoter instruction in the trace (polymorphic code) // if this is true we have to break the trace and recompile it from the current eip address VOID checkIfWrittenAddress(ADDRINT eip, CONTEXT * ctxt, UINT32 ins_size, void *pcpatchesH){ PolymorphicCodeHandlerModule *pcpatches = (PolymorphicCodeHandlerModule *)pcpatchesH; //we have to check if the wriotten address is between the eip and eip + inst_size because // sometime can happen that only part of the original instruction is written // ES : push 0x20 -> push 0x30 (only the operand is written) if(pcpatches->getFirstWrittenAddressInMesmory() >= eip && pcpatches->getFirstWrittenAddressInMesmory() <= eip + ins_size){ PIN_SetContextReg(ctxt, REG_EIP, eip); //reset the address pcpatches->setFirstWrittenAddressInMesmory(0x0); // break the terace PIN_ExecuteAt(ctxt); } }
static VOID OnThreadStart(THREADID tid, CONTEXT *ctxt, INT32, VOID *) { // Skip root thread. // if (tid == 0) return; // Give each worker thread a unique, contiguous ID. // static unsigned workerCount = 0; THREAD_INFO *info = new THREAD_INFO(workerCount++); PIN_SetContextReg(ctxt, RegThreadInfo, reinterpret_cast<ADDRINT>(info)); }
static VOID SyscallExit(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) { ADDRINT addr = PIN_GetContextReg(ctxt, REG_INST_G0); if (!addr) return; // Reset REG_INST_G0 PIN_SetContextReg(ctxt, REG_INST_G0, 0); ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); ADDRINT ret = PIN_GetSyscallReturn(ctxt, std); ADDRINT value = 0; if (ret == (ADDRINT)-1 || PIN_SafeCopy(&value, Addrint2VoidStar(addr), sizeof(ADDRINT)) != sizeof(ADDRINT)) { Out << Header(threadIndex, pc) << "Failed to read actual TLS pointer" << endl; } Out << Header(threadIndex, pc) << "sysarch returned: " << ", 0x" << std::hex << value << "" << std::endl; }
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); }
/* * thread start callback (analysis function) * * allocate space for the syscall context and VCPUs * (i.e., thread context), and set the TLS-like pointer * (i.e., thread_ctx_ptr) accordingly * * @tid: thread id * @ctx: CPU context * @flags: OS specific flags for the new thread * @v: callback value */ static void thread_alloc(THREADID tid, CONTEXT *ctx, INT32 flags, VOID *v) { /* thread context pointer (ptr) */ thread_ctx_t *tctx = NULL; /* allocate space for the thread context; optimized branch */ if (unlikely((tctx = (thread_ctx_t *)calloc(1, sizeof(thread_ctx_t))) == NULL)) { /* error message */ LOG(string(__FUNCTION__) + ": thread_ctx_t allocation failed (" + string(strerror(errno)) + ")\n"); /* die */ libdft_die(); } /* save the address of the per-thread context to the spilled register */ PIN_SetContextReg(ctx, thread_ctx_ptr, (ADDRINT)tctx); }
VOID REPLACE_ReplacedXmmRegs(CONTEXT *context, THREADID tid, AFUNPTR originalFunction) { printf ("TOOL in REPLACE_ReplacedXmmRegs\n"); fflush (stdout); CONTEXT writableContext, *ctxt; if (KnobUseIargConstContext) { // need to copy the ctxt into a writable context PIN_SaveContext(context, &writableContext); ctxt = &writableContext; } else { ctxt = context; } /* set the xmm regs in the ctxt which is used to execute the originalFunction (via PIN_CallApplicationFunction) */ CHAR fpContextSpaceForFpConextFromPin[FPSTATE_SIZE]; FPSTATE *fpContextFromPin = reinterpret_cast<FPSTATE *>(fpContextSpaceForFpConextFromPin); PIN_GetContextFPState(ctxt, fpContextFromPin); for (int i=0; i<NUM_XMM_REGS; i++) { fpContextFromPin->fxsave_legacy._xmms[i]._vec32[0] = 0xacdcacdc; fpContextFromPin->fxsave_legacy._xmms[i]._vec32[1] = 0xacdcacdc; fpContextFromPin->fxsave_legacy._xmms[i]._vec32[2] = 0xacdcacdc; fpContextFromPin->fxsave_legacy._xmms[i]._vec32[3] = 0xacdcacdc; } PIN_SetContextFPState(ctxt, fpContextFromPin); // verify the xmm regs were set in the ctxt CHAR fpContextSpaceForFpConextFromPin2[FPSTATE_SIZE]; FPSTATE *fpContextFromPin2 = reinterpret_cast<FPSTATE *>(fpContextSpaceForFpConextFromPin2); PIN_GetContextFPState(ctxt, fpContextFromPin2); for (int i=0; i<NUM_XMM_REGS; i++) { if ((fpContextFromPin->fxsave_legacy._xmms[i]._vec64[0] !=fpContextFromPin2->fxsave_legacy._xmms[i]._vec64[0]) || (fpContextFromPin->fxsave_legacy._xmms[i]._vec64[1] !=fpContextFromPin2->fxsave_legacy._xmms[i]._vec64[1])) { printf("TOOL ERROR at xmm[%d] (%lx %lx %lx %lx) (%lx %lx %lx %lx)\n", i, (unsigned long)fpContextFromPin->fxsave_legacy._xmms[i]._vec32[0], (unsigned long)fpContextFromPin->fxsave_legacy._xmms[i]._vec32[1], (unsigned long)fpContextFromPin->fxsave_legacy._xmms[i]._vec32[2], (unsigned long)fpContextFromPin->fxsave_legacy._xmms[i]._vec32[3], (unsigned long)fpContextFromPin2->fxsave_legacy._xmms[i]._vec32[0], (unsigned long)fpContextFromPin2->fxsave_legacy._xmms[i]._vec32[1], (unsigned long)fpContextFromPin2->fxsave_legacy._xmms[i]._vec32[2], (unsigned long)fpContextFromPin2->fxsave_legacy._xmms[i]._vec32[3]); exit (-1); } } // call the originalFunction function with the xmm regs set from above printf("TOOL Calling replaced ReplacedXmmRegs()\n"); fflush (stdout); PIN_CallApplicationFunction(ctxt, tid, CALLINGSTD_DEFAULT, originalFunction, PIN_PARG_END()); printf("TOOL Returned from replaced ReplacedXmmRegs()\n"); fflush (stdout); if (executeAtAddr != 0) { // set xmm regs to other values for (int i=0; i<NUM_XMM_REGS; i++) { fpContextFromPin->fxsave_legacy._xmms[i]._vec32[0] = 0xdeadbeef; fpContextFromPin->fxsave_legacy._xmms[i]._vec32[1] = 0xdeadbeef; fpContextFromPin->fxsave_legacy._xmms[i]._vec32[2] = 0xdeadbeef; fpContextFromPin->fxsave_legacy._xmms[i]._vec32[3] = 0xdeadbeef; } PIN_SetContextFPState(ctxt, fpContextFromPin); // execute the application function ExecuteAtFunc with the xmm regs set PIN_SetContextReg(ctxt, REG_INST_PTR, executeAtAddr); printf("TOOL Calling ExecutedAtFunc\n"); fflush (stdout); PIN_ExecuteAt (ctxt); printf("TOOL returned from ExecutedAtFunc\n"); fflush (stdout); } }
static VOID OnThreadStart(THREADID tid, CONTEXT *ctxt, INT32, VOID *) { TINFO *tinfo = new TINFO(PIN_GetContextReg(ctxt, REG_STACK_PTR)); ThreadInfos.insert(std::make_pair(tid, tinfo)); PIN_SetContextReg(ctxt, RegTinfo, reinterpret_cast<ADDRINT>(tinfo)); }
// In order to avoid obsidium to take the path of the 'or byte ptr [esp+0x1],0x1' VOID KillObsidiumDeadPath(CONTEXT *ctxt){ PIN_SetContextReg(ctxt,REG_EAX,0x7); }
VOID OnThread(THREADID threadIndex, CONTEXT *ctxt, INT32 flags, VOID *v) { PIN_SetContextReg(ctxt, scratchReg, 0); }
VOID ThreadStart(THREADID tid, CONTEXT *ctxt, int flags, VOID *v) { for (UINT32 r = 0; r <= 9; r++) PIN_SetContextReg(ctxt, REG(REG_INST_G0 + r), BaseValue + tid + r); }
VOID AnalysisFunc(CONTEXT *context) { PIN_SetContextReg(context, REG_GAX, 0); }
VOID REPLACE_ReplacedX87Regs(CONTEXT *context, THREADID tid, AFUNPTR originalFunction) { printf ("TOOL in REPLACE_ReplacedX87Regs x87 regs are:\n"); fflush (stdout); CHAR fpContextSpaceForFpConextFromPin[FPSTATE_SIZE]; FPSTATE *fpContextFromPin = reinterpret_cast<FPSTATE *>(fpContextSpaceForFpConextFromPin); PIN_GetContextFPState(context, fpContextFromPin); // verfiy that x87 registers are as they were set by the app just before the call to // ReplacedX87Regs, which is replaced by this function /* app set the x87 fp regs just before the call to ReplacedX87Regs as follows _mxcsr 1f80 _st[0] 0 3fff 80000000 0 _st[1] 0 3fff 80000000 0 _st[2] 0 3fff 80000000 0 _st[3] 0 5a5a 5a5a5a5a 5a5a5a5a _st[4] 0 5a5a 5a5a5a5a 5a5a5a5a _st[5] 0 5a5a 5a5a5a5a 5a5a5a5a _st[6] 0 5a5a 5a5a5a5a 5a5a5a5a _st[7] 0 5a5a 5a5a5a5a 5a5a5a5a */ printf ("_mxcsr %x\n", fpContextFromPin->fxsave_legacy._mxcsr); if (fpContextFromPin->fxsave_legacy._mxcsr & 0x200) { printf ("***Error divide by zero should be masked\n"); exit (-1); } int i; for (i=0; i<3; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); printf ("_st[%d] %x %x %x %x\n", i,ptr->_hi2,ptr->_hi1,ptr->_lo2,ptr->_lo1); if (ptr->_hi2 != 0 && ptr->_hi1 != 0x3fff && ptr->_lo2 != 0x80000000 && ptr->_lo1 != 0) { printf ("***Error in this _st\n"); exit(-1); } } for (; i< 8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); printf ("_st[%d] %x %x %x %x\n", i,ptr->_hi2,ptr->_hi1,ptr->_lo2,ptr->_lo1); if (ptr->_hi2 != 0 && ptr->_hi1 != 0x5a5a && ptr->_lo2 != 0x5a5a5a5a && ptr->_lo1 != 0x5a5a5a5a) { printf ("***Error in this _st\n"); exit(-1); } } CONTEXT writableContext, *ctxt; if (KnobUseIargConstContext) { // need to copy the ctxt into a writable context PIN_SaveContext(context, &writableContext); ctxt = &writableContext; } else { ctxt = context; } /* set the x87 regs in the ctxt which is used to execute the originalFunction (via PIN_CallApplicationFunction) */ PIN_GetContextFPState(ctxt, fpContextFromPin); for (i=0; i< 8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); ptr->_hi2=0xacdcacdc; ptr->_hi1=0xacdcacdc; ptr->_lo2=0xacdcacdc; ptr->_lo1=0xacdcacdc; } fpContextFromPin->fxsave_legacy._mxcsr |= (0x200); // mask divide by zero PIN_SetContextFPState(ctxt, fpContextFromPin); // verify the setting worked for (i=0; i<8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); ptr->_hi2=0x0; ptr->_hi1=0x0; ptr->_lo2=0x0; ptr->_lo1=0x0; } PIN_GetContextFPState(ctxt, fpContextFromPin); for (i=0; i<8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); if (ptr->_hi2 != 0xacdcacdc || ptr->_hi2 != 0xacdcacdc || ptr->_lo2!= 0xacdcacdc || ptr->_lo1!= 0xacdcacdc ) { printf ("TOOL error1 in setting fp context in REPLACE_ReplacedX87Regs\n"); exit (-1); } } // call the originalFunction function with the xmm regs set from above printf("TOOL Calling replaced ReplacedX87Regs()\n"); fflush (stdout); PIN_CallApplicationFunction(ctxt, tid, CALLINGSTD_DEFAULT, originalFunction, PIN_PARG_END()); printf("TOOL Returned from replaced ReplacedX87Regs()\n"); fflush (stdout); if (executeAtAddr != 0) { for (i=0; i< 8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); ptr->_hi2=0xcacdcacd; ptr->_hi1=0xcacdcacd; ptr->_lo2=0xcacdcacd; ptr->_lo1=0xcacdcacd; } PIN_SetContextFPState(ctxt, fpContextFromPin); // verify the setting worked for (i=0; i<8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); ptr->_hi2=0x0; ptr->_hi1=0x0; ptr->_lo2=0x0; ptr->_lo1=0x0; } PIN_GetContextFPState(ctxt, fpContextFromPin); for (i=0; i<8; i++) { RAW32 *ptr = reinterpret_cast<RAW32 *>(&fpContextFromPin->fxsave_legacy._sts[i]._raw); if (ptr->_hi2 != 0xcacdcacd || ptr->_hi2 != 0xcacdcacd || ptr->_lo2!= 0xcacdcacd || ptr->_lo1!= 0xcacdcacd ) { printf ("TOOL error2 in setting fp context in REPLACE_ReplacedX87Regs\n"); exit (-1); } } // execute the application function ExecuteAtFunc with the xmm regs set PIN_SetContextReg(ctxt, REG_INST_PTR, executeAtAddr); printf("TOOL Calling ExecutedAtFunc\n"); fflush (stdout); PIN_ExecuteAt (ctxt); printf("TOOL returned from ExecutedAtFunc\n"); fflush (stdout); } }