MALLOCTYPE user: malloc replacement calling default malloc? - Aix

This is a discussion on MALLOCTYPE user: malloc replacement calling default malloc? - Aix ; I would like to monitor calls to malloc/free/etc via the MALLOCTYPE user: malloc replacement mechanism. But i just want to monitor them, not re-implement them. Is there a way to call the default malloc routines from a user defined malloc ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: MALLOCTYPE user: malloc replacement calling default malloc?

  1. MALLOCTYPE user: malloc replacement calling default malloc?

    I would like to monitor calls to malloc/free/etc via the MALLOCTYPE
    user: malloc replacement mechanism. But i just want to monitor them,
    not re-implement them. Is there a way to call the default malloc
    routines from a user defined malloc handler? Just calling malloc()
    gives the expected infinite recursion, since malloc calls get
    redirected to the user defined malloc replacement!

    Are they available via other symbols such as malloc_y_heap or similar
    that I could refer to directly in my replacement module?


  2. Re: MALLOCTYPE user: malloc replacement calling default malloc?

    hobie744 writes:

    > Are they available via other symbols such as malloc_y_heap or similar
    > that I could refer to directly in my replacement module?


    At least on my version of AIX 5.1, libc.a(shr.o) contains __malloc,
    __realloc, __calloc and __free entries, which all jump directly into
    correspondig libc.a(shr.o)malloc, realloc, etc.

    Cheers,
    --
    In order to understand recursion you must first understand recursion.
    Remove /-nsp/ for email.

  3. Re: MALLOCTYPE user: malloc replacement calling default malloc?

    > At least on my version of AIX 5.1, libc.a(shr.o) contains __malloc,
    > __realloc, __calloc and __free entries, which all jump directly into
    > correspondig libc.a(shr.o)malloc, realloc, etc.


    calling __malloc from my __malloc__ gives the same infinite recursion
    on my 4.3.3 and 5.2 box (i dont have a 5.1 to try this on...).




  4. Re: MALLOCTYPE user: malloc replacement calling default malloc?

    On May 18, 7:17 pm, hobie744 wrote:
    > > At least on my version of AIX 5.1, libc.a(shr.o) contains __malloc,
    > > __realloc, __calloc and __free entries, which all jump directly into
    > > correspondig libc.a(shr.o)malloc, realloc, etc.

    >
    > calling __malloc from my __malloc__ gives the same infinite recursion
    > on my 4.3.3 and 5.2 box (i dont have a 5.1 to try this on...).


    What exactly would you like to monitor?
    If you don't have to do it programatically you can use malloc log, or
    the malloc trace hooks.


  5. Re: MALLOCTYPE user: malloc replacement calling default malloc?

    On May 19, 3:42 pm, rajbir wrote:
    > What exactly would you like to monitor?
    > If you don't have to do it programatically you can use malloc log, or
    > the malloc trace hooks.


    I want to be able to list the who/what/where/when of all allocated
    blocks outstanding
    at any given time. The malloc log facility wont give me the
    timestamp, and it requires
    code changes to the application. The malloc trace hooks dont give the
    allocation stack.

    With a generous hint from Gary Hook (thanks, Gary!) i've accomplished
    this another way. I essentially
    create a modified copy of libc.a (specific to the target system) with
    my own versions of malloc, realloc and free. In an init method called
    via the -binitfini linker option, I modify function descriptors to
    insert my methods in place of the originals. My methods perform their
    tracking, and call the original methods. This accomplishes the goal
    of not modifying the application under study. All i do is set LIBPATH
    to point to my custom libc, and presto, i now have a monitored heap.

    I started from an example that worked for the "execv" function.
    malloc was a little trickier since it was called from within the
    init_execv method, dlopen and dlsym. for those cases, i just sbrk'd
    the needed memory and didn't worry about the leaks.

    At the bottom of the init_execv method, I opened a pipe, forked a
    child, and sent my heap events to the child for tracking. One tricky
    thing I found was that things like the % (mod) operator didn't work in
    that child process loop. Since % is actually some library method, I
    got strange linker warnings about bad opcodes and a core when I tried
    to mod anyway. And strangely (for a similar reason i'm sure), i
    couldn't use memcpy. But printf worked??

    -----------execv.c----------
    #include
    #include
    #include
    execv( const char *path,
    char *const argv[] )
    {
    printf( "Inside shim execv()....\n" );
    /* Remove the path that contains our wrapper, or subsequent calls
    to execv
    * may recurse. This code should be smarter: get the current
    value of LIBPATH,
    * clean it up, and store the new path back in the environment.
    For this
    * example, we know that we only have to clear LIBPATH.
    */
    putenv( "LIBPATH=" );
    (*S_RealExecv)( path, argv );
    }
    int init_execv( void )
    {
    void *handle = NULL;
    S_RealExecv = (int (*)(const char *,char *const []))
    malloc( 3*sizeof(void *) );
    if ( !S_RealExecv )
    return( -1 );

    /* Get a handle to the real libc, which we presume is in /usr/
    lib. Using a full
    * path avoids picking up our bogus copy by mistake.
    */
    handle = dlopen( "/usr/lib/libc.a(shr.o)", RTLD_GLOBAL|RTLD_NOW|
    RTLD_MEMBER );
    if ( handle )
    {
    void **target = (void **) S_RealExecv;
    void **fP = (void **) dlsym( handle, "execv" );
    void **newDef = (void **) &execv;

    /* fP points to the original descriptor. target points to the
    * descriptor variable in this file, which we use to save the real
    * value.
    */
    if ( fP )
    {
    target[0] = fP[0];
    target[1] = fP[1];
    target[2] = fP[2];

    fP[0] = newDef[0];
    fP[1] = newDef[1];
    fP[2] = newDef[2];
    }
    else
    return( -1 );
    }
    else
    return( -1 );
    return( 0 );
    }
    --------------makefile-----------
    CC= xlc
    CFLAGS= -g
    LD= ld
    all: libc.a libcwrapper.so main
    main: main.o
    $(CC) -o main main.o

    libc.a: shr.o
    $(AR) rv libc.a shr.o
    ln libc.a libc_r.a

    shr.o: execv.o libcwrapper.so
    $(LD) -o shr.o execv.o libcwrapper.so -L/usr/lib -L$(PWD) -
    bE:shr.exp -bM:SRE \
    -blibpath:/usr/lib:/lib -bnoentry -lc -binitfini:init_execv

    libcwrapper.so: shr.imp
    ld -o libcwrapper.so -bM:SRE -bnoentry -bI:shr.exp -bE:shr.exp -
    blibpath:/usr/lib:/lib

    clean:
    @rm -f *.so core a.out libc.a libc_r.a *.o main

    tar:
    tar -cvf shim1.tar README Makefile main.c execv.c
    -------------------main.c-----------
    #include
    #include

    main( int argc, char *argv[] )
    {
    char **argvP = argv + 1;
    printf( "execv()'ing %s...\n", argv[1] );
    execv( argv[1], argvP );
    printf( "done!\n" );
    exit( 0 );
    }
    --------------------README-------------
    shr.exp and shr.imp are generated from the actual libc on the system:
    ar xv /usr/lib/libc.a shr.o
    rtl_enable -s shr.o
    rm shr.o shr.sh

    With the import/export lists created, you have the interface for
    libc.a(shr.o).
    Modify shr.exp by adding this line at the beginning of the file:
    #! /usr/lib/libc.a(shr.o)

    Now you can
    make libcwrapper.so

    then write your code for your custom execv() function. In this
    example,
    it's in execv.c. Also, you need an init function, init_execv here,
    that is specified on the command line when you build your new shr.o.
    Look at the makefile for details. Now you can
    make shr.o

    and if successful,
    make libc.a

    In this directory you have a wrapper version of libc.a (and libc_r,
    which
    is often used by programs; they're the same file on the system) which
    depends
    upon libcwrapper.so. It, in turn, depends explicitly on libc.a in /
    usr/lib;
    use dump -HTv to examine the loader section. Absolute paths ensure
    that
    libcwrapper.so sits directly on top of the real libc.a. But our
    customer
    libc.a sits on top of libcwrapper.so and contains custom code.
    Uninteresting
    symbols are simply passed through these wrappers (the import/export
    classification).

    The test program calls exec. I tested with

    LIBPATH=. ./main /bin/echo hi

    which works. To test the clearing of LIBPATH in execv() I ran this:

    LIBPATH=. ./main ./main /bin/echo hi

    This should result in the program exec'ing itself, but running just as
    if the shim library wasn't used.

    Note that nothing special is done to build main. No LIBPATH, etc.
    This
    is to emulate the normal construction of a program.




+ Reply to Thread