Tl: dr : Se você precisar continuar usando várias versões da libc , como muitos de nós, um utilitário importante a ser usado é o PatchElf .
Normalmente, se tudo o que você deseja é forçar sua própria versão do interpretador de programa ao criar seu próprio programa, tudo o que você precisa fazer é compilar com as seguintes opções:
gcc -Wl,-dynamic-linker,/my/lib/ld-linux.so.2 ...
Mas isso não funciona com utilitários de terceiros e com alguns objetos compartilhados que são no entanto executável por si mesmos, para que invocar patchelf em um determinado programa ELF como segue:
patchelf --set-interpreter /my/lib/my-ld-linux.so.2 someprogram
A razão pela qual não se trata apenas de editar com um editor hexadecimal o antigo executável e substituir o endereço antigo do intérprete pelo novo, é que os dois não precisam ter o mesmo tamanho; patchelf cuida de ampliar seu executável para você.
Você também pode alterar a variável rpath , da seguinte maneira:
patchelf --set-rpath /my_libs:$LD_LIBRARY_PATH someprogram
Acho isso muito mais prático do que usar os invólucros comuns em torno de comandos com LD_LIBRARY_PATH .
Quanto ao execve , deve ser apenas a chamada de sistema mais fundamental no Unix: execve (filename) executa o nome do arquivo especificado. Por exemplo, seu shell executa um comando por meio de uma chamada da família execve : primeiro se bifurca e, em seguida, o processo filho gera o comando execve ( ls, cd ,, ... o nome dele). A maioria dos programas precisa de bibliotecas vinculadas dinamicamente, por exemplo, para ls :
$ ldd $(which ls)
linux-vdso.so.1 => (0x00007ffe3b0e7000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f1423dda000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1423a11000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f14237a0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f142359c000)
/lib64/ld-linux-x86-64.so.2 (0x0000563800043000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f142337f000)
Quando você carrega ls , é não o ponto de entrada normal de binário que é usado no início, mas ld-linux em vez disso: ele cuida de carregar todos os não resolvidos, as bibliotecas necessárias, e então transfere o controle para a aplicação real, ls neste caso. Faz isso executando o arquivo do programa.
Não sou capaz de dizer por que exatamente seu programa trava., Mas tentaria verificar se todos os programas invocados exigem o mesmo intérprete; você faz isso verificando a saída de:
$ readelf -l / bin / ls
O tipo de arquivo Elf é EXEC (arquivo executável)
Ponto de entrada 0x4049a0
Existem 9 cabeçalhos de programa, começando no deslocamento 64
Cabeçalhos do programa:
Tipo Offset VirtAddr PhysAddr
Alinhamento de sinalizadores FileSiz MemSiz
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 RE 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Solicitando intérprete de programa: /lib64/ld-linux-x86-64.so.2]
...........................
(a ênfase é minha ...).
EDIT : uma excelente discussão de um dos autores da chamada do sistema execveat pode ser encontrada aqui , e o código do kernel relevante está aqui . O código mostra que nenhuma variável do sistema é lida e a rotina load_elf_binary examina o interpretador de programa PT_INTERP .