Программа Unix, использующая неправильную функцию из общих библиотек - PullRequest
3 голосов
/ 06 марта 2010

Я работаю над рефакторингом набора старых утилит и созданием нового сервера, который будет использовать общий код из всех них, чтобы объединить их функциональность и разрешить внешний доступ удаленным клиентам. Для каждой утилиты я беру код, который мне нужен для сервера, и реорганизую его в общую библиотеку, чтобы утилита и сервер теперь связывались с общей библиотекой. Из-за способа, которым бывший разработчик этих утилит делал вещи, они в значительной степени просто копировали и вставляли все, когда им нужно было создать новую утилиту, так что есть тонна функций, которые имеют одинаковую сигнатуру (то есть обратные вызовы для анализатора XML), но делать разные вещи внутри.

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

Например, у меня есть xml для устройств A, B, C, которые анализируются общей библиотекой xml, но каждое устройство имеет свою собственную общую библиотеку libA, libB, libC, которая используется сервером. Когда я обращаюсь к серверу с просьбой отправить xml для устройства C, он использует функцию 'HandleStartElement' из libA вместо функции с тем же именем и сигнатурой в libC, хотя общие библиотеки только объявляют эти функции внутренне и не Не делитесь заголовками, которые упоминают эти внутренние обратные вызовы для разбора XML.

Может кто-нибудь объяснить мне, почему он не читает правильную функцию и как избежать этого в будущем?

Мой make-файл для сервера имеет следующие флаги для компиляции основной программы:

-I../include -L../lib -lA -lB -lC

Каждая общая библиотека использует флаги рядом с отсутствующими для общей библиотеки и не использует -fPIC.

1 Ответ

7 голосов
/ 06 марта 2010

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

Если я правильно понимаю вашу проблему, то функции с одинаковыми именами не предназначены для «просмотра» за пределами общей библиотеки. Общая библиотека имеет «динамическую таблицу символов», в которой указывается, какие символы экспортируются и импортируются общей библиотекой. С инструментами GNU вы можете увидеть его содержимое с помощью nm -D libfoo.so. Традиционные линкеры Unix заполняют эту таблицу символов, используя все открытые сущности в объектных файлах (а именно, не static функции и глобальные переменные). Здесь вам нужна более контролируемая конструкция таблицы символов. Если ваш код использует инструменты GNU (например, вы работаете в Linux), тогда вы хотите прочитать эту статью , в частности, раздел 2.2. Короткая история: формат ELF поддерживает то, что вам нужно, и есть несколько инструментов / способов достижения этого.

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

Вы должны использовать -fPIC. Не использовать -fPIC для разделяемых библиотек на некоторых архитектурах - фатальная ошибка. Поскольку ваш код не дает сбоя, я полагаю, что вы работаете на оборудовании x86.

...