为什么在Pin中无法调用某些回调函数?

时间:2015-12-08 12:32:57

标签: linux pthreads intel-pin

我使用Intel-Pin在Linux中检测pthread_mutex_lockpthread_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

1 个答案:

答案 0 :(得分:0)

正如Nitzan已经说过的那样,API说明了一切:Pin试图检测函数的每个ret指令,但成功并不保证。想想如果在函数内抛出异常会发生什么,或者如果在函数外发生跳远......

在到达return语句之前,函数被中断的原因有很多。