Как, собственно, `-fno-semantic-interposition` отличается от` -fvisibility = protected`?

o11c спросил: 13 июня 2018 в 09:31 в: c++

От https://gcc.gnu.org/onlinedocs/gcc-8.1.0 /gcc/Optimize-Options.html#index-fsemantic-interposition

-fsemantic-interposition

От https://gcc.gnu.org /onlinedocs/gcc/Common-Function-Attributes.html#index-visibility-function-attribute

protected

Защищенная видимость похожа на видимость по умолчанию, за исключением того, что она указывает, что ссылки в пределах определяющего модуля привязываются к определению в этом модуле. То есть объявленный объект не может быть переопределен другим модулем.

Это звучит точно так же.

Есть ли какая-то реальная разница, кроме этого -fno-semantic-interposition для изменения любых функций явно с пометкой default на protected?


2 ответа

Florian Weimer ответил: 14 июня 2018 в 06:20

Этот вопрос трудно ответить, потому что в настоящее время -fsemantic-interposition на самом деле не работает. В этом примере

int a;int
f1 (int a)
{
  return a;
}int
f2 (void)
{
  return f1 (a) - a;
}

тело f2 эффективно оптимизировано в return 0; даже с помощью -O2 -fsemantic-interposition (и также с помощью -O2 -fno-semantic-interposition, если смысл этой опции в документации заменен). Я указал на ошибку.

Вероятное намерение состоит в том, что -fsemantic-interposition отключит такие оптимизации, так что вы получите вызов f1 и явное вычисление результата.

Видимость символов ELF на самом деле не связана с этим, главным образом потому, что она применима только к динамической компоновке. Редактор ссылок может по-прежнему вставлять символы в статическое время ссылки (например, с помощью опции -z muldefs), поэтому компилятор должен действительно предоставить способ включения interposition without для изменения свойств символа ( поэтому что-то еще за пределами __attribute__ ((weak))).

o11c ответил: 14 июня 2018 в 03:18
За закрытие комментариев к этой ошибке я добавил -fPIC ... then -fsemantic-interposition -fvisibility=protected позволяет точно такую ​​же оптимизацию, как -fno-semantic-interposition
yugr ответил: 15 июня 2018 в 07:52
-fsemantic-interposition влияет только на код, скомпилированный для разделяемых библиотек (с помощью -fPIC). Функции в исполняемых файлах не являются промежуточными, поэтому компилятор будет оптимизировать их независимо от -semantic-interposition. По этой причине ошибка была решена как недействительная.
PSkocik ответил: 13 июня 2018 в 09:50

-fno-semantic-interposition должен быть о генерации кода. -fvisibility=protected относится к атрибуту символа. protected появилась перед -fsemantic-interposition и, как объясняется в книге Ульриха Дреппера "Как писать общие библиотеки", это атрибут видимости, который вы не должны использовать.

Общий ELF ABI определяет другой режим видимости: защищенный. В этой схеме ссылки на символы, определенные в одном и том же объекте, всегда удовлетворяются локально. Но символы по-прежнему доступны вне DSO. Это звучит как идеальный механизм для оптимизации DSO, избегая использования экспортированных символов (см. Раздел 2.2.7), но это не так. Обработка ссылок на защищенные символы еще дороже, чем нормальный поиск. Эта проблема является требованием стандарта ISO C. Стандарт требует, чтобы указатели на функции, указывающие на одну и ту же функцию, могли быть использованы для равенства. Это правило было бы нарушено с помощью быстрой и простой реализации защищенной видимости. Предположим, приложение, которое ссылается на защищенную функцию в DSO. Также в DSO есть еще одна функция, которая ссылается на указанную функцию. Указатель в приложении указывает на запись PLT для функции в PLT приложения. Если поиск защищенного символа должен просто вернуть адрес функции, находящейся в DSO, адреса будут отличаться. В среде программирования без этого требования указателей функций использование защищенной видимости будет полезно и быстро. Но так как обычно существует только одна реализация динамического компоновщика в системе, и эта реализация должна хорошо работать с программами на C, использование защищенной оболочки крайне обескуражено.

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

o11c ответил: 13 июня 2018 в 09:58
Это не объясняет, как отличается -fno-semantic-interposition. (и не объясняет, насколько защищенная видимость как-то хуже, чем видимость по умолчанию ... и игнорирует тот факт, что большинство функций вызываются напрямую, а не превращаются в указатели на функции)
PSkocik ответил: 13 июня 2018 в 10:10
-fno-semantic-interposition сообщает компилятору оптимизировать код, как если бы символы не были взаимозаменяемыми. __attribute__((visibility("protected"))) сообщает компилятору прикрепить атрибут видимости к генерируемому им символу (параметр CLI -fvisibility=* указывает значение по умолчанию), которое, в свою очередь, инструктирует компоновщик привязать символ определенным образом. А именно, через PLT для функций, если они видны, IP-относительно, если они скрыты, а в некоторых PLT-невзрачных, но дорогостоящих, если они защищены.