我使用Intel-Pin在Linux中检测pthread_mutex_lock
和pthread_mutex_unlock
。我分别在这两个锁定函数的调用之前和之后插入函数,所以我希望该工具在锁定函数之前和之后输出字符串。
仪器代码如下
#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
结果是
lab@lab:~/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:Pin 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
答案 0 :(得分:0)
正如Nitzan已经说过的那样,API说明了一切:Pin试图检测函数的每个ret指令,但成功并不保证。想想如果在函数内抛出异常会发生什么,或者如果在函数外发生跳远......
在到达return语句之前,函数被中断的原因有很多。