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.

826 lines
27 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 <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include "pin.H"
#include "instlib.H"
using std::iostream;
using std::ostringstream;
KNOB<BOOL> KnobGetIntContext(KNOB_MODE_WRITEONCE, "pintool", "get_int_context", "0", "get int context");
KNOB<BOOL> KnobGetPartOfIntContext(KNOB_MODE_WRITEONCE, "pintool", "get_part_of_int_context", "0", "get part of int context");
KNOB<BOOL> KnobGetFpContext(KNOB_MODE_WRITEONCE, "pintool", "get_fp_context", "0", "get fp context");
KNOB<BOOL> KnobCompareContexts(KNOB_MODE_WRITEONCE, "pintool", "compare_contexts", "1", "compare contexts");
KNOB<BOOL> KnobCompareReverseContexts(KNOB_MODE_WRITEONCE, "pintool", "reverse_compare_contexts", "0", "reverse compare contexts");
KNOB<BOOL> KnobOnStackContextOnly(KNOB_MODE_WRITEONCE, "pintool", "on_stack_context_only", "0", "on stack context only");
KNOB<BOOL> KnobGetSpillAreaContextOnly(KNOB_MODE_WRITEONCE, "pintool", "spill_area_context_only", "0", "spillArea context only");
KNOB<BOOL> KnobContextAtTrace(KNOB_MODE_WRITEONCE, "pintool", "context_at_trace", "1", "context at trace");
KNOB<BOOL> KnobContextAtIns(KNOB_MODE_WRITEONCE, "pintool", "context_at_ins", "0", "context at ins");
BOOL supportsAvx;
extern "C" BOOL ProcessorSupportsAvx();
// The tool assumes single-threaded application.
// This may not be the case on Windows 10.
// We arbitrary choose single thread to profile.
THREADID myThread = INVALID_THREADID;
ADDRINT IfMyThread(THREADID threadId)
{
// Profile only single thread at any time
return threadId == myThread;
}
VOID ThreadStart(THREADID tid, CONTEXT *ctxt, INT32 flags, VOID *v)
{
// Determine single thread to profile.
if (myThread == INVALID_THREADID) myThread = tid;
}
static char nibble_to_ascii_hex(UINT8 i) {
if (i<10) return i+'0';
if (i<16) return i-10+'A';
return '?';
}
static void print_hex_line(char* buf, const UINT8* array, const int length) {
int n = length;
int i=0;
if (length == 0)
n = XED_MAX_INSTRUCTION_BYTES;
for( i=0 ; i< n; i++) {
buf[2*i+0] = nibble_to_ascii_hex(array[i]>>4);
buf[2*i+1] = nibble_to_ascii_hex(array[i]&0xF);
}
buf[2*i]=0;
}
static string
disassemble(UINT64 start, UINT64 stop) {
UINT64 pc = start;
xed_state_t dstate;
xed_syntax_enum_t syntax = XED_SYNTAX_INTEL;
xed_error_enum_t xed_error;
xed_decoded_inst_t xedd;
ostringstream os;
if (sizeof(ADDRINT) == 4)
xed_state_init(&dstate,
XED_MACHINE_MODE_LEGACY_32,
XED_ADDRESS_WIDTH_32b,
XED_ADDRESS_WIDTH_32b);
else
xed_state_init(&dstate,
XED_MACHINE_MODE_LONG_64,
XED_ADDRESS_WIDTH_64b,
XED_ADDRESS_WIDTH_64b);
/*while( pc < stop )*/ {
xed_decoded_inst_zero_set_mode(&xedd, &dstate);
UINT32 len = 15;
if (stop - pc < 15)
len = stop-pc;
xed_error = xed_decode(&xedd, reinterpret_cast<const UINT8*>(pc), len);
bool okay = (xed_error == XED_ERROR_NONE);
iostream::fmtflags fmt = os.flags();
os << std::setfill('0')
<< "XDIS "
<< std::hex
<< std::setw(sizeof(ADDRINT)*2)
<< pc
<< std::dec
<< ": "
<< std::setfill(' ')
<< std::setw(4);
if (okay) {
char buffer[200];
unsigned int dec_len, sp;
os << xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xedd));
dec_len = xed_decoded_inst_get_length(&xedd);
print_hex_line(buffer, reinterpret_cast<UINT8*>(pc), dec_len);
os << " " << buffer;
for ( sp=dec_len; sp < 12; sp++) // pad out the instruction bytes
os << " ";
os << " ";
memset(buffer,0,200);
int dis_okay = xed_format_context(syntax, &xedd, buffer, 200, pc, 0, 0);
if (dis_okay)
os << buffer << endl;
else
os << "Error disasassembling pc 0x" << std::hex << pc << std::dec << endl;
pc += dec_len;
}
else { // print the byte and keep going.
UINT8 memval = *reinterpret_cast<UINT8*>(pc);
os << "???? " // no extension
<< std::hex
<< std::setw(2)
<< std::setfill('0')
<< static_cast<UINT32>(memval)
<< std::endl;
pc += 1;
}
os.flags(fmt);
}
return os.str();
}
ADDRINT eaxReg;
VOID GetIntRegsFromContext (CONTEXT *ctxt)
{
PIN_GetContextReg( ctxt, REG_INST_PTR );
PIN_GetContextReg( ctxt, REG_GAX );
PIN_GetContextReg( ctxt, REG_GBX );
if (KnobGetPartOfIntContext)
{
return;
}
PIN_GetContextReg( ctxt, REG_GCX );
PIN_GetContextReg( ctxt, REG_GDX) ;
PIN_GetContextReg( ctxt, REG_GSI );
PIN_GetContextReg( ctxt, REG_GDI );
PIN_GetContextReg( ctxt, REG_GBP );
PIN_GetContextReg( ctxt, REG_STACK_PTR );
PIN_GetContextReg( ctxt, REG_SEG_SS );
PIN_GetContextReg( ctxt, REG_SEG_CS );
PIN_GetContextReg( ctxt, REG_SEG_DS) ;
PIN_GetContextReg( ctxt, REG_SEG_ES );
PIN_GetContextReg( ctxt, REG_SEG_FS) ;
PIN_GetContextReg( ctxt, REG_SEG_GS );
PIN_GetContextReg( ctxt, REG_GFLAGS );
#ifdef TARGET_IA32E
PIN_GetContextReg( ctxt, REG_R8 );
PIN_GetContextReg( ctxt, REG_R9 );
PIN_GetContextReg( ctxt, REG_R10 );
PIN_GetContextReg( ctxt, REG_R11 );
PIN_GetContextReg( ctxt, REG_R12 );
PIN_GetContextReg( ctxt, REG_R13 );
PIN_GetContextReg( ctxt, REG_R14 );
PIN_GetContextReg( ctxt, REG_R15 );
#endif
}
CHAR fpContextSpaceForFpConextFromPin[FPSTATE_SIZE+FPSTATE_ALIGNMENT];
VOID GetFpContextFromContext (CONTEXT *ctxt)
{
FPSTATE *fpContextFromPin =
reinterpret_cast<FPSTATE *>
(( reinterpret_cast<ADDRINT>(fpContextSpaceForFpConextFromPin) + (FPSTATE_ALIGNMENT - 1))
& (-FPSTATE_ALIGNMENT));
PIN_GetContextFPState(ctxt, fpContextFromPin);
}
BOOL CompareIntContext (CONTEXT *context1, CONTEXT *context2)
{
BOOL compareOk = TRUE;
ADDRINT regInstPtr1 = PIN_GetContextReg( context1, REG_INST_PTR );
ADDRINT regInstPtr2 = PIN_GetContextReg( context2, REG_INST_PTR );
if (regInstPtr1 != regInstPtr2)
{
printf ("REG_INST_PTR %p REG_INST_PTR %p\n",
reinterpret_cast<VOID *>(regInstPtr1), reinterpret_cast<VOID *>(regInstPtr2));
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GAX ) != PIN_GetContextReg( context2, REG_GAX ))
{
printf ("REG_GAX ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GBX ) != PIN_GetContextReg( context2, REG_GBX ))
{
printf ("REG_GBX ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GCX ) != PIN_GetContextReg( context2, REG_GCX ))
{
printf ("REG_GCX ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GDX ) != PIN_GetContextReg( context2, REG_GDX ))
{
printf ("REG_GDX ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GSI ) != PIN_GetContextReg( context2, REG_GSI ))
{
printf ("REG_GSI ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GDI ) != PIN_GetContextReg( context2, REG_GDI ))
{
printf ("REG_GDI ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GBP ) != PIN_GetContextReg( context2, REG_GBP ))
{
printf ("REG_GBP ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_STACK_PTR ) != PIN_GetContextReg( context2, REG_STACK_PTR ))
{
printf ("REG_STACK_PTR ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_SEG_SS ) != PIN_GetContextReg( context2, REG_SEG_SS ))
{
printf ("REG_SEG_SS ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_SEG_CS ) != PIN_GetContextReg( context2, REG_SEG_CS ))
{
printf ("REG_SEG_CS ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_SEG_DS ) != PIN_GetContextReg( context2, REG_SEG_DS ))
{
printf ("REG_SEG_DS ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_SEG_ES ) != PIN_GetContextReg( context2, REG_SEG_ES ))
{
printf ("REG_SEG_ES ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_SEG_FS ) != PIN_GetContextReg( context2, REG_SEG_FS ))
{
ADDRINT fs1 = PIN_GetContextReg( context1, REG_SEG_FS );
ADDRINT fs2 = PIN_GetContextReg( context2, REG_SEG_FS );
if ( (fs1&(~0x3)) != (fs2&(~0x3)))
{ // rpl of fs may be changed without Pin noticing - e.g. printf changes rpl
printf ("REG_SEG_FS ERROR\n");
compareOk = FALSE;
}
}
if (PIN_GetContextReg( context1, REG_SEG_GS ) != PIN_GetContextReg( context2, REG_SEG_GS ))
{
ADDRINT gs1 = PIN_GetContextReg( context1, REG_SEG_GS );
ADDRINT gs2 = PIN_GetContextReg( context2, REG_SEG_GS );
if ( (gs1&(~0x3)) != (gs2&(~0x3)))
{ // rpl of gs may be changed without Pin noticing - e.g. printf changes rpl
printf ("REG_SEG_GS ERROR\n");
compareOk = FALSE;
}
}
if (PIN_GetContextReg( context1, REG_SEG_GS_BASE ) != PIN_GetContextReg( context2, REG_SEG_GS_BASE ))
{
printf ("REG_SEG_GS_BASE ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_SEG_FS_BASE ) != PIN_GetContextReg( context2, REG_SEG_FS_BASE ))
{
printf ("REG_SEG_FS_BASE ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_GFLAGS ) != PIN_GetContextReg( context2, REG_GFLAGS ))
{
printf ("REG_GFLAGS ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G0 ) != PIN_GetContextReg( context2, REG_INST_G0 ))
{
printf ("REG_INST_G0 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G1) != PIN_GetContextReg( context2, REG_INST_G1 ))
{
printf ("REG_INST_G1 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G2) != PIN_GetContextReg( context2, REG_INST_G2 ))
{
printf ("REG_INST_G2 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G3) != PIN_GetContextReg( context2, REG_INST_G3 ))
{
printf ("REG_INST_G3 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G4) != PIN_GetContextReg( context2, REG_INST_G4 ))
{
printf ("REG_INST_G4 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G5) != PIN_GetContextReg( context2, REG_INST_G5 ))
{
printf ("REG_INST_G5 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G6) != PIN_GetContextReg( context2, REG_INST_G6 ))
{
printf ("REG_INST_G6 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G7) != PIN_GetContextReg( context2, REG_INST_G7 ))
{
printf ("REG_INST_G7 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G8) != PIN_GetContextReg( context2, REG_INST_G8 ))
{
printf ("REG_INST_G8 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_INST_G9) != PIN_GetContextReg( context2, REG_INST_G9 ))
{
printf ("REG_INST_G9 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE0) != PIN_GetContextReg( context2, REG_BUF_BASE0 ))
{
printf ("REG_BUF_BASE0 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE1) != PIN_GetContextReg( context2, REG_BUF_BASE1 ))
{
printf ("REG_BUF_BASE1 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE2) != PIN_GetContextReg( context2, REG_BUF_BASE2 ))
{
printf ("REG_BUF_BASE2 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE3) != PIN_GetContextReg( context2, REG_BUF_BASE3 ))
{
printf ("REG_BUF_BASE3 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE4) != PIN_GetContextReg( context2, REG_BUF_BASE4 ))
{
printf ("REG_BUF_BASE4 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE5) != PIN_GetContextReg( context2, REG_BUF_BASE5 ))
{
printf ("REG_BUF_BASE5 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE6) != PIN_GetContextReg( context2, REG_BUF_BASE6 ))
{
printf ("REG_BUF_BASE6 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE7) != PIN_GetContextReg( context2, REG_BUF_BASE7 ))
{
printf ("REG_BUF_BASE7 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE8) != PIN_GetContextReg( context2, REG_BUF_BASE8 ))
{
printf ("REG_BUF_BASE8 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_BASE9) != PIN_GetContextReg( context2, REG_BUF_BASE9 ))
{
printf ("REG_BUF_BASE9 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END0) != PIN_GetContextReg( context2, REG_BUF_END0 ))
{
printf ("REG_BUF_END0 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END1) != PIN_GetContextReg( context2, REG_BUF_END1 ))
{
printf ("REG_BUF_END1 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END2) != PIN_GetContextReg( context2, REG_BUF_END2 ))
{
printf ("REG_BUF_END2 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END3) != PIN_GetContextReg( context2, REG_BUF_END3 ))
{
printf ("REG_BUF_END3 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END4) != PIN_GetContextReg( context2, REG_BUF_END4 ))
{
printf ("REG_BUF_END4 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END5) != PIN_GetContextReg( context2, REG_BUF_END5 ))
{
printf ("REG_BUF_END5 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END6) != PIN_GetContextReg( context2, REG_BUF_END6 ))
{
printf ("REG_BUF_END6 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END7) != PIN_GetContextReg( context2, REG_BUF_END7 ))
{
printf ("REG_BUF_END7 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END8) != PIN_GetContextReg( context2, REG_BUF_END8 ))
{
printf ("REG_BUF_END8 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_BUF_END9) != PIN_GetContextReg( context2, REG_BUF_END9 ))
{
printf ("REG_BUF_END9 ERROR\n");
compareOk = FALSE;
}
#ifdef TARGET_IA32E
if (PIN_GetContextReg( context1, REG_R8 ) != PIN_GetContextReg( context2, REG_R8 ))
{
printf ("REG_R8 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R9 ) != PIN_GetContextReg( context2, REG_R9 ))
{
printf ("REG_R9 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R10 ) != PIN_GetContextReg( context2, REG_R10 ))
{
printf ("REG_R10 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R11 ) != PIN_GetContextReg( context2, REG_R11 ))
{
printf ("REG_R11 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R12 ) != PIN_GetContextReg( context2, REG_R12 ))
{
printf ("REG_R12 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R13 ) != PIN_GetContextReg( context2, REG_R13 ))
{
printf ("REG_R13 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R14 ) != PIN_GetContextReg( context2, REG_R14 ))
{
printf ("REG_R14 ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_R15 ) != PIN_GetContextReg( context2, REG_R15 ))
{
printf ("REG_R15 ERROR\n");
compareOk = FALSE;
}
#endif
// short fp regs
if (PIN_GetContextReg( context1, REG_FPCW ) != PIN_GetContextReg( context2, REG_FPCW ))
{
printf ("REG_FPCW ERRO\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_FPSW ) != PIN_GetContextReg( context2, REG_FPSW ))
{
printf ("REG_FPSW ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_FPTAG ) != PIN_GetContextReg( context2, REG_FPTAG ))
{
printf ("REG_FPTAG ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_FPTAG_FULL ) != PIN_GetContextReg( context2, REG_FPTAG_FULL ))
{
printf ("REG_FPTAG_FULL ERROR\n");
compareOk = FALSE;
}
#if 0
// these appear to change unexpectedly
if (PIN_GetContextReg( context1, REG_FPIP_SEL ) != PIN_GetContextReg( context2, REG_FPIP_SEL ))
{
printf ("REG_FPIP_SEL ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_FPDP_SEL ) != PIN_GetContextReg( context2, REG_FPDP_SEL ))
{
printf ("REG_FPDP_SEL ERROR\n");
compareOk = FALSE;
}
#endif
if (PIN_GetContextReg( context1, REG_FPIP_OFF ) != PIN_GetContextReg( context2, REG_FPIP_OFF ))
{
printf ("REG_FPIP_OFF ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_FPDP_OFF ) != PIN_GetContextReg( context2, REG_FPDP_OFF ))
{
printf ("REG_FPDP_OFF ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_FPOPCODE ) != PIN_GetContextReg( context2, REG_FPOPCODE ))
{
printf ("REG_FPOPCODE ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_MXCSR ) != PIN_GetContextReg( context2, REG_MXCSR ))
{
printf ("REG_MXCSR ERROR\n");
compareOk = FALSE;
}
if (PIN_GetContextReg( context1, REG_MXCSRMASK ) != PIN_GetContextReg( context2, REG_MXCSRMASK ))
{
printf ("REG_MXCSRMASK ERROR\n");
compareOk = FALSE;
}
if (!compareOk)
{
string s = disassemble ((regInstPtr1),(regInstPtr1)+15);
printf ("Failure at %p: %s\n", reinterpret_cast<VOID *>(regInstPtr1), s.c_str());
}
return (compareOk);
}
BOOL CompareFpContext(CONTEXT *context1, CONTEXT *context2)
{
ADDRINT regInstPtr1 = PIN_GetContextReg( context1, REG_INST_PTR );
BOOL compareOk = TRUE;
CHAR fpContext1[FPSTATE_SIZE];
CHAR fpContext2[FPSTATE_SIZE];
FPSTATE *fpVerboseContext1, *fpVerboseContext2;
fpVerboseContext1 = reinterpret_cast <FPSTATE *>(fpContext1);
fpVerboseContext2 = reinterpret_cast <FPSTATE *>(fpContext2);
PIN_GetContextFPState(context1, fpVerboseContext1);
PIN_GetContextFPState(context2, fpVerboseContext2);
if ( fpVerboseContext1->fxsave_legacy._fcw != fpVerboseContext2->fxsave_legacy._fcw)
{
printf ("fcw ERROR\n");
compareOk = FALSE;
}
if ( fpVerboseContext1->fxsave_legacy._fsw != fpVerboseContext2->fxsave_legacy._fsw)
{
printf ("_fsw ERROR\n");
compareOk = FALSE;
}
if ( fpVerboseContext1->fxsave_legacy._ftw != fpVerboseContext2->fxsave_legacy._ftw)
{
printf ("_ftw ERROR\n");
compareOk = FALSE;
}
if ( fpVerboseContext1->fxsave_legacy._fop != fpVerboseContext2->fxsave_legacy._fop)
{
printf ("_fop ERROR\n");
compareOk = FALSE;
}
if ( fpVerboseContext1->fxsave_legacy._fpuip != fpVerboseContext2->fxsave_legacy._fpuip)
{
printf ("_fpuip ERROR\n");
compareOk = FALSE;
}
#if 0
/* the _cs field seems to be changing randomly when running 32on64 linux
needs further investigation to prove it is not a Pin bug */
if ( fpVerboseContext1->fxsave_legacy._cs != fpVerboseContext2->fxsave_legacy._cs)
{
printf ("_cs ERROR\n");
compareOk = FALSE;
}
/* the _ds field seems to be changing randomly when running 32on64 linux
needs further investigation to prove it is not a Pin bug */
if ( fpVerboseContext1->fxsave_legacy._ds != fpVerboseContext2->fxsave_legacy._ds)
{
printf ("_ds ERROR\n");
compareOk = FALSE;
}
#endif
if ( fpVerboseContext1->fxsave_legacy._fpudp != fpVerboseContext2->fxsave_legacy._fpudp)
{
printf ("_fpudp ERROR\n");
compareOk = FALSE;
}
if ( fpVerboseContext1->fxsave_legacy._mxcsr != fpVerboseContext2->fxsave_legacy._mxcsr)
{
printf ("_mxcsr ERROR\n");
compareOk = FALSE;
}
if ( fpVerboseContext1->fxsave_legacy._mxcsrmask != fpVerboseContext2->fxsave_legacy._mxcsrmask)
{
printf ("_mxcsrmask ERROR\n");
compareOk = FALSE;
}
int i;
for (i=0; i< 8; i++)
{
if ((fpVerboseContext1->fxsave_legacy._sts[i]._raw._lo != fpVerboseContext2->fxsave_legacy._sts[i]._raw._lo) ||
(fpVerboseContext1->fxsave_legacy._sts[i]._raw._hi != fpVerboseContext2->fxsave_legacy._sts[i]._raw._hi))
{
printf ("_st[%d] ERROR\n", i);
compareOk = FALSE;
}
}
for (i=0;
#ifdef TARGET_IA32E
i< 16;
#else
i< 8;
#endif
i++)
{
if ((fpVerboseContext1->fxsave_legacy._xmms[i]._vec64[0] != fpVerboseContext2->fxsave_legacy._xmms[i]._vec64[0]) ||
(fpVerboseContext1->fxsave_legacy._xmms[i]._vec64[1] != fpVerboseContext2->fxsave_legacy._xmms[i]._vec64[1]))
{
printf ("_xmm[%d] ERROR\n", i);
fflush (stdout);
compareOk = FALSE;
}
}
if (supportsAvx)
{
int k = 0;
for (int i = 0;
#ifdef TARGET_IA32E
i < 16;
#else
i< 8;
#endif
++i)
{
for (int j=0; j<16; j++)
{
if (fpVerboseContext1->_xstate._ymmUpper[k] != fpVerboseContext2->_xstate._ymmUpper[k])
{
printf ("ymm[%d] ERROR\n", i);
fflush (stdout);
compareOk = FALSE;
}
k++;
}
}
}
if (!compareOk)
{
string s = disassemble ((regInstPtr1),(regInstPtr1)+15);
printf ("Failure at %p: %s\n", reinterpret_cast<VOID *>(regInstPtr1), s.c_str());
}
return (compareOk);
}
CONTEXT contextAtReceive;
ADDRINT mxcsr;
VOID ReceiveContext (CONTEXT *ctxt)
{
if (KnobGetIntContext || KnobGetPartOfIntContext)
{
GetIntRegsFromContext(ctxt);
}
if (KnobGetFpContext)
{
GetFpContextFromContext(ctxt);
}
if (!(KnobOnStackContextOnly || KnobGetSpillAreaContextOnly || !KnobCompareContexts))
{
PIN_SaveContext(ctxt, &contextAtReceive);
}
}
VOID VerifyContext (CONTEXT *contextAtVerify)
{
BOOL successInt = CompareIntContext(contextAtVerify, &contextAtReceive);
BOOL successFp = CompareFpContext(contextAtVerify, &contextAtReceive);
if (!successInt || !successFp)
{
exit(-1);
}
}
VOID Trace(TRACE trace, VOID *v)
{
if (KnobCompareContexts)
{
TRACE_InsertIfCall(trace, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
TRACE_InsertThenCall(trace, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONST_CONTEXT, IARG_END);
TRACE_InsertIfCall(trace, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
TRACE_InsertThenCall(trace, IPOINT_BEFORE, (AFUNPTR) VerifyContext, IARG_CONTEXT, IARG_END);
if (KnobCompareReverseContexts)
{
TRACE_InsertIfCall(trace, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
TRACE_InsertThenCall(trace, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONTEXT, IARG_END);
TRACE_InsertIfCall(trace, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
TRACE_InsertThenCall(trace, IPOINT_BEFORE, (AFUNPTR) VerifyContext, IARG_CONST_CONTEXT, IARG_END);
}
}
else if (KnobOnStackContextOnly)
{
TRACE_InsertIfCall(trace, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
TRACE_InsertThenCall(trace, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONTEXT, IARG_END);
}
else if (KnobGetSpillAreaContextOnly)
{
TRACE_InsertIfCall(trace, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
TRACE_InsertThenCall(trace, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONST_CONTEXT, IARG_END);
}
}
VOID Instruction(INS ins, VOID *v)
{
if (KnobCompareContexts)
{
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONTEXT, IARG_END);
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR) VerifyContext, IARG_CONST_CONTEXT, IARG_END);
if (KnobCompareReverseContexts)
{
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONST_CONTEXT, IARG_END);
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR) VerifyContext, IARG_CONTEXT, IARG_END);
}
}
else if (KnobOnStackContextOnly)
{
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONTEXT, IARG_END);
}
else if (KnobGetSpillAreaContextOnly)
{
INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(IfMyThread), IARG_THREAD_ID, IARG_END);
INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR) ReceiveContext, IARG_CONST_CONTEXT, IARG_END);
}
}
int main(int argc, char *argv[])
{
PIN_Init(argc,argv);
if (KnobContextAtTrace)
{
TRACE_AddInstrumentFunction(Trace, 0);
}
if (KnobContextAtIns)
{
INS_AddInstrumentFunction(Instruction, 0);
}
// Add callbacks
PIN_AddThreadStartFunction(ThreadStart, 0);
supportsAvx = ProcessorSupportsAvx();
// Never returns
PIN_StartProgram();
return 0;
}