Могу ли я изменить 'rpath' в уже скомпилированном двоичном файле?
У меня есть старый исполняемый файл, который запланирован для кучи металлолома, но его еще нет. Он опирается на некоторые библиотеки, которые были удалены из моего окружения, но у меня есть некоторые библиотеки-заглушки в тех местах, где они работают нормально. Я хотел бы указать этот исполняемый файл на эти заглушки. Да, я мог бы установить LD_LIBRARY_PATH, но этот исполняемый файл вызывается многими сценариями и многими пользователями, и я бы хотел исправить это в одном месте.
У меня нет источника для этого, и было бы трудно получить его. Я думал - могу ли я отредактировать этот файл, используя редактор с поддержкой ELF, и добавить простой PATH в rpath, чтобы он поразил новые библиотеки? Возможно ли это, или когда вы создаете бинарный файл ELF, вы фиксируете вещи в локациях, и они не могут быть перемещены?
3 ответа
Есть инструмент под названием chrpath
который может сделать это - он, вероятно, доступен в пакетах вашего дистрибутива.
Существует более универсальный инструмент, чем chrpath
называется patchelf
, Первоначально он был создан для использования при создании пакетов для Nix и NixOS (система пакетов и дистрибутив GNU/Linux).
Если в двоичном файле отсутствует rpath (здесь он называется rdsamp), chrpath
терпит неудачу:
chrpath -r '$ORIGIN/../lib64' rdsamp
rdsamp: no rpath or runpath tag found.
С другой стороны,
patchelf --set-rpath '$ORIGIN/../lib64' rdsamp
преуспевает просто отлично.
Как сказал @user7610, правильный путь - это patchelf
инструмент.
Но я чувствую, что могу дать более полный ответ, охватывающий все команды, необходимые для выполнения именно этого.
Прежде всего, многие разработчики говорят о RPATH
, но они на самом деле имеют в виду RUNPATH
, Это два разных необязательных динамических раздела, и загрузчик обрабатывает их совершенно по-разному. Вы можете прочитать больше о разнице между ними здесь. На данный момент, просто помните, что если RUNPATH
установлен, RPATH
игнорируется!
Смотрите текущий R[UN]PATH
readelf -d <path-to-elf> | egrep "RPATH|RUNPATH"
Очистить путь R [UN]
patchelf --remove-rpath <path-to-elf>
Заметки:
- Удаляет оба
RPATH
а такжеRUNPATH
Добавить значения в R[UN]PATH
patchelf [--force-rpath] --set-rpath "<desired-rpath>" <path-to-elf>
Заметки:
<desired-path>
список разделенных запятыми каталогов, например:/my/libs:/my/other/libs
- Если вы укажете
--force-rpath
, устанавливаетRPATH
иначе устанавливаетRUNPATH
Это сработало для меня, заменив XORIGIN на $ORIGIN.
chrpath -r '\$\ORIGIN/../lib64' httpd