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.
152 lines
4.2 KiB
152 lines
4.2 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.
|
|
*/
|
|
|
|
/*
|
|
* Emulate instruction that implicitly touch the stack:
|
|
* push, pop, leave.
|
|
* call and return
|
|
*/
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
#include <set>
|
|
#include "pin.H"
|
|
using std::hex;
|
|
using std::string;
|
|
using std::endl;
|
|
|
|
KNOB<UINT32> KnobDetach(KNOB_MODE_WRITEONCE, "pintool", "d", "-1", "stop tracing at this point");
|
|
KNOB<BOOL> KnobLog(KNOB_MODE_WRITEONCE, "pintool", "l", "0", "log all instructions");
|
|
|
|
static UINT32 scount = 0;
|
|
static REG scratchReg;
|
|
static std::set<ADDRINT> branchTakenIns;
|
|
FILE *out = 0;
|
|
|
|
VOID PrintIns(void *p, const char *s)
|
|
{
|
|
if(!out)
|
|
return;
|
|
|
|
fprintf(out, "%6d: %p %s\n", scount, p, s);
|
|
fflush(out);
|
|
}
|
|
|
|
ADDRINT EmuIndJmp(ADDRINT tgtip)
|
|
{
|
|
return tgtip;
|
|
}
|
|
|
|
VOID BranchBefore(THREADID tid, ADDRINT pc)
|
|
{
|
|
if (0 != tid) return;
|
|
branchTakenIns.insert(pc);
|
|
}
|
|
|
|
VOID BranchTaken(THREADID tid, ADDRINT pc, ADDRINT expected)
|
|
{
|
|
if (0 != tid) return;
|
|
ASSERT(pc == expected, "pc = " + hexstr(pc) + "INS_Address() = " + hexstr(expected));
|
|
branchTakenIns.erase(pc);
|
|
}
|
|
|
|
VOID Ins( INS ins, VOID *v )
|
|
{
|
|
if (KnobDetach > 0 && scount > KnobDetach)
|
|
return;
|
|
|
|
if (KnobLog)
|
|
{
|
|
void *addr = Addrint2VoidStar(INS_Address(ins));
|
|
string disasm = INS_Disassemble(ins);
|
|
PrintIns(addr, disasm.c_str());
|
|
}
|
|
|
|
scount++;
|
|
|
|
// call and return need also stack manipulation (see emu_stack.cpp)
|
|
// conditional jumps need handling the condition (not supported yet)
|
|
if (INS_IsCall(ins) || INS_IsRet(ins) || INS_Category(ins) == XED_CATEGORY_COND_BR)
|
|
return;
|
|
|
|
if (INS_IsIndirectControlFlow(ins))
|
|
{
|
|
INS_InsertCall(ins, IPOINT_BEFORE,
|
|
AFUNPTR(EmuIndJmp),
|
|
IARG_BRANCH_TARGET_ADDR,
|
|
IARG_RETURN_REGS, scratchReg, IARG_END);
|
|
|
|
INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg);
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)BranchBefore, IARG_THREAD_ID, IARG_INST_PTR, IARG_END);
|
|
INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)BranchTaken, IARG_THREAD_ID, IARG_INST_PTR, IARG_ADDRINT, INS_Address(ins), IARG_END);
|
|
|
|
INS_Delete(ins);
|
|
}
|
|
else if (INS_IsDirectControlFlow(ins))
|
|
{
|
|
ADDRINT tgt = INS_DirectControlFlowTargetAddress(ins);
|
|
|
|
INS_InsertDirectJump(ins, IPOINT_AFTER, tgt);
|
|
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)BranchBefore, IARG_THREAD_ID, IARG_INST_PTR, IARG_END);
|
|
INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)BranchTaken, IARG_THREAD_ID, IARG_INST_PTR, IARG_ADDRINT, INS_Address(ins), IARG_END);
|
|
|
|
INS_Delete(ins);
|
|
}
|
|
}
|
|
|
|
VOID Fini(INT32 code, VOID *v)
|
|
{
|
|
if (!branchTakenIns.empty())
|
|
{
|
|
for (std::set<ADDRINT>::iterator it = branchTakenIns.begin(); it != branchTakenIns.end(); it++)
|
|
{
|
|
std::cerr << "Instrumentation for IPOINT_TAKEN_BRANCH for instruction at " << hex << *it << " wasn't executed" << endl;
|
|
}
|
|
ASSERTX(FALSE);
|
|
}
|
|
if (out)
|
|
fclose(out);
|
|
}
|
|
|
|
// argc, argv are the entire command line, including pin -t <toolname> -- ...
|
|
int main(int argc, char * argv[])
|
|
{
|
|
// Initialize pin
|
|
PIN_Init(argc, argv);
|
|
|
|
if (KnobLog)
|
|
{
|
|
out = fopen("emu_jumps.txt", "w");
|
|
if (!out)
|
|
fprintf(stderr, "Can't open log file emu_jumps.txt\n");
|
|
}
|
|
|
|
scratchReg = PIN_ClaimToolRegister();
|
|
if (!REG_valid(scratchReg))
|
|
{
|
|
if (out)
|
|
fprintf (out, "Cannot allocate a scratch register.\n");
|
|
fprintf (stderr, "Cannot allocate a scratch register.\n");
|
|
return 1;
|
|
}
|
|
|
|
// Register instruction instrumentation callback.
|
|
INS_AddInstrumentFunction(Ins, 0);
|
|
|
|
// Register Fini to be called when the application exits
|
|
PIN_AddFiniFunction(Fini, 0);
|
|
|
|
// Start the program, never returns
|
|
PIN_StartProgram();
|
|
|
|
return 0;
|
|
}
|
|
|