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
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();
|
|
}
|