Относительный к исполняемому пути динамический компоновщик / интерпретатор ld-linux - PullRequest
0 голосов
/ 23 февраля 2019

Я хочу отправлять и архивировать двоичные файлы (исполняемые файлы с библиотеками), которые имеют обратную и прямую совместимость с максимально возможным количеством дистрибутивов Linux и возможностью перемещения всего пакета.Как я понимаю, системные библиотеки, такие как libc, также должны быть отправлены, потому что исполняемый файл будет аварийно завершен при другой версии libc.Между тем libc, похоже, связан с ld-linux (например, двоичные файлы, скомпилированные при тестировании Debian, уже не работают на Ubuntu 18.04 LTS), поэтому мне нужно также упаковать ld-linux.

Мое решение - поставитьвсе исполняемые файлы и библиотеки в одном каталоге и установите rpath на $ORIGIN (либо связав с -Wl,rpath=$ORIGIN, либо установив с помощью chrpath или patchelf).Это делает библиотеки перемещаемыми вместе с исполняемым файлом и работает для всех библиотек, кроме ld-linux, который является самим компоновщиком.

Возможно изменить путь динамического компоновщика с помощью -Wl,--dynamic-linker=/my/path/ld-linux.so или установить его с помощью patchelf но путь должен быть абсолютным:

  1. Трюк $ORIGIN не работает
  2. Относительный путь, такой как ./, работает, но только если текущий каталог такой жекак сам загрузчик (исполняемый файл вылетает с ошибками при запуске из другого места)
  3. Я могу написать сценарий оболочки для обнаружения всех путей и запуска исполняемого файла с /my/path/ld-linux.so /my/path/myexecutable $@, но это означает еще один уровень косвенности и издержекЯ хотел бы избежать.

Есть ли способ установить путь к ld-linux относительно исполняемого файла непосредственно в исполняемый файл?

Может быть, есть способ статически связатьзагрузчик ld-linux?

1 Ответ

0 голосов
/ 25 февраля 2019

Как я понимаю, системные библиотеки, такие как libc, также должны поставляться, потому что исполняемый файл будет аварийно завершаться при другой версии libc.

То есть неверно : GLIBCгарантирует обратную совместимость (исполняемый файл, построенный на более старой системе, продолжит работать на более новых версиях GLIBC).

Единственный разумный способ добиться того, чего вы хотите, - это скомпилировать с самой старой версиейGLIBC, который вы хотите поддерживать.

Между тем libc, похоже, связан с ld-linux

Правильно: libc.so.6 и ld-linux являются частью GLIBC, должен происходить из той же сборки, и любое несоответствие может привести к катастрофическому отказу (SIGSEGV внутри libc.so.6 или внутри ld-linux).

Мне нужно упаковать ld-linux тоже.

Это сложно: абсолютный путь к ld-linux жестко закодирован в a.out и не может быть изменен.Сделать перемещаемым a.out, который может допускать изменения пути к ld-linux, невозможно (если не считать явного вызова загрузчика, который вы уже пробовали; который плохо работает для исполняемых файлов, которые повторно исполняются сами)).

Обновление:

Я мог бы попытаться использовать старую Ubuntu LTS и получить большую часть обратной совместимости, но тогда я не получил бы новый C++ 17 компиляторов, которые в основном сводят на нет весь смысл современной программной инженерии.

Вы можете установить более новый компилятор на более старой системе и получить C ++ 17 с более старой GLIBC.

Одна трудность в том, что вам может потребоваться более новый libstdc++.so.6.

Хорошая новость заключается в том, что -Wl,-rpath=$ORIGIN работает нормально - это только GLIBC, который трудно переместить.Вы также можете связать исполняемый файл с libstdc++.a с --static-libstdc++.

Однако при этом могут возникнуть последствия для лицензирования (но с другой стороны, ваш план уже включал распространение всех библиотек, так что проблема не нова).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...