LD_LIBRARY_PATH environment variable

compilingdynamic-linkingenvironment-variableslibraries

I am trying to test the LD_LIBRARY_PATH environment variable. I have a program test.c as follows:

int main()
{
     func("hello world");
}

I have two files func1.c and func2.c:

// func1.c
#include <stdio.h>
void func(const char * str)
{
     printf("%s", str);
}

And

// func2.c
#include <stdio.h>
void func(const char * str)
{
     printf("No print");
}

I want to do the following somehow:

  • Convert func1.c and func2.c to .so files – both with same name func.so (they will be placed in different folders, say dir1 and dir2
  • Compile test.c s.t. I only mention that it has a dependency func.so, but I don't tell it where it is (I want the environment variable to be used to find this)
  • Set the environment variable, in first try to dir1 and in second try to dir2 to observe different output in each run of test program

Is the above doable ? If so, how to do step 2 ?

I did the following for step 1 (same steps for func2):

$ gcc -fPIC -g -c func1.c
$ gcc -shared -fPIC -o func.so func1.o

Best Answer

Use ld -soname:

$ mkdir dir1 dir2
$ gcc -shared -fPIC -o dir1/func.so func1.c -Wl,-soname,func.so
$ gcc -shared -fPIC -o dir2/func.so func2.c -Wl,-soname,func.so
$ gcc test.c dir1/func.so
$ ldd a.out
    linux-vdso.so.1 =>  (0x00007ffda80d7000)
    func.so => not found
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f639079e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f6390b68000)
$ LD_LIBRARY_PATH='$ORIGIN/dir1:$ORIGIN/dir2' ./a.out
hello world
$ LD_LIBRARY_PATH='$ORIGIN/dir2:$ORIGIN/dir1' ./a.out
No print

-Wl,-soname,func.so (this means -soname func.so is passed to ld) embeds SONAME attribute of func.so in the output. You can examine it by readelf -d:

$ readelf -d dir1/func.so 

Dynamic section at offset 0xe08 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [func.so]
...

Linked with this func.so with SONAME, a.out has that in its NEEDED attribute:

$ readelf -d a.out

Dynamic section at offset 0xe18 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [func.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
...

Without -Wl,-soname,func.so, you'll get the following by readelf -d:

$ readelf -d dir1/func.so 

Dynamic section at offset 0xe18 contains 24 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
...

$ readelf -d a.out

Dynamic section at offset 0xe18 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [dir1/func.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
...
Related Question