В чем разница между флагами -symbolic и -shared GCC?

Из описания документации они, похоже, делают то же самое, за исключением того, что поддержка «не всех систем» разделена, а «только некоторые системы» поддерживают символическую (непонятно, являются ли они одним и тем же набором систем):

-shared Создавать общий объект, который затем может быть связан с другими объектами для формирования исполняемого файла. Не все системы поддерживают эту опцию. Для outlookируемых результатов вы также должны указать тот же набор параметров, которые были использованы для генерации кода (-fpic, -fPIC или подсистемы модели) при указании этой опции. [1]

-symbolic Привязать ссылки к глобальным символам при создании общего объекта. Предупреждать о каких-либо неразрешенных ссылках (если не переопределено опцией редактора ссылок -Xlinker -z -Xlinker defs). Эта опция поддерживает только несколько систем.

Я подозреваю, что разница заключается в «Создавать общий объект, который затем может быть связан с другими объектами, чтобы сформировать исполняемую» часть, но это похоже на то, что верно для любой библиотеки. Означает ли это, что результирующий общий объект также может быть связан статически?

    Реферат: -symbolic предотвращает интерполяцию внутри общих объектов

    Связывание с общими объектами допускает функцию, называемую интерполяцией символов. Идея состоит в том, что вы можете «вставить» новое определение глобального символа, чтобы оно называлось скорее «регулярным» определением.

    Один classический пример – 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 () из другого общего объекта.

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