Topic
3 replies Latest Post - ‏2013-02-14T13:15:58Z by butthead2
butthead2
butthead2
4 Posts
ACCEPTED ANSWER

Pinned topic LDR_PRELOAD64

‏2013-01-25T11:54:57Z |
hello

I've tried to catch some library calls using LDR_PRELOAD64 and have found out that I'm not able to catch all the calls

my program calls 'foo' from libfoo.so (libfoo.so=foo.o+shmoo.o)
'foo' calls 'shmoo' from libfoo.so(shmoo.o) and 'bar' from libfoo.so(foo.o)

summary:
  • I am able to catch 'foo' and unable to catch 'shmoo' and 'bar' on aix 5.3 (5300-05, xlc v8)
  • I am able to catch 'foo' and 'shmoo' and unable to catch 'bar' on aix 7.1 (7100-00, xlc v12)
  • I am able to catch 'foo', 'shmoo' and 'bar' on linux

what I would like to know: is this is limited by system/linker/libraries/whatever or I am missing some compilation flags or some other stuff?

in a live situation I am not able to change libfoo.so (third party code) but I want to catch the 'bar' call and write backtrace
to my log file (libfoo.so library likes to write meaningless 'something went wrong somewhere' message)



//------- main.c: #include <stdio.h>   

int foo(

int );   

int main(

int argc, 

char **argv) 
{ foo(3); 

return 0; 
}




//------- foo.c: #include <stdio.h>   

int shmoo(

int );   

int foo(

int i) 
{ printf(
"foo i=%d\n",i); bar(2); 

return shmoo(i); 
}   

int bar(

int i) 
{ printf(
"bar i=%d\n",i); 

return 0; 
}




//------- shmoo.c: #include <stdio.h>   

int shmoo(

int i) 
{ printf(
"shmoo i=%d\n",i);   

return 5; 
}




//------- overload.c: #include <stdio.h> #include <dlfcn.h>   typedef 

int(*foo_t)(

int); typedef 

int(*shmoo_t)(

int); typedef 

int(*bar_t)(

int);   

static 

int doinit=1; 

static 

void *dl;   

static foo_t p_foo; 

static shmoo_t p_shmoo; 

static bar_t p_bar;   

static 

void init(

void) 
{ printf(
"dlopen\n"); dl=dlopen(
"libfoo.so",RTLD_NOW|RTLD_GLOBAL); 

if (dl!=NULL) 
{ printf(
"dlsym\n"); p_foo=(foo_t)dlsym(dl,
"foo"); p_shmoo=(shmoo_t)dlsym(dl,
"shmoo"); p_bar=(bar_t)dlsym(dl,
"bar"); printf(
"%p %p %p\n",p_foo,p_shmoo,p_bar); 
} doinit=0; 
}   

int foo(

int i) 
{ printf(
"got foo\n"); 

if (doinit) init(); 

return p_foo(i); 
} 

int shmoo(

int i) 
{ printf(
"got shmoo\n"); 

if (doinit) init(); 

return p_shmoo(i); 
} 

int bar(

int i) 
{ printf(
"got bar\n"); 

if (doinit) init(); 

return p_bar(i); 
}




//------- compile.sh: #!/bin/bash export LIBPATH=`pwd` CFLAGS=
"-q64 -g -bnoipath -qtwolink -D_LARGE_FILES -D__XCOFF32__ -D__XCOFF64__ -brtl -qstaticinline -bexpall" xlc $CFLAGS -c main.c foo.c shmoo.c && \ xlc $CFLAGS -G -o libfoo.so foo.o shmoo.o && \ xlc $CFLAGS -o main main.o -L`pwd` -lfoo && \ xlc $CFLAGS -bexpall -G -o liboverload.so overload.c -ldl && \ ./main && LDR_PRELOAD64=liboverload.so ./main || read c
Updated on 2013-02-14T13:15:58Z at 2013-02-14T13:15:58Z by butthead2
  • butthead2
    butthead2
    4 Posts
    ACCEPTED ANSWER

    Re: LDR_PRELOAD64

    ‏2013-02-07T11:48:51Z  in response to butthead2
    anybody?
  • flodstrom
    flodstrom
    56 Posts
    ACCEPTED ANSWER

    Re: LDR_PRELOAD64

    ‏2013-02-14T12:28:20Z  in response to butthead2
    If I understand this correctly you are trying to use that liboverload.so as a form wrapper lib to libfoo.so, is that correct?

    To me this is a rather unconventional approach to catching function calls to a library or a shared object. I would even suspect that you may run into some unpredicatable behaviour of you application while you have both the libfoo and liboverload loaded at the same (symbol conflicts?)?

    If I were you I would dump that liboverload and use a debugger to catch the function calls. If you are doing this on AIX 6.1 or 7.1 you could also try out probevue for some dynamic tracing.

    For example, use a simple probevue script like the following:

    
    
    /* catch.e */ 
    /* Catch function calls + argument for libfoo functions */   
    
    int foo(
    
    int i); 
    
    int bar(
    
    int i); 
    
    int shmoo(
    
    int i);   @@BEGIN 
    { printf(
    "*** Start Probing ***\n"); 
    }   @@uft:$__CPID:*:foo:entry 
    { printf(
    "Got foo(%d)\n", __arg1); 
    }   @@uft:$__CPID:*:bar:entry 
    { printf(
    "Got bar(%d)\n", __arg1); 
    }   @@uft:$__CPID:*:shmoo:entry 
    { printf(
    "Got shmoo(%d)\n", __arg1); 
    }   @@END 
    { printf(
    "\n*** End Probing ***\n"); 
    }
    


    Use the following command to do the trace (above script example named "catch.e").

    probevue -X ./main catch.e

    You may have to run it as root though.
    • butthead2
      butthead2
      4 Posts
      ACCEPTED ANSWER

      Re: LDR_PRELOAD64

      ‏2013-02-14T13:15:58Z  in response to flodstrom
      Hello

      I would love to use probevue but my production environment is AIX 5.3 :-( and there is no way to change this

      also it would be difficult to use debugger and breakpoint because this (terminal) program is used whole days and
      it acctually consists of lot of binaries used like this:
      binX -> execve -> binY -> execve -> binZ ... -> execve -> binY ...
      and only one of them produces this error once in a while

      and regarding LDR_PRELOAD64 - there won't be any symbol conflict because:

      "During symbol resolution, the preloaded libraries listed in the environment variable will be searched first for every imported symbol, and only when a symbol is not found will the normal search be used"

      I even managed to use this on development and test environments to catch and log oracle and informix sql statements and host variables by
      making a wrapper to sqlcxt (oracle) and sqli* (informix) functions. so it is nice feature

      anyway thanks for your ideas