0

I use the Intel-Pin to instrument pthread_mutex_lock and pthread_mutex_unlock in Linux. I insert functions before and after this two lock function's invocation respectively, so I expect that the tool will output strings before and after the lock functions.
The instrument code is as follow

#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 */
/* ===================================================================== */

compile this tool

make obj-ia32/mytool.so TARGET=ia32

use this tool to instrument a simple test

#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;
}

compile this test

gcc -g t.c -o t -lpthread

At last, I use the my tool to instrument this test

sudo ./pin -t obj-ia32/mytool.so -- ./t

the result is

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

You can see there is no Pthread_mutex_unlock_callAfter, I have insert a function after the pthread_mutex_unlock, why this function have not been callded?
PS :the Pin API say that

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
wangxf
  • 160
  • 1
  • 11
  • The NOTE in the api reference says it already: pin makes a best effort to instrument ipoint_after but it's not guaranteed. If you want guaranteed before and after callbacks, use the RTN replace api. – nitzanms Dec 09 '15 at 05:09
  • @nitzanms I'm the new guy who use the Pin, there is many problems for me to use it. Thank you very much. If I have some problem, where I can ask the question about Pin? – wangxf Dec 09 '15 at 07:51
  • You can ask here of course, but you will also find a lot of useful info in Pinheads, a support group for Pin users: https://groups.yahoo.com/neo/groups/pinheads/info – nitzanms Dec 10 '15 at 09:37

1 Answers1

0

As Nitzan said already, the APIs says it all: Pin tries to instrument each ret instruction of the function, but success is not garanteed. Think what would happen if an exception is thrown within the function, or if a long jump outside of the function happens...

There are many reasons for a function to be interrupted before reaching the return statement.

Heyji
  • 1,113
  • 8
  • 26