ProblemWithVerifyELFAndRPATH: различия между версиями
(Import from freesource.info) |
м (→Смотри также: +link) |
||
Строка 87: | Строка 87: | ||
* [http://wiki.sisyphus.ru/devel/TextRel/libtool http://wiki.sisyphus.ru/devel/TextRel/libtool] | * [http://wiki.sisyphus.ru/devel/TextRel/libtool http://wiki.sisyphus.ru/devel/TextRel/libtool] | ||
* [http://lists.altlinux.ru/pipermail/devel/2005-June/021705.html http://lists.altlinux.ru/pipermail/devel/2005-June/021705.html] | * [http://lists.altlinux.ru/pipermail/devel/2005-June/021705.html http://lists.altlinux.ru/pipermail/devel/2005-June/021705.html] | ||
* http://lists.altlinux.org/pipermail/devel/2011-December/192727.html |
Версия от 15:17, 15 декабря 2011
Проблемы с ELF
RPATH
При сборке wmnetload я столкнулся со следующей ошибкой:
verify-elf: ./usr/bin/wmnetload: RPATH entry contains ":": :/usr/local/lib
Было два возможных выхода из сложившейся ситуации, даже три:
1) ослабить проверку, добавив в спек %set_verify_elf_method textrel=relaxed 2) докопаться до истинной причины и решить проблему в корне 3) не собирать wmnetload :-)
Я конечно же выбрал второй вариант и ниже опишу последовательность своих действий, в результате которых удалось избежать этой ошибки. Возможно, что в вашем случае разрешить подобную ошибку придется иным способом, но в моем сработал этот. В любом случае рекомендую вам ознакомиться с материалами, ссылки на которые приведены в конце.
Немного теории
Перед тем как начать что-то делать не плохо бы узнать что такое RPATH и почему /usr/local/lib, присутствующий в нем, является ошибкой.
RPATH -- это свойство некоего ELF-объекта (программы или библиотеки) хранить в себе дополнительные пути поиска разделяемых (shared) библиотек. Т.е. программа будет искать so'шку сначала там, куда указывает RPATH, а затем в /lib, /usr/lib и других системных путях, которые указаны в /etc/ld.so.conf. Значение переменный RPATH "зашито" в самой програме и вы можете увидеть его вызвав readelf -a program. Среди множества появившейся информации ищите упоминание про RPATH. Маленькая тонкость: в бинарниках со стандартным значением RPATH вы не найдете упоминания о нем, так как по умолчанию значение у переменной пустое. Для примера приведу часть вывода readelf для все того же wmnetload, скомпилированного с /usr/local/lib в RPATH:
[c0der@mycomp ~/wm/bin]$ readelf -a wmnetload | grep RPATH 0x0000000f (RPATH) Library rpath: [ :/usr/local/lib]
В случае, если RPATH не содержит дополнительных путей, мы ничего не увидим, т.е. вывод программы будет пустым.
Почему RPATH не должен содержать какие-либо пути отличные от стандартных? Потому что все библиотеки должны располагаться в стандартных и отведенных для этого местах, а именно в /usr/lib. "Потому что должны быть веские причины держать разделяемую библиотеку не в /usr/lib и тем более веские держать их в разных местах, ни одно из которых не является /usr/lib" (с) lioka
Поиск источника проблемы
Начал я с того, что по'grep'ал исходники на предмет этого самого RPATH. Все указывало на файл configure.in, в котором я обнаружил следующие строки:
dnl dnl Hack in rpath -- yes, this sucks, and it even has a hidden dependency dnl on the implementation of AC_PATH_XTRA. F@&* you, portability. dnl if test "$GCC" = yes; then if test "ac_R_space" = no; then RPATH="-Wl,\"-R$LIBRARY_RPATH\"" else RPATH="-Wl,\"-R $LIBRARY_RPATH\"" fi ...
Как видим, RPATH включает в себя $LIBRARY_RPATH. Тогда ищем где и как определяется $LIBRARY_RPATH. Наша цель узнать как в ней оказывается /usr/local/lib и удалить этот путь.
LIBRARY_RPATH=`echo "$LIBRARY_SEARCH_PATH" | sed 's/[ *]-L[ *]/:/g'`
Теперь ищем где же определяется $LIBRARY_SEARCH_PATH:
LIBRARY_SEARCH_PATH="$lib_search_path -L/usr/local/lib"
Вот то что мы искали! Вот откуда "растут ноги" у нашей проблемы. Остаётся лишь удалить этот путь из RPATH.
Решение проблемы
Как мы выяснили выше для ликвидации проблемы нужно удалить путь /usr/local/lib из $LIBRARY_SEARCH_PATH. Я сделал это так:
%__sed -i 's|LIBRARY_SEARCH_PATH="$lib_search_path -L/usr/local/lib"|LIBRARY_SEARCH_PATH="$lib_search_path"|' configure.in
Т.е. просто заменил строку sed'ом. Этот код следует вызывать в секции %pre, т.е. до вызова %configure. Также следует не забыть пересоздать configure-скрипт, вызвав autoconf (%__autoconf).
LD_LIBRARY_PATH
При расположении библиотек в нестандартных местах и использовании нестандартной среды сборки (не autotools) может возникнуть проблема, при которой проверка бинарных файлов не может пройти. Если не проходит проверка бинарных файлов из /usr/bin, скорее всего в них указан (или вовсе не указан) неверный RPATH.
Проверка при сборке пакета
Для проверки бинарных файлов и библиотек используется значение LD_LIBRARY_PATH, полученное примерно следующим образом: - добавляется значение RPATH; - добавляется архитектурно-зависимый путь поиска библиотек (%_libdir:/%_lib); - к вычисленному значению добавляется вывод от libtool-ldconfig-dump (я так понимаю он скажет какие мы нестандартные каталоги для библиотек использовали в проекте) - к полученному списку добавляется в начало он же, но с префиксом %buildroot для каждого элемента;
Благодарности
- Дмитрию Левину (ldv@) за то что сделал все эти проверки
- Виталию Липатову (lav@) за то что предложил и вдохновил написать об этом
- Сергею Большакову aka lioka (sbolshakov@) за объяснение теоретических основ