You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
273 lines
7.8 KiB
273 lines
7.8 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
/*! @file
|
|
The test shows how wrappers may be implemented in DLL loaded in runtime.
|
|
The dopen() is being called from application space. But it can't be called
|
|
before libc is initialized.
|
|
In this example I call dlopen before main().
|
|
*/
|
|
|
|
#include "pin.H"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <dlfcn.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "tool_macros.h"
|
|
using std::cerr;
|
|
using std::endl;
|
|
using std::cout;
|
|
|
|
#ifdef TARGET_MAC
|
|
# define MALLOC_LIB "libsystem_malloc.dylib"
|
|
#else
|
|
# define MALLOC_LIB "libc.so"
|
|
#endif
|
|
|
|
|
|
|
|
/* ===================================================================== */
|
|
|
|
INT32 Usage()
|
|
{
|
|
cerr <<
|
|
"This pin tool inserts a user-written version of malloc() and free() into the application.\n"
|
|
"\n";
|
|
cerr << KNOB_BASE::StringKnobSummary();
|
|
cerr << endl;
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* ===================================================================== */
|
|
/* Definitions for Probe mode */
|
|
/* ===================================================================== */
|
|
|
|
typedef typeof(malloc) * MallocType;
|
|
typedef typeof(free) * FreeType;
|
|
typedef typeof(dlopen) * DlopenType;
|
|
typedef typeof(dlsym) * DlsymType;
|
|
|
|
MallocType MallocWrapper = 0;
|
|
MallocType origMalloc = 0;
|
|
|
|
FreeType FreeWrapper = 0;
|
|
FreeType origFree = 0;
|
|
|
|
void * MallocTraceHandle = 0;
|
|
|
|
DlopenType AppDlopen = 0;
|
|
DlsymType AppDlsym = 0;
|
|
|
|
typedef VOID (*SET_ORIG_FPTR)(MallocType mallocPtr, FreeType freePtr);
|
|
|
|
/* ===================================================================== */
|
|
/* Probe mode tool */
|
|
/* ===================================================================== */
|
|
|
|
VOID *MallocWrapperInTool(size_t size)
|
|
{
|
|
if (MallocWrapper)
|
|
{
|
|
return (*MallocWrapper)(size);
|
|
}
|
|
else
|
|
{
|
|
ASSERTX(origMalloc != 0);
|
|
return (*origMalloc)(size);
|
|
}
|
|
}
|
|
|
|
VOID FreeWrapperInTool(void *p)
|
|
{
|
|
if (FreeWrapper)
|
|
{
|
|
(*FreeWrapper)(p);
|
|
}
|
|
else
|
|
{
|
|
ASSERTX(origFree != 0);
|
|
(*origFree)(p);
|
|
}
|
|
}
|
|
|
|
/* I'm calling dlopen before main.
|
|
* Some malloc-free may be lost, of course.
|
|
* But the earliest point you can call dlopen is after init of libc
|
|
*/
|
|
VOID MainRtnCallback()
|
|
{
|
|
cout << "In main callback" << endl;
|
|
// inject libmallocwrappers.so into application by executing application dlopen
|
|
|
|
MallocTraceHandle = AppDlopen(SHARED_LIB("libmallocwrappers"), RTLD_LAZY);
|
|
ASSERTX(MallocTraceHandle);
|
|
|
|
// Get function pointers for the wrappers
|
|
MallocWrapper = MallocType(AppDlsym(MallocTraceHandle, "mallocWrapper"));
|
|
FreeWrapper = FreeType(AppDlsym(MallocTraceHandle, "freeWrapper"));
|
|
ASSERTX(MallocWrapper && FreeWrapper);
|
|
|
|
// Send original function pointers to libmallocwrappers.so
|
|
SET_ORIG_FPTR setOriginalFptr = (SET_ORIG_FPTR) AppDlsym(MallocTraceHandle, "SetOriginalFptr");
|
|
ASSERTX(setOriginalFptr != 0);
|
|
(*setOriginalFptr)(origMalloc, origFree);
|
|
}
|
|
|
|
VOID ImageLoad(IMG img, VOID *v)
|
|
{
|
|
if (strstr(IMG_Name(img).c_str(), "libdl.so"))
|
|
{
|
|
// Get the function pointer for the application dlopen:
|
|
// dlopen@@GLIBC_2.1 is the official, versioned name.
|
|
//
|
|
// The exact suffix must match the ABI of the libdl header files
|
|
// this source code gets compiled against. Makefile/configure
|
|
// trickery would be needed to figure this suffix out, so it
|
|
// is simply hard-coded here.
|
|
//
|
|
// To keep the resulting binaries compatible with future libdl.so
|
|
// versions, this code also checks for backwards compatibility
|
|
// versions of the calls as they would be provided in such a
|
|
// future version.
|
|
|
|
#if defined(TARGET_IA32E)
|
|
# define DLOPEN_VERSION "GLIBC_2.2.5"
|
|
# define DLSYM_VERSION "GLIBC_2.2.5"
|
|
#elif defined(TARGET_IA32)
|
|
# define DLOPEN_VERSION "GLIBC_2.1"
|
|
# define DLSYM_VERSION "GLIBC_2.0"
|
|
#else
|
|
# error symbol versions unknown for this target
|
|
#endif
|
|
|
|
RTN dlopenRtn = RTN_FindByName(img, "dlopen@@" DLOPEN_VERSION);
|
|
if (!RTN_Valid(dlopenRtn))
|
|
{
|
|
dlopenRtn = RTN_FindByName(img, "dlopen@" DLOPEN_VERSION);
|
|
}
|
|
|
|
if (!RTN_Valid(dlopenRtn))
|
|
{
|
|
// fallback for the cases in which symbols do not have a version
|
|
dlopenRtn = RTN_FindByName(img, "dlopen");
|
|
}
|
|
|
|
ASSERTX(RTN_Valid(dlopenRtn));
|
|
AppDlopen = DlopenType(RTN_Funptr(dlopenRtn));
|
|
|
|
// Get the function pointer for the application dlsym
|
|
RTN dlsymRtn = RTN_FindByName(img, "dlsym@@" DLSYM_VERSION);
|
|
if (!RTN_Valid(dlsymRtn)) {
|
|
dlsymRtn = RTN_FindByName(img, "dlsym@" DLSYM_VERSION);
|
|
}
|
|
if (!RTN_Valid(dlsymRtn)) {
|
|
// fallback for the cases in which symbols do not have a version
|
|
dlsymRtn = RTN_FindByName(img, "dlsym");
|
|
}
|
|
|
|
ASSERTX(RTN_Valid(dlsymRtn));
|
|
AppDlsym = DlsymType(RTN_Funptr(dlsymRtn));
|
|
|
|
|
|
}
|
|
if (strstr(IMG_Name(img).c_str(), "libdyld.dylib"))
|
|
{
|
|
RTN dlopenRtn = RTN_FindByName(img, C_MANGLE("dlopen") );
|
|
|
|
// Get the function pointer for the application dlsym
|
|
RTN dlsymRtn = RTN_FindByName(img, C_MANGLE("dlsym") );
|
|
|
|
// In some systems, dlsym and dlopen symbols don't exist.
|
|
// In this case, exit with special return code.
|
|
if (!RTN_Valid(dlsymRtn) && !RTN_Valid(dlopenRtn))
|
|
{
|
|
cerr << "Error: dlsym and dlopen not found" << endl;
|
|
PIN_ExitApplication(13);
|
|
}
|
|
|
|
AppDlopen = DlopenType(RTN_Funptr(dlopenRtn));
|
|
AppDlsym = DlsymType(RTN_Funptr(dlsymRtn));
|
|
|
|
}
|
|
|
|
if (strstr(IMG_Name(img).c_str(), MALLOC_LIB))
|
|
{
|
|
// Replace malloc and free in application libc with wrappers in libmallocwrappers.so
|
|
RTN mallocRtn = RTN_FindByName(img, C_MANGLE("malloc"));
|
|
ASSERTX(RTN_Valid(mallocRtn));
|
|
|
|
if ( ! RTN_IsSafeForProbedReplacement( mallocRtn ) )
|
|
{
|
|
cout << "Cannot replace malloc in " << IMG_Name(img) << endl;
|
|
exit(1);
|
|
}
|
|
RTN freeRtn = RTN_FindByName(img, C_MANGLE("free"));
|
|
ASSERTX(RTN_Valid(freeRtn));
|
|
|
|
if ( ! RTN_IsSafeForProbedReplacement( freeRtn ) )
|
|
{
|
|
cout << "Cannot replace free in " << IMG_Name(img) << endl;
|
|
exit(1);
|
|
}
|
|
|
|
origMalloc = (MallocType)RTN_ReplaceProbed(mallocRtn, AFUNPTR(MallocWrapperInTool));
|
|
|
|
origFree = (FreeType)RTN_ReplaceProbed(freeRtn, AFUNPTR(FreeWrapperInTool));
|
|
|
|
}
|
|
|
|
/* I call dopen before main. If this point is too late for you,
|
|
catch init() of libc and call dlopen after init() is done
|
|
*/
|
|
if (IMG_IsMainExecutable(img))
|
|
{
|
|
RTN mainRtn = RTN_FindByName(img, "_main");
|
|
if (!RTN_Valid(mainRtn))
|
|
mainRtn = RTN_FindByName(img, "main");
|
|
|
|
if (!RTN_Valid(mainRtn))
|
|
{
|
|
cout << "Can't find the main routine in " << IMG_Name(img) << endl;
|
|
exit(1);
|
|
}
|
|
RTN_InsertCallProbed(mainRtn, IPOINT_BEFORE, AFUNPTR(MainRtnCallback), IARG_END);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ===================================================================== */
|
|
/* main */
|
|
/* ===================================================================== */
|
|
|
|
int main(int argc, CHAR *argv[])
|
|
{
|
|
PIN_InitSymbols();
|
|
|
|
if( PIN_Init(argc,argv) )
|
|
{
|
|
return Usage();
|
|
}
|
|
|
|
IMG_AddInstrumentFunction(ImageLoad, 0);
|
|
|
|
PIN_StartProgramProbed();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ===================================================================== */
|
|
/* eof */
|
|
/* ===================================================================== */
|