web-dev-qa-db-fra.com

Puis-je changer 'rpath' dans un binaire déjà compilé?

J'ai un ancien exécutable qui est programmé pour le rebut, mais ce n'est pas encore là. Cela dépend de certaines bibliothèques qui ont été supprimées de mon environnement, mais j'ai des bibliothèques à bouts où cela fonctionne bien. Je voudrais pointer cet exécutable sur ces bibliothèques de stub. Oui, je pourrais définir LD_LIBRARY_PATH, mais cet exécutable est appelé à partir de nombreux scripts, ainsi que de nombreux utilisateurs et j'aimerais le résoudre en un seul endroit.

Je n'ai pas de source pour cela et il serait difficile de l'obtenir. Je pensais - puis-je éditer ce fichier en utilisant un éditeur compatible avec ELF et ajouter un simple PATH à rpath pour qu'il soit affiché dans les nouvelles bibliothèques? Est-ce possible ou une fois que vous avez créé un fichier binaire ELF, vous corrigez les choses en fonction des emplacements et vous ne pouvez pas les déplacer?

66
Rich Homolka

Il existe un outil appelé chrpath qui peut le faire - il est probablement disponible dans les packages de votre distribution.

64
TomH

Il existe un outil plus universel que chrpath appelé patchelf . Il a été créé à l'origine pour être utilisé dans la création de packages pour Nix et NixOS (système de packaging et distribution GNU/Linux).

S'il n'y a pas de rpath dans un binaire (appelé ici rdsamp), chrpath échoue:

chrpath -r '$Origin/../lib64' rdsamp 
rdsamp: no rpath or runpath tag found.

D'autre part,

patchelf --set-rpath '$Origin/../lib64' rdsamp

réussit très bien.

124
user7610

Cela a fonctionné pour moi, en remplaçant XORIGIN par $ Origin.

chrpath -r '\$\Origin/../lib64' httpd

0
vikram kedlaya

Tout comme @ user7610, la bonne solution consiste à utiliser l'outil patchelf.

Mais j'estime pouvoir donner une réponse plus complète, couvrant toutes les commandes dont on a besoin pour faire exactement cela.

Tout d'abord, de nombreux développeurs parlent de RPATH, mais ils veulent en fait dire RUNPATH. Ce sont deux sections dynamiques facultatives différentes, et le chargeur les traite très différemment. Vous pouvez en savoir plus sur la différence entre eux ici. Pour l'instant, rappelez-vous que si RUNPATH est défini, RPATH est ignoré!

Voir l'actuel R [UN] PATH

readelf -d <path-to-elf> | egrep "RPATH|RUNPATH"

Efface le chemin R [UN]

patchelf --remove-rpath <path-to-elf>

Remarques:

  • Supprime à la fois RPATH et RUNPATH

Ajouter des valeurs à R [UN] PATH

patchelf [--force-rpath] --set-rpath "<desired-rpath>" <path-to-elf>

Remarques:

  • <desired-path> est une liste de répertoires séparés par des virgules, par exemple: /my/libs:/my/other/libs
  • Si vous spécifiez --force-rpath, définissez RPATH, sinon définissez RUNPATH
0
Daniel Trugman