2009-04-16 3 views
5

Я создал общую библиотеку (* .so) с использованием файлов объектных кодов * .o (исходный код C) с использованием компилятора RVDS на Windows Host.Как экспортировать символы из общей библиотеки

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

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

Так что мои вопросы: -

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

  2. Как будет работать общая библиотека ?, то есть будут ли адреса, где будут загружаться и выполняться функции, будут предоставлены в библиотеке при создании библиотеки. Как приложение (main()) разрешает адреса, где выполняются функции библиотеки?

  3. Как работает статическая библиотека, то есть как эта спецификация адреса и разрешение происходит в случае статической библиотеки?

Thank you.

ответ

11

Вот как это работает на Linux:

1) Нет, вам не нужно ничего делать. Однако вы можете ограничить экспортирование переменных аргументом командной строки gcc -fvisibility и явно экспортировать экспортируемые записи с атрибутом видимости.

2) Исполняемый файл будет иметь таблицу всех функций, которые он импортирует (это все функции с видимостью по умолчанию). Погрузчик/компоновщик выбирает адрес для загрузки библиотек и заполнения этой таблицы непосредственно перед запуском, вызовы этих функций являются косвенными вызовами. (Обратите внимание, что это относится и к общим объектам)

3) Статическое связывание выполняется по времени соединения (которое после компиляции). Фактические адреса заменяются в сборке, и они являются прямыми вызовами.

Примечание: есть вещь, называемая PIC (позиция независимого кода). AFAIK, это касается ссылок на данные/функции в одном и том же общем объекте, поэтому компоновщику не нужно перезаписывать половину кода библиотеки при загрузке библиотеки, так как код не делает никаких абсолютных ссылок на его собственные данные. Вы можете попытаться поэкспериментировать с ним.

0

Вы знаете что-нибудь о причине аварии?

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

+0

@Jonathan: Я не загружаю общую библиотеку, используя вызовы dlopen(). – goldenmean

+0

ОК - У меня нет идей. Я больше знаком с Unix/Linux; Возможно, я помогу. –

3
  1. Вам не нужно экспортировать символы с gcc, так как он экспортирует все символы по умолчанию; Однако RVDS может или не может делать то же самое. Проверьте свою документацию по компилятору RVDS (попробуйте настроить его для вывода «Relocatable ELF»?)

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

  3. Со статическими библиотеками во время компиляции происходит все разрешение символа, перемещение и назначение адресов загрузки.

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

Если вы создаете статическую библиотеку и разделяемую библиотеку непосредственно из RVDS, одним из вариантов было бы попытаться преобразовать эту статическую библиотеку к общей библиотеке:

gcc -shared -o libfoo.so libfoo.a 

Если это помогает, то RVDS поделился библиотеки линкер (или его конфигурацию), скорее всего, нарушена.

Смежные вопросы