Могу ли я изменить '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

Другие вопросы по тегам