Флаг -R для компоновщика в cc/gcc

Вопрос или проблема

Ссылка:
Weak symbol

В ссылке упоминается следующий параметр компоновщика:

cc  main.o -L`pwd` -Wl,-R`pwd` -lpowerslow -o main2

Назначение всех указанных выше флагов задокументировано в Руководстве по GCC, за исключением -R.

Что этот флаг указывает компоновщику?

TIA

Vinod

Для GCC это всего лишь одна опция, а не две:

-Wl,-R`pwd` 

Конструкция -Wl,<что-то> используется для передачи части <что-то> в виде опции(й) компоновщику (ld). В данном случае, она указывает gcc вызвать ld как:

ld -R`pwd` <другие параметры...>

И если вы взгляните на man ld в Linux, вы найдете (выделено мной):

-R файл

[…]

Читать имена символов и их адреса из файла, но не перемещать его и не включать в выходной файл. Это позволяет вашему выходному файлу ссылаться символически на абсолютные адреса памяти, определенные в других программах. Вы можете использовать эту опцию более одного раза.

Для совместимости с другими ELF компоновщиками, если опция -R сопровождается именем каталога, а не именем файла, она трактуется как опция -rpath.

И опция -rpath:

-rpath=dir

Добавить каталог в путь поиска библиотек времени выполнения. Это используется при компоновке ELF исполняемого файла с общими объектами. Все аргументы -rpath конкатенируются и передаются линкеру времени выполнения, который использует их для поиска общих объектов при выполнении. […]

Таким образом, вся конструкция означает “укажите линкеру времени выполнения искать общие объекты для компоновки в текущем рабочем каталоге”.

Документация ld также отмечает:

Опция -rpath может также использоваться на SunOS. По умолчанию, на SunOS, компоновщик формирует путь поиска времени выполнения из всех предоставленных ему опций -L. Если используется опция -rpath, путь поиска времени выполнения будет формироваться исключительно с использованием опций -rpath, игнорируя опции -L. Это может быть полезно при использовании gcc, который добавляет много опций -L, которые могут находиться на файловых системах, смонтированных через NFS.

Так, общая цель этой конструкционной опции, например в

cc -g -c -o main.o main.c
cc -g -fpic -c -o power_slow.po power_slow.c
cc -shared -fpic -o libpowerslow.so power_slow.po
cc  main.o -L`pwd` -Wl,-R`pwd` -lpowerslow -o main

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

Вы должны понимать, что, хотя “встраивание” текущего рабочего каталога полезно в примерах краткосрочных бинарных файлов, таких как построенный здесь, вы должны указать что-то другое в качестве пути поиска библиотеки времени выполнения при построении чего-то, предназначенного для установки для системного использования.

Из страницы руководства ld

-R файл
--just-symbols=файл
.....
Для совместимости с другими ELF компоновщиками, если опция -R сопровождается именем каталога, а не именем файла, она трактуется как опция -rpath.

Это означает, что исполняемый файл добавит текущий каталог в список мест, в которых линкер времени выполнения будет искать общие библиотеки, что поможет ему обнаружить библиотеку powerslow.

Было бы менее запутанно использовать -rpath вместо -R.

Ответ или решение

Флаг -R в контексте использования с компилятором GCC и линковщиком ld заслуживает внимания, поскольку его назначение и поведение у различных систем могут различаться, а также оно оказывается важным для корректной работы собранных исполняемых файлов. В данном контексте -R на самом деле представляет собой алиас для -rpath, когда он используется с директориями. Чтобы полностью понять, как работает этот флаг, необходимо рассмотреть теорию, примеры и практическое применение.

Теория

Флаг -R в контексте компоновки исполняемых файлов служит для указания дополнительных директорий поиска динамических библиотек в момент выполнения программы (runtime). Если -R указан вместе с именем файла, линкер загрузит символы и их адреса из этого файла, но не будет использовать его для создания выходного файла. Однако, когда -R следует за именем директории, он становится эквивалентен флагу -rpath.

Флаг -rpath добавляет указанную директорию в путь поиска библиотек на стадии исполнения программы. Это особенно важно в UNIX-подобных системах, таких как Linux или Solaris, где динамические библиотеки (.so файлы) часто находятся в различных местах файловой системы, и необходимо сообщить загрузчику библиотек (runtime linker), где искать необходимые зависимости.

Пример

Рассмотрим следующий пример компиляции и линковки, приведенный в вопросе:

cc -g -c -o main.o main.c
cc -g -fpic -c -o power_slow.po power_slow.c
cc -shared -fpic -o libpowerslow.so power_slow.po
cc main.o -L`pwd` -Wl,-R`pwd` -lpowerslow -o main
  1. Первый этап компилирует исходный файл main.c в объектный файл main.o.
  2. Второй этап компилирует power_slow.c в позиционно-независимый объектный файл power_slow.po.
  3. Третий этап создает из power_slow.po динамическую библиотеку libpowerslow.so.
  4. Четвертый этап связывает двоичный файл main, используя main.o и libpowerslow.so.

Ключевой частью является -Wl,-R\pwd`, где-Wl,указывает GCC передать флаг-Rнапрямую линковщику, а`pwd`подставляет текущую директорию. Таким образом, линковщик будет искать динамические библиотеки в текущей директории, гарантируя, что файлmainвыполнится с версиейlibpowerslow.so`, скомпилированной в третьем шаге.

Применение

Использование флага -R важно при разработке программных продуктов, которые зависят от собственных динамических библиотек, находящихся не в стандартных путях поиска. Это помогает избежать конфликтов с системными библиотеками, которые могут иметь то же имя.

Тем не менее, на стадии деплоя следует осторожно использовать -rpath, так как он добавляет дополнительные абсолютные пути в исполняемый файл, которые могут изменить поведение программы при перемещении внутри файловой системы или если системы различаются в структурах директорий. В частности, хранение таких путей может привести к потенциальным проблемам безопасности и повышению зависимости от конкретной конфигурации системы.

Заключение

Флаг -R, хоть и недостаточно документирован в документации GCC, является мощным инструментом в руках разработчика для управления путями поиска динамических библиотек на стадии исполнения. Однако, для долгосрочных и переносимых решений, таких как производство и распространение ПО, рекомендуется использовать более целенаправленный подход к управлению путями поиска динамических библиотек, например использование LD_LIBRARY_PATH или конфигурационных файлов загрузчика. Это поможет создать более надежные и универсальные приложения.

Оцените материал
Добавить комментарий

Капча загружается...