6

In the man page for ld.so(8), it says that

When resolving library dependencies, the dynamic linker first inspects each dependency string to see if it contains a slash (this can occur if a library pathname containing slashes was specified at link time). If a slash is found, then the dependency string is interpreted as a (relative or absolute) pathname, and the library is loaded using that pathname.

How can gcc link against a library with a path with a slash? I have tried with -l but that seems to work only with a library name which it uses to search various paths, not with a path argument itself.

One follow-on question: when linking to a relative path in this way, what is the path relative to (e.g. the directory containing the binary or the working directory at runtime)?

All of the linking guides I find when searching discuss using RPATH, LD_LIBRARY_PATH, and RUNPATH. RPATH is deprecated and most discussions discourage using LD_LIBRARY_PATH. RUNPATH with a path starting with $ORIGIN allows for a link to a relative path, but it is a little fragile because it can be overridden by LD_LIBRARY_PATH. I wanted to know if a relative path would be more robust (since I can't find anything discussing this I am guessing not, likely because the path is relative to the runtime directory).

3 Answers 3

15

If we (for the moment) ignore the gcc or linking portion of the question and instead modify a binary with patchelf on a linux system

$ ldd hello
        linux-vdso.so.1 =>  (0x00007ffd35584000)
        libhello.so.1 => not found
        libc.so.6 => /lib64/libc.so.6 (0x00007f02e4f6f000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f02e533c000)
$ patchelf --remove-needed libhello.so.1 hello
$ patchelf --add-needed ./libhello.so.1 hello
$ ldd hello
        linux-vdso.so.1 =>  (0x00007ffdb74fc000)
        ./libhello.so.1 => not found
        libc.so.6 => /lib64/libc.so.6 (0x00007f2ad5c28000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f2ad5ff5000)

We now have a binary with a relative path library, which if there exist suitable directories with libhello.so.1 files present in them

$ cd english/
$ ../hello
hello, world
$ cd ../lojban/
$ ../hello
coi rodo

we find that the path is relative to the working directory of the process, which opens up all sorts of problems, especially security problems. There might be some productive use for this, testing different versions of a library, perhaps. It would likely be simpler to compile two different binaries, or patchelf in the necessary library without the complication of a relative working directory.

compile steps

libhello only has a helloworld call

$ cat libhello.c
#include <stdio.h>
void helloworld(void)
{
    printf("coi rodo\n");
}

and was compiled via

CFLAGS="-fPIC" make libhello.o
gcc -shared -fPIC -Wl,-soname,libhello.so.1 -o libhello.so.1.0.0 libhello.o -lc
ln -s libhello.so.1.0.0 libhello.so.1
ln -s libhello.so.1.0.0 libhello.so

and the hello that makes the helloworld call was compiled via

$ cat hello.c
int main(void)
{
    helloworld();
    return 0;
}
$ CFLAGS="-lhello -L`pwd`/english" make hello

without patchelf

In hindsight, modify the gcc command to use a relative directory path:

$ gcc -shared -fPIC -Wl,-soname,./libhello.so.1 -o libhello.so.1.0.0 libhello.o -lc
$ cd ..
$ rm hello
$ CFLAGS="-lhello -L`pwd`/lojban" make hello
$ ldd hello | grep hello
        ./libhello.so.1 => not found
$ english
$ ../hello
hello, world

It's probably more sensible to compile the library in a normal fashion and then fiddle around with any binaries as necessary using patchelf.

0
5

You would do this by passing options to the linker. For instance, to run test-programs from ncurses' build-directory (which rely upon libraries not installed), I use an option like this (in the gcc command-line):

-Wl,-rpath,../lib

which embeds a relative pathname. The same option can embed an absolute pathname:

-Wl,-rpath,../lib:/usr/local/ncurses6/lib

Doing that is useful for local testing, but not for installing on the system for a variety of reasons. Debian has a policy against it, dating back to the 1990s, though coherent discussion is rare (see for example RPATH issue which collects some of the information).

0

If you use gcc to compile simply, you just need to do like this:

gcc -o prog main.c ./liblib.so

After compile, the program has the same behavior as the thrig's answer. I think this command should be only used in testing environment.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .