lei.chen
lei.chen

Reputation: 13

lib specified by LD_PRELOAD can not be loaded

I met some trouble when using LD_PRELOAD to load my so.

The steps are as following:

  1. libtest.c:

    void fun()
    {
        return 
    }
    
  2. gcc -o libtest.so libtest.c -fPIC --shared

  3. export LD_PRELOAD=pwd/libtest.so

  4. main.c

    extern void fun(); void main() { fun() }

  5. gcc -o main -L. main.c -ltest

  6. Then ldd main

    ldd main linux-vdso.so.1=>(0x00007ffff7ffd000) /home/shiyanlou/Code/libtest.so(0x00007ffff7df9000) libtest.so=>not found libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6 (0x00007ffffa29000) /lib64/ld-linux-x86-64.so.2 (0x0000555555554000)

  7. execute main ./main it promotes: error while loading shared library:libtest.so. cannot open shared object file:No such file or directory.

I wonder that why it prompts that libtest.so cannot be found After I exported LD_PRELOAD variable. However, I also tried to use LD_PRELOAD to specify a different shared lib(not "libc.so") to inject malloc function, it works! Why LD_PRELOAD only works for the shared lib that was not used when linking???

Upvotes: 1

Views: 2818

Answers (3)

neilliu
neilliu

Reputation: 3

I think the reason why your example not working is that your libtest.so does not have the correct soname.

If you compile your libtest.c with the following command

$ gcc -o libtest.so libtest.c -fPIC -shared -Wl,-soname,libtest.so

then you should be able to execute your main with PRELOAD.

Upvotes: 0

lei.chen
lei.chen

Reputation: 13

I copied and rename the DSO as libtest2.so and reset LD_PRELOAD to the renamed DSO(with absolute path), It also prompt that libtest.so could not be found.

I think that the reason why it prompt so is that the libtest.so which is used for hard dependency could not be loaded.

That is to say while LD_PRELOAD has been loaded, but hard dependency could not be satisfied, so it could not execute ./main either.

Now I can conclude that when execute ./main, hard dependency DSO must be satisfied because every hard dependency DSO also must be loaded(although this DSO shall be totally replaced!), otherwise it will prompt that the DSO could not be found!

Thanks for your help @Darryl Miles

Upvotes: 0

Darryl Miles
Darryl Miles

Reputation: 4631

You need to create 2 versions of the *.so. One which has default behavior and is loaded and hard linked via "-ltest".

Now build your default libtest.so and prove with nm -B the symbol you are expecting to intercept is dynamically linked.

Now build main.c into main.o, then check main.o with nm to also see it has an extern unsatisfied linkage requirement on the symbol.

Now link ./main with main.o and libtest.so and then run it. The ./main needs to run with this copy by default, demonstrate the default behavior and also show the correct path to the correct DSO via ldd command.

...

Now you take the step to create the LD_PRELOAD version.

You shall call this libtest2.so. You do not use the -ltest2

The point is that whoever built ./main does not know about libtest2.so at all, there is no hard linkage dependency.

libtest2.so has alternative behavior, like make foo() returns a different string/number) and the goal now is to intercept this 2nd version at runtime, so the 1st version is not called by default (or at all). By using the LD_PRELOAD environment.

LD_PRELOAD=./libtest2.so ./main

...

Good luck.

Upvotes: 1

Related Questions