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.

196 lines
5.4 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 <fstream>
#include <unistd.h>
#include <sched.h>
using std::hex;
using std::dec;
using std::cerr;
/* Test PIN_SpawnThreadAndExecuteAt in a simple tool.
* Can be run on any target application, since it only executes a few
* instructions from there.
*/
static KNOB<BOOL> KnobVerbose(KNOB_MODE_WRITEONCE,
"pintool",
"v",
"0",
"Output verbose information");
static KNOB<BOOL> KnobFromCallback(KNOB_MODE_WRITEONCE,
"pintool",
"c",
"0",
"Create threads in callback, rather than analysis functions");
static UINT32 threadsCreated = 0;
static ADDRINT threadFunction= 0;
// MAXTHREADS includes the static thread that starts the world, so must be >=2 to test anything!
#define MAXTHREADS 2
#define STACKSIZE 1024
static VOID cloneThread(CONTEXT * ctxt)
{
// Should maybe use atomic increment here, but if we create a few bonus ones, it
// doesn't really matter!
UINT32 threadId = ++threadsCreated;
if (threadId >= MAXTHREADS)
return;
CONTEXT localContext;
if (!ctxt)
{
ctxt = &localContext;
PIN_SetContextReg(ctxt, REG_GFLAGS, 0);
}
if (!PIN_SpawnApplicationThread(ctxt))
{
cerr << "PIN_SpawnApplicationThread failed\n";
PIN_ExitProcess(-1);
}
if (KnobVerbose)
cerr << "Spawned a new thread (" << threadId << ")\n";
}
static VOID ThreadCreateCallback(THREADID tid, CONTEXT * ctxt, INT32 flags, VOID * v)
{
if (KnobVerbose)
cerr << "Thread create callback for " << tid << "\n";
// First thread is static, we don't want to mangle it, but we do create a new thread
// from the callback.
if (KnobFromCallback)
{
ADDRINT * stack = new ADDRINT [1024];
CONTEXT context;
ctxt = &context;
if (!threadFunction)
{
cerr << "Cannot find 'doNothing()' in application\n";
PIN_ExitProcess(-1);
}
// Fill in sensible values for critical registers.
PIN_SetContextReg(ctxt, REG_STACK_PTR,ADDRINT (&stack[1023]));
PIN_SetContextReg(ctxt, REG_INST_PTR, threadFunction);
PIN_SetContextReg(ctxt, REG_GFLAGS, 0);
cloneThread(ctxt);
}
if (tid >= (MAXTHREADS-1))
{
cerr << "Created all threads OK\n";
PIN_ExitProcess(0);
}
// First thread is created statically, we don't want to mess with it.
if (tid == 0 || KnobFromCallback)
return;
if (!threadFunction)
{
cerr << "Cannot find 'doNothing()' in application\n";
PIN_ExitProcess(-1);
}
ADDRINT * stack = new ADDRINT [1024];
// Fill in sensible values for critical registers.
PIN_SetContextReg(ctxt, REG_STACK_PTR,ADDRINT (&stack[1023]));
PIN_SetContextReg(ctxt, REG_INST_PTR, ADDRINT (&threadFunction));
PIN_SetContextReg(ctxt, REG_GFLAGS, 0);
}
static VOID ThreadExitCallback(THREADID tid, const CONTEXT *ctxt, INT32 code, VOID * v)
{
cerr << "Thread " << tid << " terminated (" << code <<")\n";
if (ctxt)
{
cerr << "Thread " << tid << " IP: " << hex << PIN_GetContextReg(ctxt, REG_INST_PTR) << dec << "\n";
}
}
static VOID ContextChangeCallback(THREADID tid, CONTEXT_CHANGE_REASON reason,
const CONTEXT *from, CONTEXT *to, INT32 info, VOID *v)
{
cerr << "Thread " << tid << " context change " << reason << " info " << info << "\n";
if (from)
{
cerr << "Thread " << tid << " IP: " << hex << PIN_GetContextReg(from, REG_INST_PTR) << dec << "\n";
}
}
static VOID AddInstrumentation(INS ins, VOID *)
{
static INT InstrumentedInstructions = 0;
if (InstrumentedInstructions++ < MAXTHREADS)
{
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)cloneThread,
IARG_ADDRINT, 0,
IARG_END);
}
}
static VOID ImageLoadCallback(IMG img, VOID *v)
{
if (threadFunction == 0)
{
if (KnobVerbose)
cerr << "Looking for doNothing in " << IMG_Name(img) << "\n";
#ifndef TARGET_MAC
RTN rtn = RTN_FindByName (img, "doNothing");
#else
RTN rtn = RTN_FindByName (img, "_doNothing");
#endif
if (RTN_Valid(rtn))
{
threadFunction = RTN_Address(rtn);
if (KnobVerbose)
cerr << "'doNothing' at " << hex << threadFunction << dec << "\n";
}
}
}
int
main(int argc, char *argv[])
{
if(PIN_Init(argc,argv))
{
cerr << "Bad arguments\n";
return -1;
}
PIN_InitSymbols();
IMG_AddInstrumentFunction(ImageLoadCallback, 0);
PIN_AddThreadStartFunction(ThreadCreateCallback, 0);
PIN_AddThreadFiniFunction (ThreadExitCallback, 0);
PIN_AddContextChangeFunction(ContextChangeCallback, 0);
if (!KnobFromCallback)
INS_AddInstrumentFunction (AddInstrumentation, 0);
PIN_StartProgram();
}