Como vincular a uma biblioteca compartilhada com um caminho relativo?

0

Na página man do ld.so (8) , diz que

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.

Como pode gcc vincular-se a uma biblioteca com um caminho com uma barra? Eu tentei com -l , mas parece funcionar apenas com um nome de biblioteca que ele usa para pesquisar vários caminhos, não com um argumento de caminho em si.

Uma pergunta subseqüente: ao vincular a um caminho relativo dessa maneira, qual é o caminho relativo (por exemplo, o diretório que contém o binário ou o diretório de trabalho em tempo de execução)?

Todos os guias de vinculação encontrados ao pesquisar discutem usando RPATH , LD_LIBRARY_PATH e RUNPATH . RPATH está obsoleto e a maioria das discussões desestimula o uso de LD_LIBRARY_PATH . RUNPATH com um caminho que começa com $ORIGIN permite um link para um caminho relativo, mas é um pouco frágil porque pode ser substituído por LD_LIBRARY_PATH . Eu queria saber se um caminho relativo seria mais robusto (já que não consigo encontrar nada que discuta isso, acho que não, provavelmente porque o caminho é relativo ao diretório de tempo de execução).

    
por ws_e_c421 02.11.2018 / 16:26

2 respostas

2

Se nós (no momento) ignorarmos a gcc ou a parte de vinculação da pergunta e, em vez disso, modificarmos um binário com patchelf em um sistema linux

$ 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)

Agora temos um binário com uma biblioteca de caminhos relativos, que se houver diretórios adequados com libhello.so.1 arquivos presentes neles

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

descobrimos que o caminho é relativo ao diretório de trabalho do processo , que abre todos os tipos de problemas, especialmente segurança problemas . Pode haver algum uso produtivo para isso, testando diferentes versões de uma biblioteca, talvez. Provavelmente seria mais simples compilar dois binários diferentes ou patchelf na biblioteca necessária sem a complicação de um diretório de trabalho relativo.

etapas de compilação

libhello tem apenas uma chamada helloworld

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

e foi compilado 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

e o hello que faz a chamada helloworld foi compilada via

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

sem patchelf

Em retrospectiva, modifique o comando gcc para usar um caminho de diretório relativo:

$ 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

Provavelmente é mais sensato compilar a biblioteca de uma maneira normal e depois mexer em qualquer binários, conforme necessário, usando patchelf .

    
por 02.11.2018 / 21:01
1

Você faria isso passando as opções ao vinculador. Por exemplo, para executar programas de teste do diretório build de ncurses (que depende de bibliotecas não instaladas), eu uso uma opção como essa (na linha de comando do gcc):

-Wl,-rpath,../lib

que incorpora um nome de caminho relativo. A mesma opção pode incorporar um nome de caminho absoluto:

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

Isso é útil para testes locais, mas não para instalação no sistema por diversos motivos. O Debian tem uma política contra ele, que remonta à década de 1990, embora uma discussão coerente seja rara (veja, por exemplo, a edição RPATH que coleta algumas das a informação).

    
por 02.11.2018 / 21:27