É possível configurar o carregador dinâmico para um executável?

2

Estou procurando uma maneira de permitir que um executável encontre sua biblioteca compartilhada, mas, para evitar conflitos com qualquer pacote que possa usar uma versão diferente da mesma biblioteca compartilhada, prefiro manter essas bibliotecas em um 'caminho particular' '(não / usr / lib).

As possíveis maneiras parecem:

  • rpath incorporado no executável
  • define LD_LIBRARY_PATH quando o executável é iniciado
  • inclua o caminho das bibliotecas na configuração do ldconfig em um arquivo ld.so.conf.d

o rpath vincula a estrutura de destino à construção, o caminho de configuração ld.so.conf.d para o sistema, o LD_LIBRARY_PATH precisa que o processo do chamador esteja ciente disso.

Então, eu queria saber se é possível usar ld.so.conf.d (ou configuração de carregador semelhante) aplicada somente a um executável?

    
por mpromonet 04.09.2014 / 18:12

3 respostas

0

É possível usar um rpath relativo usando $ORIGIN .

Vincular executáveis a -Wl,-rpath,'$ORIGIN/../lib' permite que os executáveis encontrem suas bibliotecas instaladas:

  • executáveis em <base>/bin/
  • bibliotecas compartilhadas em <base>/lib/

Continuar assim permite configurar este link apenas para esses executáveis e o diretório <base> pode estar em qualquer lugar.

    
por 30.03.2016 / 20:44
2

Não é fácil. Os arquivos ld.so.conf têm um formato muito simples: são apenas uma lista de caminhos.

Você poderia fazer algo construindo seu executável com um interpretador diferente ; o normal seria algo como /lib64/ld-linux-x86-64.so.2 1 e é o que realmente é responsável por realizar a vinculação dinâmica. Portanto, o vinculador dinâmico personalizado pode procurar em ld.so.conf diferente ou fazer qualquer coisa. Mas isso soa muito pior do que o rpath!

Uma solução muito mais simples é um wrapper. Instale o binário como program.real ou, melhor ainda, em /usr/local/lib/ em algum lugar (isto é, não em $PATH ). Em seguida, coloque um script de shell simples como /usr/local/bin/program :

#!/bin/sh
export LD_LIBRARY_PATH=/path/to/libs
exec /usr/local/lib/program/program.real

Agora, a localização da sua biblioteca é independente da compilação, mas o programa de chamada não precisa de conhecimento dela.



1 : maneira rápida de encontrar o que normalmente está no seu sistema: readelf /bin/bash -p .interp . Tente alguns executáveis diferentes; você encontrará pelo menos programas de 32 e 64 bits usando um diferente.

    
por 04.09.2014 / 19:50
-1

O argumento filename para dlopen pode ser um caminho absoluto (começa com ' / ').

Portanto, armazene o 'caminho privado' em um arquivo de configuração, construa o nome completo da biblioteca a partir dele. Ou, se você souber que a biblioteca particular estará no mesmo diretório que o executável, faça operações de string simples no caminho para o executável para encontrá-la ...

#include <dlfcn.h>
#include <unistd.h>
#include <string.h>

static int (*foo)();

/* ... */
char buf[BUFSIZ];
char *lastslash;
void *handle;

realpath(argv[0],buf);
lastslash = strrchr(buf,'/');
strcpy(lastslash,"foo." VERSION_BUILD ".so");
dlopen(buf,RTLD_LOCAL | RTLD_LAZY);
*(void **)(&foo) = dlsym(handle, "foo");

/* ... */
printf("%d\n",foo());
    
por 04.09.2014 / 19:18