0
我使用Intel-Pin来测试Linux中的pthread_mutex_lock
和pthread_mutex_unlock
。我分别在这两个锁定函数的调用之前和之后插入函数,所以我期望该工具将在锁定函数之前和之后输出字符串。
该仪器代码是作为遵循为什么在Pin中不能调用某个回调函数?
#include "pin.H"
#include <iostream>
#include <fstream>
/* ===================================================================== */
/* Names of pthread_mutex_lock and pthread_mutex_unlock */
/* ===================================================================== */
#define PTHREAD_MUTEX_INIT "pthread_mutex_init"
#define PTHREAD_MUTEX_DESTROY "pthread_mutex_destroy"
#define PTHREAD_MUTEX_LOCK "pthread_mutex_lock"
#define PTHREAD_MUTEX_UNLOCK "pthread_mutex_unlock"
/* ===================================================================== */
/* Global Variables */
/* ===================================================================== */
PIN_LOCK lock;
std::ofstream TraceFile;
/* ===================================================================== */
/* Commandline Switches */
/* ===================================================================== */
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "malloctrace.out", "specify trace file name");
/* ===================================================================== */
/* ===================================================================== */
/* Analysis routines */
/* ===================================================================== */
VOID Pthread_mutex_lock_callBefore(ADDRINT lockaddr)
{
PIN_GetLock(&lock, 1);
printf("Pthread_mutex_lock_callBefore\n");
PIN_ReleaseLock(&lock);
}
VOID Pthread_mutex_lock_callAfter(ADDRINT ret)
{
if(ret != 0)
return;
PIN_GetLock(&lock, 2);
printf("Pthread_mutex_lock_callAfter\n");
PIN_ReleaseLock(&lock);
}
VOID Pthread_mutex_unlock_callBefore(ADDRINT lockaddr)
{
PIN_GetLock(&lock, 3);
printf("Pthread_mutex_unlock_callBefore\n");
PIN_ReleaseLock(&lock);
}
static VOID Pthread_mutex_unlock_callAfter(ADDRINT ret)
{
if(ret != 0)
return;
PIN_GetLock(&lock, 4);
printf("Pthread_mutex_unlock_callAfter\n");
PIN_ReleaseLock(&lock);
}
/* ===================================================================== */
/* Instrumentation routines */
/* ===================================================================== */
VOID Image(IMG img, VOID *v)
{
RTN pmlRtn = RTN_FindByName(img, PTHREAD_MUTEX_LOCK);
if (RTN_Valid(pmlRtn) && PIN_IsApplicationThread())
{
RTN_Open(pmlRtn);
RTN_InsertCall(pmlRtn, IPOINT_BEFORE, (AFUNPTR)Pthread_mutex_lock_callBefore,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_END);
RTN_InsertCall(pmlRtn, IPOINT_AFTER, (AFUNPTR)Pthread_mutex_lock_callAfter,
IARG_FUNCRET_EXITPOINT_VALUE,
IARG_END);
RTN_Close(pmlRtn);
}
//pthread_mutex_unlock
pmlRtn = RTN_FindByName(img, PTHREAD_MUTEX_UNLOCK);
if (RTN_Valid(pmlRtn))
{
RTN_Open(pmlRtn);
RTN_InsertCall(pmlRtn, IPOINT_BEFORE, (AFUNPTR)Pthread_mutex_unlock_callBefore,
IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
IARG_END);
RTN_InsertCall(pmlRtn, IPOINT_AFTER, (AFUNPTR)Pthread_mutex_unlock_callAfter,
IARG_FUNCRET_EXITPOINT_VALUE,
IARG_END);
RTN_Close(pmlRtn);
}
}
/* ===================================================================== */
VOID Fini(INT32 code, VOID *v)
{
TraceFile.close();
}
/* ===================================================================== */
/* Print Help Message */
/* ===================================================================== */
INT32 Usage()
{
cerr << "This tool produces a trace of calls to malloc." << endl;
cerr << endl << KNOB_BASE::StringKnobSummary() << endl;
return -1;
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
int main(int argc, char *argv[])
{
// Initialize pin & symbol manager
PIN_InitLock(&lock);
PIN_InitSymbols();
if(PIN_Init(argc,argv))
{
return Usage();
}
// Write to a file since cout and cerr maybe closed by the application
TraceFile.open(KnobOutputFile.Value().c_str());
TraceFile << hex;
TraceFile.setf(ios::showbase);
// Register Image to be called to instrument functions.
IMG_AddInstrumentFunction(Image, 0);
PIN_AddFiniFunction(Fini, 0);
// Never returns
PIN_StartProgram();
return 0;
}
/* ===================================================================== */
/* eof */
/* ===================================================================== */
编译此工具
make obj-ia32/mytool.so TARGET=ia32
使用此工具器械一个简单的测试
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t m;
void * fun1(void *arg)
{
pthread_mutex_lock(&m);
pthread_mutex_unlock(&m);
}
int main(int argc,char* argv[])
{
pthread_t npid1;
pthread_mutex_init(&m,NULL);
pthread_create(&npid1,NULL,fun1,NULL);
pthread_join(npid1,NULL);
return 0;
}
编译此测试
gcc -g t.c -o t -lpthread
最后,我用我的工具仪器这个测试
sudo ./pin -t obj-ia32/mytool.so -- ./t
结果是
[email protected]:~/MyPinTool$ sudo ./pin -t obj-ia32/mytool.so -- ./t
Pthread_mutex_lock_callBefore
Pthread_mutex_lock_callAfter
Pthread_mutex_unlock_callBefore
Pthread_mutex_lock_callBefore
Pthread_mutex_lock_callAfter
Pthread_mutex_unlock_callBefore
Pthread_mutex_lock_callBefore
Pthread_mutex_lock_callAfter
Pthread_mutex_unlock_callBefore
你可以看到有没有Pthread_mutex_unlock_callAfter
,我有调用pthread_mutex_unlock后插入函数,为什么这个功能还没有被召唤?
PS:引脚API说
VOID LEVEL_PINCLIENT::RTN_InsertCall ( RTN rtn,
IPOINT action,
AFUNPTR funptr,
...
)
Insert call relative to a rtn.
Parameters:
rtn Routine to instrument
action Use IPOINT_BEFORE to call funptr before execution, or IPOINT_AFTER for immediately before the return NOTE: IPOINT_AFTER is implemented by instrumenting each return instruction in a routine. Pin tries to find all return instructions, but success is not guaranteed
funptr Analysis function to call
... IARG_TYPE. Arguments to pass to funptr
api参考文献中的NOTE已经表明:pin尽最大努力来测试ipoint_after,但不能保证。如果您希望在回调之前和之后保证,请使用RTN替换API。 – nitzanms
@nitzanms我是使用Pin的新人,对我来说使用它有很多问题。非常感谢你。如果我有一些问题,我可以在哪里询问有关Pin的问题? – wangxf
当然你可以在这里问,但你也可以在Pinheads中找到很多有用的信息,Pin用户的支持小组:https://groups.yahoo.com/neo/groups/pinheads/info – nitzanms