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.