Проблема с получением компоновщика GNU (ld) для экспорта символа - PullRequest
7 голосов
/ 13 сентября 2011

Я использую некоторые инструменты GNU, например, компилятор GNU C ++ (g ++) и компоновщик GNU (ld) для создания файла общей библиотеки (.so), а также двоичного исполняемого файла.

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

-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt

, где файл ${top_srcdir}/dynamic_symbol_table.txt содержитследующее содержимое:

{
  extern "C++"
  {
    "ToolboxManager::registerToolbox*";
  };
};

Обратите внимание на использование звездочки (*) в файле, чтобы заставить компоновщик экспортировать все символы, начинающиеся с ToolboxManager::registerToolbox.

Когда я запускаюУтилита GNU nm (nm -C -g ./a.out) в результирующем двоичном исполняемом файле отображает следующую информацию о вышеупомянутом методе класса:

08053da0 T ToolboxManager::registerToolbox  
           (  
            std::string&,  
            std::string&,  
            std::map  
            <  
             std::string,  
             Factory_DSPB_Base*,  
             std::less  
             <  
              std::string  
             >,  
             std::allocator  
             <  
              std::pair  
              <  
               std::string const,  
               Factory_DSPB_Base*  
              >  
             >  
            >&  
           )

или, если утилита nm вызывается, как указано выше, но на этот разбез использования ключа командной строки -C;

08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

Пока все выглядит нормально.«Т» перед определением метода класса ToolboxManager::registerToolbox означает, что метод находится в разделе «Текст / код» файла.

Аналогично, если я запускаю утилиту nm (nm -C -g ./toolbox.so) в файле общей библиотеки он отображает следующую информацию о том же вышеупомянутом методе класса:

U ToolboxManager::registerToolbox
  (
   std::string&,
   std::string&,
   std::map
   <
    std::string,
    Factory_DSPB_Base*,
    std::less
    <
     std::string
    >,
    std::allocator
    <
     std::pair
     <
      std::string const,
      Factory_DSPB_Base*
     >
    >
   >&
  )

Это также выглядит хорошо.«U» перед определением метода класса ToolboxManager::registerToolbox означает, что метод не определен в файле общей библиотеки.

Однако возникает проблема, когда я запускаю двоичный файл, доступный для выполнения из командной строкии эта проблема приводит к отображению следующего сообщения об ошибке:

./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

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

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

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

Затем я повторно связал исполняемый файл двоичного кода, однако на этот раз я заменил следующую команду компоновщика:

-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt

наthe this;

-Wl,--export-dynamic

Параметр компоновщика --export-dynamic дает указание компоновщику GNU добавить все символы в таблицу динамических символов.

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

Заранее спасибо.

1 Ответ

3 голосов
/ 14 сентября 2011

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

"ToolboxManager::registerToolbox*"

внутри файла ${top_srcdir}/dynamic_symbol_table.txt и затем перекомпоновать бинарный исполняемый файл, тогда он работает. Таким образом, функция dlopen больше не будет работать.

Я не могу не задаться вопросом, было бы правильнее задать этот вопрос в списке рассылки GNU binutils, чем здесь, на этом веб-сайте.

...