Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking shared library absolute vs. relative path

I've been trying to link a shared library into my program and I want its path to be relative to my RPATH.

However, when I ran ldd, I noticed that the absolute path of the shared library was linked. Any ideas why?

Edit:

/home/projects/my_files/winter_fresh.so
libgcc_s.so.1 => /home/tomo/anaconda3/lib/libgcc_s.so.1 (0x00007f0a3bf64000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0a3bd47000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a3b97d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a3e369000)
libstdc++.so.6 => /home/tomo/anaconda3/lib/libstdc++.so.6 (0x00007f0a3b643000)

The issue is the first file. I don't want the library for winter_fresh to be an absolute path, since I have an RPATH that contains it.

like image 527
ProgrammingRain Avatar asked May 27 '18 21:05

ProgrammingRain


2 Answers

The issue is the first file. I don't want the library for winter_fresh to be an absolute path

This most usually happens when you link against your library like so:

gcc ... /home/projects/my_files/winter_fresh.so ...

and your library does not have SONAME (you didn't use -soname linker option when building it).

To fix this, either add SONAME to winter_fresh.so (a good practice in general), or link against it like so:

gcc ... -L /home/projects/my_files -l:winter_fresh.so

An even better approach might be to rename winter_fresh.so to libwinter_fresh.so, and then link against it like so:

gcc ... -L /home/projects/my_files -lwinter_fresh
like image 109
Employed Russian Avatar answered Sep 22 '22 14:09

Employed Russian


My guess is, you compiled your program using winter_fresh.so as source file, not by linking against it.
If you encoded the path to shared library/executable as /home/projects/my_files/winter_fresh.so, you can put your shared library inside RPATH directory, like this:

 $ mkdir some_dir
 $ mkdir -p some_dir/home/projects/my_files
 $ cp /home/projects/my_files/winter_fresh.so some_dir/home/projects/my_files
 $ RPATH=$(pwd)/some_dir ./executable

The linker searches for library named /home/projects/my_files/winter_fresh.so under RPATH.

Now a simple test:

// main.c
int main() {
  int external_function(void);
  return external_function();
}

// exlib.c
#include <stdio.h>
int external_function(void) {
  return printf("%s\n", __func__);
}

Now, let's create bad.out compiled with exlib.so shared library used as source:

$ gcc -shared -fPIC -o exlib.so exlib.c
$ gcc /tmp/exlib.so main.c -o bad.out
$ ldd bad.out
linux-vdso.so.1 (0x00007ffd921db000)
/tmp/exlib.so (0x00007fe4470f7000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fe446d3b000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fe4474fb000)

As you see the string /tmp/exlib.so points to the shared library. I can run the program, using RPATH to point the linker to exlib.so location. I need to create subtree /tmp/exlib.so inside RPATH, like this:

$ mkdir -p lib/tmp
$ mv exlib.so lib/tmp
$ RPATH=$(pwd)/lib ./bad.out
external_function

When running bad.out, linker searches for a file named /tmp/exlib.so inside RPATH.
Linux uses a convention for naming shared libraries. Now let's link against good.out:

$ gcc -shared -fPIC -o libexlib.so exlib.c
$ gcc -I /tmp -lexlib main.c -o good.out
$ ldd good.out 
linux-vdso.so.1 (0x00007ffcb01bf000)
libexlib.so => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007fc1230ef000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fc1236ad000)

Now you see that good.out is linked against libexlib.so. gcc searched for alibrary named libexlib.so inside /tmp directory when linking. I can run good.out by specyfing LD_LIBRARY_PATH to the path libexlib.so resides:

 $ LD_LIBRARY_PATH=/tmp ldd ./good.out
 external_function
like image 24
KamilCuk Avatar answered Sep 18 '22 14:09

KamilCuk