В чем разница между флагами -symbolic и -shared GCC?
-
22-09-2019 - |
Вопрос
Судя по описанию документации, они, похоже, делают одно и то же, за исключением того, что "не все системы" поддерживают shared и "только некоторые системы" поддерживают symbolic (неясно, являются ли это одним и тем же набором систем):
-общий доступ Создайте общий объект, который затем может быть связан с другими объектами для формирования исполняемого файла.Не все системы поддерживают эту опцию.Для получения предсказуемых результатов необходимо также указать тот же набор параметров, который использовался для генерации кода (-fpic, -fPIC или model подразделы) при указании этого параметра.[1]
-символьный Привязывайте ссылки к глобальным символам при создании общего объекта.Предупреждать о любых неразрешенных ссылках (если они не переопределены редактором ссылок option -Xlinker -z -Xlinker defs).Только несколько систем поддерживают эту опцию .
Я подозреваю, что разница заключается в части "Создать общий объект, который затем может быть связан с другими объектами для формирования исполняемого файла", но это звучит как нечто, что верно для любой библиотеки.Означает ли это, что результирующий общий объект также может быть связан статически?
Решение
Краткие сведения:-символ предотвращает интерпозицию функции внутри общего объекта
Связывание с общими объектами позволяет использовать функцию, называемую интерпозицией символов.Идея заключается в том, что вы можете "вставить" новое определение глобального символа так, чтобы оно вызывалось скорее, чем "обычное" определение.
Одним из классических примеров является malloc().В наиболее распространенном случае malloc() определяется в libc.Но вы можете вставить свою собственную версию malloc, загрузив библиотеку, которая определяет этот символ, перед загрузкой libc (большинство компоновщиков среды выполнения позволяют использовать LD_PRELOAD для определенных библиотек для загрузки перед исполняемым файлом).
По умолчанию любая функция внутри общего объекта, которая не является статической, является глобальным символом.Из-за этого могут быть вставлены любые функции внутри общего объекта.Рассмотрим сценарий, в котором общий объект имеет функции high_level() и low_level(), а high_level() вызывает low_level() как часть его реализации, и ни high_level(), ни low_level() не являются статическими функциями.
Можно вставить функцию low_level() таким образом, чтобы функция high_level() вызывала функцию low_level() из другого общего объекта.
Вот тут-то и вступает в дело символичность.При создании вашего общего объекта компоновщик увидит, что low_level() определен в том же общем объекте, что и high_level(), и привяжет вызов таким образом, что он не может быть вставлен.Таким образом, вы знаете, что любые вызовы из одной функции в вашем общем объекте в другую в том же общем объекте никогда не будут вставлены.