1

I used a pin tool posted on intel's official Manual:

#include "pin.H"
#include <iostream>
#include <fstream>

/* ===================================================================== */
/* Names of malloc and free */
/* ===================================================================== */
#if defined(TARGET_MAC)
#define MALLOC "_malloc"
#define FREE "_free"
#else
#define MALLOC "malloc"
#define FREE "free"
#endif

/* ===================================================================== */
/* Global Variables */
/* ===================================================================== */

std::ofstream TraceFile;

/* ===================================================================== */
/* Commandline Switches */
/* ===================================================================== */

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
    "o", "malloctrace.out", "specify trace file name");

/* ===================================================================== */


/* ===================================================================== */
/* Analysis routines                                                     */
/* ===================================================================== */

VOID Arg1Before(CHAR * name, ADDRINT size)
{
    TraceFile << name << "(" << size << ")" << endl;
}

VOID MallocAfter(ADDRINT ret)
{
    TraceFile << "  returns " << ret << endl;
}


/* ===================================================================== */
/* Instrumentation routines                                              */
/* ===================================================================== */

VOID Image(IMG img, VOID *v)
{
    // Instrument the malloc() and free() functions.  Print the input argument
    // of each malloc() or free(), and the return value of malloc().
    //
    //  Find the malloc() function.
    RTN mallocRtn = RTN_FindByName(img, MALLOC);
    if (RTN_Valid(mallocRtn))
    {
        RTN_Open(mallocRtn);

        // Instrument malloc() to print the input argument value and the return value.
        RTN_InsertCall(mallocRtn, IPOINT_BEFORE, (AFUNPTR)Arg1Before,
                       IARG_ADDRINT, MALLOC,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
                       IARG_END);
        RTN_InsertCall(mallocRtn, IPOINT_AFTER, (AFUNPTR)MallocAfter,
                       IARG_FUNCRET_EXITPOINT_VALUE, IARG_END);

        RTN_Close(mallocRtn);
    }

    // Find the free() function.
    RTN freeRtn = RTN_FindByName(img, FREE);
    if (RTN_Valid(freeRtn))
    {
        RTN_Open(freeRtn);
        // Instrument free() to print the input argument value.
        RTN_InsertCall(freeRtn, IPOINT_BEFORE, (AFUNPTR)Arg1Before,
                       IARG_ADDRINT, FREE,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
                       IARG_END);
        RTN_Close(freeRtn);
    }
}

/* ===================================================================== */

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

The example above prints the input argument for malloc() and free(), and the return value from malloc().

I tested it against my code:

#include <stdio.h>
#include <stdlib.h>

void foo()
{

  int a = 2;
  int val;
  val = a;
  printf("%i\n", val);

}

int main()
{
  int i;
  char *str = (char*)malloc(15);
  char * xx = (char*)malloc(30);

  for (i = 0; i < 10; ++i)
  {
    str[i] = rand()%23+'a';
  }
  for (i = 0; i < 10; ++i)
  {
    xx[i] = rand()%23+'a';
  }
  xx[i] = '\0';
  str[i] = '\0';

  printf("%s\n", str);
  printf("%s\n", xx);
  free(str);
  foo();
  return 0;

}

And got the following output:

$ tail malloctrace.out 
malloc(0x110)
  returns 0x7f258b149e00
malloc(0xf)
malloc(0xf)
  returns 0x107a260
malloc(0x1e)
  returns 0x107a280
malloc(0x400)
  returns 0x107a2b0
free(0x107a260)

Now, in the my posted code there are a couple of malloc calls:

char *str = (char*)malloc(15);
char * xx = (char*)malloc(30);

But, as you can notice in the above output, couple of malloc function calls are detected:

malloc(0xf)
malloc(0xf)

I believe these correspond to malloc(15) (Notice, the same is not true in the case of malloc(30)). Could you please tell me why is this the case, also can we detect such call only once.

Objdump:

Malloc:

0000000000400500 <malloc@plt>:
  400500:       ff 25 2a 0b 20 00       jmp    QWORD PTR [rip+0x200b2a]        # 601030 <malloc@GLIBC_2.2.5>
  400506:       68 03 00 00 00          push   0x3
  40050b:       e9 b0 ff ff ff          jmp    4004c0 <.plt>

Part of my main function:

  int i;
  char *str = (char*)malloc(15);
  40063a:       bf 0f 00 00 00          mov    edi,0xf
  40063f:       e8 bc fe ff ff          call   400500 <malloc@plt>
  400644:       48 89 45 f0             mov    QWORD PTR [rbp-0x10],rax
  char * xx = (char*)malloc(30);
  400648:       bf 1e 00 00 00          mov    edi,0x1e
  40064d:       e8 ae fe ff ff          call   400500 <malloc@plt>
  400652:       48 89 45 e8             mov    QWORD PTR [rbp-0x18],rax

Notice only a couple of malloc calls.

R4444
  • 2,016
  • 2
  • 19
  • 30
  • 2
    The Pin tool looks fine. Note that `malloc(0x1e)` corresponds to `malloc(30)`. I think somehow `malloc(0xf)` is being called twice. Examine the assembly code generated by your compiler using `objdump`. – Hadi Brais Apr 02 '19 at 08:55
  • 2
    Compiling your test program (not the PIN tool) with `gcc -Og` on x86-64 Linux, and tracing its library function calls with `ltrace`, I see only the expected 2 `malloc` calls. Have you tried setting a breakpoint on `malloc` to see if there really is a 2nd call to it from somewhere? – Peter Cordes Apr 02 '19 at 13:21
  • hadi yes I examined that, @Peter yes, I debugged the code exactly as u said, but couldn't find anything (maybe I'm lacking some knowledge). I have updated the question with objdump. – R4444 Apr 02 '19 at 14:11
  • 1
    Maybe try compiling with `-fno-plt`. Perhaps lazy dynamic linking is causing the first call from within your program to be seen twice. (Although the real malloc function in libc is only called once; the first through the PLT stub it doesn't jump directly to malloc. Single-step into it on the first and then the 2nd call if you want to see the PLT in action. – Peter Cordes Apr 02 '19 at 14:16
  • 2
    Hmm... (1) Which Pin version are you using? (2) Which compiler & version & compiler options are you using to compile the code? (3) How are you compiling the Pin tool? I'll try to see if I can reproduce this on my system. – Hadi Brais Apr 02 '19 at 14:49
  • @peter yes I just tried what you said, but couldn't find anything unusual (again, this could be because of my limited knowledge). Hadi - 1) pin-3.7 2) Compiler: `gcc/g++-8.2.1` with no special flags. 3) For the compilation of pin, I am using the same makefile provided in `ManualExamples` folder of pin. Thanks (both of )u. – R4444 Apr 02 '19 at 15:04
  • 1
    I was not able to reproduce the behavior using gcc 5.4, gcc 7.3, or gcc 8.1. I only get one `malloc` call in the trace per `malloc` call. – Hadi Brais Apr 02 '19 at 19:18
  • Hadi: Thanks. I am not sure why is it happening in my case though. I tried few other examples, but still the same result. Only for the `first` malloc called. (`0xf` in the example above). – R4444 Apr 02 '19 at 19:20
  • @R4444 hello, this is an old question, but did you ever figure out the reason why this problem occurred? Similar thing is happening on my code, and I was just wondering whether there is any update on this. – Jay Dec 30 '22 at 03:41

0 Answers0