Я использую Intel-Pin для инструментов pthread_mutex_lock
и pthread_mutex_unlock
в Linux. Я вставляю функции до и после вызова этих двух функций блокировки соответственно, поэтому я ожидаю, что инструмент будет выводить строки до и после функций блокировки.
Код инструмента следующий
#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