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.
256 lines
7.5 KiB
256 lines
7.5 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.
|
|
*/
|
|
|
|
// This tool test RTN_InsHead RTN_InsHeadOnly and RTN_InsertCall (before)
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "pin.H"
|
|
|
|
UINT32 numThreads = 0;
|
|
const UINT32 MaxNumThreads = 32;
|
|
|
|
struct THREAD_DATA {
|
|
ADDRINT curRtnAddr;
|
|
int numAtRtn;
|
|
int numBeforeInsHeadOnly;
|
|
int numAfterInsHeadOnly;
|
|
int numBeforeInsHead;
|
|
int numAfterInsHead;
|
|
THREAD_DATA() : curRtnAddr(0),
|
|
numAtRtn(0),
|
|
numBeforeInsHeadOnly(0),
|
|
numAfterInsHeadOnly(0),
|
|
numBeforeInsHead(0),
|
|
numAfterInsHead(0) {}
|
|
};
|
|
|
|
// key for accessing TLS storage in the threads. initialized once in main()
|
|
static TLS_KEY tls_key;
|
|
|
|
// function to access thread-specific data
|
|
THREAD_DATA* get_tls(THREADID threadid)
|
|
{
|
|
THREAD_DATA* tdata = static_cast<THREAD_DATA*>(PIN_GetThreadData(tls_key, threadid));
|
|
return tdata;
|
|
}
|
|
|
|
int numRtnsFoundInImageCallback = 0;
|
|
int numRtnsInstrumentedFromImageCallback = 0;
|
|
int numRtnsFoundInRtnCallback = 0;
|
|
|
|
|
|
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
|
|
{
|
|
ASSERT(numThreads == threadid, "Unexpected threadid\n");
|
|
numThreads++;
|
|
ASSERT(numThreads <= MaxNumThreads, "Maximum number of threads exceeded\n");
|
|
THREAD_DATA* tdata = new THREAD_DATA();
|
|
PIN_SetThreadData(tls_key, tdata, threadid);
|
|
}
|
|
|
|
VOID AtRtn(ADDRINT rtnAddr, THREADID tid)
|
|
{
|
|
THREAD_DATA* tdata = get_tls(tid);
|
|
if (tdata->curRtnAddr != 0)
|
|
{
|
|
printf ("**** expected rtnAddr to be 0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
tdata->curRtnAddr = rtnAddr;
|
|
tdata->numAtRtn++;
|
|
}
|
|
|
|
|
|
VOID BeforeInsHeadOnly(ADDRINT insAddr, THREADID tid)
|
|
{
|
|
THREAD_DATA* tdata = get_tls(tid);
|
|
if (tdata->curRtnAddr == 0)
|
|
{
|
|
printf ("**** BeforeInsHeadOnly expected curRtnAddr to be non-0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->curRtnAddr != insAddr)
|
|
{
|
|
printf ("**** BeforeInsHeadOnly got unexpected insAddr\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
tdata->numBeforeInsHeadOnly++;
|
|
}
|
|
|
|
VOID AfterInsHeadOnly(ADDRINT insAddr, THREADID tid)
|
|
{
|
|
THREAD_DATA* tdata = get_tls(tid);
|
|
if (tdata->curRtnAddr == 0)
|
|
{
|
|
printf ("**** AfterInsHeadOnly expected curRtnAddr to be non-0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->curRtnAddr != insAddr)
|
|
{
|
|
printf ("**** AfterInsHeadOnly got unexpected insAddr\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
tdata->numAfterInsHeadOnly++;
|
|
}
|
|
|
|
|
|
VOID BeforeInsHead(ADDRINT insAddr, THREADID tid)
|
|
{
|
|
THREAD_DATA* tdata = get_tls(tid);
|
|
if (tdata->curRtnAddr == 0)
|
|
{
|
|
printf ("**** BeforeInsHead expected curRtnAddr to be non-0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->curRtnAddr != insAddr)
|
|
{
|
|
printf ("**** BeforeInsHead got unexpected insAddr\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
tdata->numBeforeInsHead++;
|
|
}
|
|
|
|
VOID AfterInsHead(ADDRINT insAddr, THREADID tid)
|
|
{
|
|
THREAD_DATA* tdata = get_tls(tid);
|
|
if (tdata->curRtnAddr == 0)
|
|
{
|
|
printf ("**** AfterInsHead expected curRtnAddr to be non-0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->curRtnAddr != insAddr)
|
|
{
|
|
printf ("**** AfterInsHead got unexpected insAddr\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
tdata->numAfterInsHead++;
|
|
tdata->curRtnAddr = 0;
|
|
}
|
|
|
|
|
|
|
|
VOID Image(IMG img, void *v)
|
|
{
|
|
for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
|
|
{
|
|
for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn))
|
|
{
|
|
RTN_Open(rtn);
|
|
numRtnsFoundInImageCallback++;
|
|
INS ins = RTN_InsHeadOnly(rtn);
|
|
if (INS_Invalid() == ins)
|
|
{ // no instruction found - assert that RTN_InsHead(rtn) also doesn't find any INS
|
|
ASSERTX (INS_Invalid() == RTN_InsHead(rtn));
|
|
RTN_Close(rtn);
|
|
continue;
|
|
}
|
|
|
|
if (INS_IsValidForIpointAfter(ins))
|
|
{
|
|
ADDRINT insAddress = INS_Address(ins);
|
|
numRtnsInstrumentedFromImageCallback++;
|
|
RTN_InsertCall( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn), IARG_ADDRINT, RTN_Address(rtn), IARG_THREAD_ID, IARG_END);
|
|
|
|
INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_THREAD_ID, IARG_END);
|
|
INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_THREAD_ID, IARG_END);
|
|
ins = RTN_InsHead(rtn);
|
|
ASSERTX(INS_Invalid() != ins);
|
|
ASSERTX(INS_Address(ins)==insAddress);
|
|
INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHead), IARG_ADDRINT, insAddress, IARG_THREAD_ID, IARG_END);
|
|
INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHead), IARG_ADDRINT, insAddress, IARG_THREAD_ID, IARG_END);
|
|
}
|
|
RTN_Close(rtn);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID Fini (INT32 code, VOID *v)
|
|
{
|
|
if (numRtnsInstrumentedFromImageCallback == 0)
|
|
{
|
|
printf ("***** expected numRtnsInstrumentedFromImageCallback to be > 0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (numRtnsFoundInImageCallback == 0)
|
|
{
|
|
printf ("***** expected numRtnsFoundInImageCallback to be > 0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (numRtnsFoundInImageCallback != numRtnsFoundInRtnCallback)
|
|
{
|
|
printf ("***** expected numRtnsFoundInImageCallback == numRtnsFoundInRtnCallback\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
}
|
|
|
|
// This function is called when the thread exits
|
|
VOID ThreadFini(THREADID threadIndex, const CONTEXT *ctxt, INT32 code, VOID *v)
|
|
{
|
|
THREAD_DATA* tdata = get_tls(threadIndex);
|
|
if (tdata->numAtRtn == 0)
|
|
{
|
|
printf ("***** expected numAtRtn to be > 0\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->numAtRtn != tdata->numBeforeInsHeadOnly)
|
|
{
|
|
printf ("***** expected numAtRtn == numBeforeInsHeadOnly\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->numAtRtn != tdata->numAfterInsHeadOnly)
|
|
{
|
|
printf ("***** expected numAtRtn == numAfterInsHeadOnly\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->numAtRtn != tdata->numBeforeInsHead)
|
|
{
|
|
printf ("***** expected numAtRtn == numBeforeInsHead\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
if (tdata->numAtRtn != tdata->numAfterInsHead)
|
|
{
|
|
printf ("***** expected numAtRtn == numAfterInsHead\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
}
|
|
|
|
VOID Rtn(RTN rtn, VOID *)
|
|
{
|
|
numRtnsFoundInRtnCallback++;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
PIN_Init(argc, argv);
|
|
PIN_InitSymbols();
|
|
|
|
// Obtain a key for TLS storage.
|
|
tls_key = PIN_CreateThreadDataKey(NULL);
|
|
if (-1 == tls_key)
|
|
{
|
|
printf ("number of already allocated keys reached the MAX_CLIENT_TLS_KEYS limit\n");
|
|
PIN_ExitProcess(1);
|
|
}
|
|
|
|
PIN_AddThreadStartFunction(ThreadStart, NULL);
|
|
// Register tFini to be called when thread exits.
|
|
PIN_AddThreadFiniFunction(ThreadFini, NULL);
|
|
IMG_AddInstrumentFunction(Image, NULL);
|
|
RTN_AddInstrumentFunction(Rtn, NULL);
|
|
PIN_AddFiniFunction(Fini, NULL);
|
|
|
|
PIN_StartProgram();
|
|
return 1;
|
|
}
|