Генерация ошибки времени соединения для устаревших функций - PullRequest
6 голосов
/ 14 января 2011

Есть ли способ с помощью gcc и GNU binutils пометить некоторые функции так, чтобы они генерировали ошибку во время соединения, если они используются? Моя ситуация такова, что у меня есть некоторые библиотечные функции, которые я не удаляю для совместимости с существующими двоичными файлами, но я хочу убедиться, что ни один недавно скомпилированный двоичный файл не пытается использовать эти функции. Я не могу просто использовать атрибуты gcc времени компиляции, потому что код, который нарушает работу, игнорирует мои заголовки и обнаруживает присутствие функций с помощью скрипта configure и сам их прототипирует. Моя цель - сгенерировать ошибку времени соединения для плохих configure сценариев, чтобы они перестали обнаруживать существование функций.

Редактировать: Идея ... будет ли использование ассемблера для указания неправильного .type для точек входа совместимым с динамическим компоновщиком, но при создании ссылок на новые программы будут возникать ошибки соединения?

Ответы [ 3 ]

2 голосов
/ 15 января 2011

FreeBSD 9.x делает что-то очень похожее на то, что вы хотите с помощью функции ttyslot(). Эта функция не имеет смысла с utmpx. Хитрость в том, что существуют только версии этого символа не по умолчанию. Следовательно, ld не найдет его, но rtld найдет версионное определение при запуске старого двоичного файла. Я не знаю, что произойдет, если старый двоичный файл имеет неверсионную ссылку, но, вероятно, разумно, если есть только одно определение.

Например,

__asm__(".symver hidden_badfunc, badfunc@MYLIB_1.0");

Как правило, также будет версия по умолчанию, например

__asm__(".symver new_badfunc, badfunc@@MYLIB_1.1");

или с помощью скрипта, совместимого с Solaris, но хитрость заключается не в том, чтобы добавить его.

Обычно директива asm заключена в макрос.

Трюк зависит от расширений GNU для определения версий символов с помощью директивы ассемблера .symver, поэтому он, вероятно, будет работать только на Linux и FreeBSD. Совместимые с Solaris версии сценариев могут выражать только одно определение на символ.

Дополнительная информация: .symver директива в info gas, Ульрих Дреппер "Как писать разделяемые библиотеки", фиксация, которая устарела ttyslot () в http://gitorious.org/freebsd/freebsd/commit/3f59ed0d571ac62355fc2bde3edbfe9a4e722845

0 голосов
/ 14 января 2011

Одной из идей может быть создание библиотеки-заглушки с этими символами, но с неожиданными свойствами.

  • возможно, создавать объекты с именами функций, поэтому компоновщик на этапе настройки может жаловаться на несовместимость символов
  • создание функций с зависимостью "dont_use_symbol_XXX", которая никогда не разрешается
  • или фальсифицируйте файл .a с глобальным индексом, который бы выполнял ваши функции, но где члены .o в архиве имеют неправильный формат
0 голосов
/ 14 января 2011

Лучший способ вызвать ошибку времени компоновки для устаревших функций, которые вы не хотите, чтобы люди использовали, состоит в том, чтобы убедиться, что устаревшие функции не присутствуют в библиотеках, что делает их одним этапом после «устаревших».

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

Получить предупреждение о времени соединения довольно сложно. Очевидно, что GCC делает это для некоторой функции (mktemp() и др.), И Apple предупреждает GCC, если вы запускаете программу, которая использует gets(). Я не знаю, что они делают, чтобы это произошло.


В свете комментариев, я думаю, вам нужно решить проблему во время компиляции, а не ждать до времени ссылки или выполнения.

Атрибуты GCC включают (из руководства GCC 4.4.1):

error ("message")

Если этот атрибут используется в объявлении функции и вызов такой функции не устранено через устранение мертвого кода или другие оптимизации, ошибка который будет включать в себя сообщение будет диагностировано. Это полезно для времени компиляции проверка, особенно вместе с __builtin_constant_p и встроенными функциями где проверка аргументов встроенной функции невозможна через extern char [(условие)? 1: -1]; трюки. Пока можно выйти из функции undefined и, таким образом, вызывает сбой ссылки, при использовании этого атрибута проблема будет диагностирован ранее и с точным местоположением звонка даже при наличии встроенные функции или когда не выдается отладочная информация.

warning ("message")

Если этот атрибут используется в объявлении функции и вызов такой функции не устраняется путем устранения мертвого кода или других оптимизаций, предупреждение который будет включать в себя сообщение будет диагностировано. Это полезно для времени компиляции проверка, особенно вместе с __builtin_constant_p и встроенными функциями. Пока можно определить функцию с помощью сообщения в .gnu.warning * раздел, при использовании этого атрибута проблема будет диагностирована ранее и с точным местоположением вызова даже при наличии встроенных функций или когда нет выдача отладочной информации.

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

...