Почему некоторая функция обратного вызова не может быть вызвана в Pin?

Я использую 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

person wangxf    schedule 08.12.2015    source источник
comment
ПРИМЕЧАНИЕ в справке по api уже говорит об этом: pin делает все возможное для инструмента ipoint_after, но это не гарантируется. Если вам нужна гарантия до и после обратных вызовов, используйте RTN replace api.   -  person nitzanms    schedule 09.12.2015
comment
@nitzanms Я новый парень, использующий пин, у меня много проблем с его использованием. Большое тебе спасибо. Если у меня возникнут проблемы, где я могу задать вопрос о пине?   -  person wangxf    schedule 09.12.2015
comment
Вы, конечно, можете спросить здесь, но вы также найдете много полезной информации в Pinheads, группе поддержки для пользователей Pin: groups.yahoo.com/neo/groups/pinheads/info   -  person nitzanms    schedule 10.12.2015


Ответы (1)


Как уже сказал Ницан, API говорит само за себя: Pin пытается инструментировать каждую команду ret функции, но успех не гарантирован. Подумайте, что произойдет, если в функции будет выброшено исключение или произойдет длинный переход за пределы функции ...

Есть много причин для прерывания функции до достижения оператора return.

person Heyji    schedule 05.01.2016