You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
5.6 KiB

/*
* 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 "pin.H"
#include <iostream>
#include <iomanip>
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<char*>(((reinterpret_cast<ADDRINT>(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<xed_iclass_enum_t>(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;
}