/* * Copyright 2002-2019 Intel Corporation. * * This software is provided to you as Sample Source Code as defined in the accompanying * End User License Agreement for the Intel(R) Software Development Products ("Agreement") * section 1.L. * * This software and the related documents are provided as is, with no express or implied * warranties, other than those that are expressly stated in the License. */ #include #include #include "pin.H" UINT64 icount = 0; #if defined(PIN_MS_COMPATIBLE) extern "C" void mmx_save(char* buf); extern "C" void mmx_restore(char* buf); #endif VOID mmx_arg(PIN_REGISTER* r, UINT32 opnd_indx, UINT32 regno) { char buffer[512+16]; char* aligned_bufp =reinterpret_cast(((reinterpret_cast(buffer) + 16) >> 4)<<4); #if defined(PIN_GNU_COMPATIBLE) asm("fxsave %0" : "=m"(*aligned_bufp)); #else mmx_save(aligned_bufp); #endif #if defined(DEBUG_SSE_REF) cout << "MMX" << regno << " operand_index: " << opnd_indx << " "; cout << setw(10) << r->dword[0] << " "; cout << setw(10) << r->dword[1] << " "; cout << endl; #endif // increment the destination... if (opnd_indx == 0) { r->dword[0] ++; } #if defined(PIN_GNU_COMPATIBLE) asm volatile("fxrstor %0" :: "m"(*aligned_bufp)); #else mmx_restore(aligned_bufp); #endif icount++; } VOID xmm_arg(PIN_REGISTER* r, UINT32 opnd_indx, UINT32 regno) { #if defined(DEBUG_SSE_REF) cout << "XMM" << regno << " operand_index: " << opnd_indx << " "; for(unsigned int i=0;i< MAX_DWORDS_PER_PIN_REG;i++) { cout << setw(10) << r->dword[i] << " "; } cout << endl; #endif // increment the destination... if (opnd_indx == 0) { r->dword[0] ++; } icount++; } CONTEXT *gctxtx; VOID TestConstContext(CONTEXT *ctxt) { gctxtx = ctxt; } int dummy=2; VOID BeforeTestConstContext() { // so it won't be inlined if (dummy > 0) { dummy = dummy*dummy*dummy; } dummy += dummy; } VOID Img(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)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { xed_iclass_enum_t iclass = static_cast(INS_Opcode(ins)); if (iclass == XED_ICLASS_MOVQ || iclass == XED_ICLASS_MOVDQU) { // const unsigned int opnd_count = INS_OperandCount(ins); unsigned int i=0; // for(unsigned int i=0; i < opnd_count;i++) { if (INS_OperandIsReg(ins,i)) { REG r = INS_OperandReg(ins,i); if (REG_is_mm(r)) { // BeforeTestConstContext causes X87 state to be spilled // before the instruction that accesses the mmx reg INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)BeforeTestConstContext, IARG_END); // TestConstContext requests the X87 context in order to verify // the Pin can find it after the instruction that accesses the mmx reg // when the X87 state is spilled INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)TestConstContext, IARG_CONST_CONTEXT, IARG_END); INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)mmx_arg, IARG_REG_REFERENCE, r, IARG_UINT32, i, IARG_UINT32, (r-REG_MM_BASE), IARG_END); } if (REG_is_xmm(r)) { INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)xmm_arg, IARG_REG_REFERENCE, r, IARG_UINT32, i, IARG_UINT32, (r-REG_XMM_BASE), IARG_END); } } } } } RTN_Close(rtn); } } } } VOID Fini(INT32 code, VOID *v) { // Don't output icount as part of the reference output // because the dynamic loader may also use xmm insts. //std::cout << "Count: " << icount << endl; } int main(int argc, char * argv[]) { PIN_Init(argc, argv); PIN_InitSymbols(); IMG_AddInstrumentFunction(Img, 0); PIN_AddFiniFunction(Fini, 0); // Never returns PIN_StartProgram(); return 0; }