/* * 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" using std::endl; UINT64 icount = 0; UINT64 error = 0; VOID * pc = 0; VOID * next_pc = 0; BOOL isSkipped = TRUE;// always skip checking the first inst VOID CountError() { error++; if (error > 100) { std::cerr << "Too many errors, giving up" << endl; exit(error); } } VOID CheckPc(VOID * iaddr) { if (next_pc != iaddr && !isSkipped) { std::cerr << "error: at PC " << pc << " computed target " << next_pc << " but executing at " << iaddr << endl; CountError(); } isSkipped = FALSE; icount++; if ((icount % 1000) == 0) { std::cerr << icount << " BBLs checked" << endl; } } // record PC of following instruction VOID RecordPc(VOID * iaddr, VOID * target, BOOL taken) { if (!taken) return; pc = iaddr; next_pc = target; } VOID Skip() { isSkipped = TRUE; } VOID Trace(TRACE trace, VOID *v) { static BOOL programStart = TRUE; if (programStart) { programStart = FALSE; next_pc = (void*)INS_Address(BBL_InsHead(TRACE_BblHead(trace))); } for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // check BBL entry PC INS_InsertCall( BBL_InsHead(bbl), IPOINT_BEFORE, (AFUNPTR)CheckPc, IARG_INST_PTR, IARG_END); INS tail = BBL_InsTail(bbl); if (INS_IsControlFlow(tail)) { // record taken branch targets INS_InsertCall( tail, IPOINT_BEFORE, AFUNPTR(RecordPc), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } if (INS_IsValidForIpointAfter(tail)) { // record fall-through INS_InsertCall( tail, IPOINT_AFTER, (AFUNPTR)RecordPc, IARG_INST_PTR, IARG_FALLTHROUGH_ADDR, IARG_BOOL, TRUE, IARG_END); } #if defined(TARGET_IA32) || defined(TARGET_IA32E) if (INS_IsSysenter(tail) || INS_HasRealRep(tail)) { // sysenter on x86 has some funny control flow that we can't correctly verify for now // Genuinely REP prefixed instructions are also odd, they appear to stutter. INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)Skip, IARG_END); } #endif } } VOID SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) { Skip(); } VOID Fini(INT32 code, VOID *v) { std::cerr << error << " errors (" << icount << " BBLs checked)" << endl; if (code) exit(code); if (error > 0) exit(error); } int main(INT32 argc, CHAR **argv) { PIN_Init(argc, argv); TRACE_AddInstrumentFunction(Trace, 0); PIN_AddSyscallEntryFunction(SyscallEntry, 0); PIN_AddFiniFunction(Fini, 0); // Never returns PIN_StartProgram(); return 0; }