Linux lib undefined symbol

How to fix symbol lookup error: undefined symbol errors in a cluster environment

I’m working on some python code that extracts some image data from an ECW file using GDAL (http://www.gdal.org/) and its python bindings. GDAL was built from source to have ECW support.

The program is run on a cluster server that I ssh into. I have tested the program through the ssh terminal and it runs fine. However, I would now like to submit a job to the cluster using qsub, but it reports the following:

I did a bit more digging and tried using LD_DEBUG=symbols to try and work out where the difference was, but that’s about as far as my knowledge/understanding has got me.

For reference, here’s what happens with LD_DEBUG=symbols and running the code in the ssh terminal (piping through grep H5Eset_auto2 to reduce some of the output):

Symbol debug output for code running in ssh terminal:

Symbol debug output for code submitted using qsub:

I guess I’m not sure why it seems to stop looking in libgdal.so.1 when submitted using qsub, when it continues to look when just run in the terminal. I also note that the qsub job is able to correctly locate libhdf5.so.7 (which is where it should find H5Eset_auto2 ) as it can find a different symbol, H5Eprint :

Any pointers on this would be incredibly useful at this stage (I hope that’s enough information — I’m more than happy to provide more information, I’m just not sure what else might be useful at this stage).

It seems that the contents of /usr/bin are different for jobs submitted using qsub (specifically libtool is missing). This is being investigated.

Источник

undefined symbol статической библиотеки

Всем привет. У меня возникла следующая проблема:

есть библиотека mimetic с открытым кодом, собрал её как статическую libmimetic.a.

использую её в своем классе, который тоже собирается как статическая библиотека libparser.a.

этот класс является членом класса-обёртки для создания своего плагина libplugin.so.

А попытка загрузить плагин в основном приложении при помощи QPluginLoader заканчивается ошибкой «undefined symbol: _ZN7mimetic18ContentDisposition5labelE».

При помощи утилиты nm я поискал этот символ в созданных выходных файлах:

0000000000000000 t _GLOBAL__sub_I__ZN7mimetic18ContentDisposition5labelE

0000000000000000 R _ZN7mimetic18ContentDisposition5labelE

Не понимаю почему этот символ остается с пометкой undefined и как это изменить, если, конечно, это решит мою проблему. Буду рад любым конструктивным советам.

Проект пишу в Qt, компилятор GCC

Статические библиотеки чувствительны к порядку при линковке. Как линкуете? Ну и не страдайте фигнёй, используйте нормальные сошки.

Где-то в описании своего проекта надо задать зависимость библиотеки parser от mimetic так чтобы эта зависимость пробрасывалась системой сборки до plugin . Как уже написали порядок линковки важен, но система сборки должна сама это разруливать.

Статические библиотеки чувствительны к порядку при линковке. Как линкуете?

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

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

the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.

Вроде как, объединение в группы это исправляет или смена на линкер, которому порядок не важен.

У ТСа, с виду, при линковки libplugin.so не указано -lmimetic . Но без подробностей как идет сборка трудно сказать.

Этот пример не о том, объектники не совсем библиотеки, если речь про библиотеки, то их и надо собирать как библиотеки и там порядок не важен и даже невозможен, так как взаимная зависимость библиотек — везде и всюду.

Читайте также:  Горячие клавиши для mac os скриншот

Забавно, что в gcc любой порядок прокатывал до версии 8.X.X. При переходе на 9-ю версию начались рвать подводные камни, пришлось местами менять порядок либ.

У ТСа, с виду, при линковки libplugin.so не указано -lmimetic.

Для статической mimetic.a это ведь ничего не даст.

Именно так. Если линкуются две библиотеки и одна использует символы из другой, то они слинкуются только в одном порядке.

undefined symbol: _ZN7mimetic18ContentDisposition5labelE

Не хотелось расписывать, но таки придётся. Если библиотека содержит несколько объектников, то символы будут последовательно выбраны и прилинкованы одним проходом просмотра библиотек. Но если символы в одном из объектников в каждой библиотеке, то все требуемые объектники будут заюзаны, а символы будут рекурсивно слинкованы, что ТСу и надо.

Молодец! Только вот это распарсь:

И зачем же ты врёшь?

Не думаю, что в GCC 8 что-то меняли, это не какое-то новое поведение. Обычно разница в поведении объясняется различиями в параметрах по умолчанию в разных дистрибутивах, так что некоторые просто не сталкиваются пока умолчания не поменяют.

Я дал полное объяснение с примером, в чём проблема у ТСа, беретё, выполняете и не врёте.

Описание того как линкер якобы работает вообще не понял (хотя я знаю как). Так что просто переделал пример, чтобы это было видно, а не скрывалось зависимостями от m.c к обоим объектным файлам в библиотеках:

а не скрывалось зависимостями от m.c к обоим объектным файлам в библиотеках:

А это ведь и надо ТСу сделать. У него нет зависимости от символа в основном модуле, но есть в плагине, но загружается только плагин без подгрузки нужного символа. Отсюда и получается, что либо внести символ в объектник плагина либо сделать экпортируемым символом из основного бинаря, чтобы оно его захотело, каким угодно пустым хаком, ну там адрес получить и прочим stub-ом.

А, так это был такой своеобразный вариант решения. Я не понял.

Раз плагин зависит от этой библиотеки, то ему её и тащить.

Второй вариант диковато смотрится. Приложение не должно выборочно включать те символы, которые используются в плагинах. Тогда уже логично всю библиотеку затащить через —whole-archive , если она большинству плагинов необходима.

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

Много много лет компилил на всем, на чем может компилиться, от слакварей с центозами до дебианов, от фри всех версий до солярки, синологи, какие только можно роутеры. И тут мне вдруг присылают, что моя программа не компилится на убунте 20-й… Пришлось поменять местами $(LIBS) $(OBJS), которые шли в таком порядке больше 20 лет… Меня это удивило немного, но не сильно нарпягло. В убунте стоит gcc 9.x.x

посмотри как люди подключают статитически стороние библиотеки в своих приложениях и сделай так же.

открываешь любой проект на гитхабе на qt и смотришь как они собирают и экспортируют символы

я подозреваю, что процессом линковки управляет больше Qt, чем я, т.к. я только перечисляю в .pro-файле зависимые библиотеки, иногда указывая пути в которых надо их искать, при помощи переменной qmake LIBS.

Но не обращая внимание на это, у меня остается непонимание почему линковщик не пытается определить этот символ.

в файле contentdescription.h содержится объявление переменной:

которое добавляется в parser.cpp при подключении этого файла при помощи #include.

В одном из методов моего класса она используется следующим образом:

В моем понимании, если бы я не использовал в своем коде mimetic::ContentDescription::label, то линковщик мог бы оставить символ этой переменной неразрешенным, а раз я эту переменную использую, то он должен найти определение, либо выдать ошибку, что ему это не удалось сделать, но видимо у меня проблемы с пониманием процесса сборки.

Вы оказались правы. После указания в pro-файл проекта, создающего плагин, библиотеки -lmimetic всё получилось. Но пришлось почему-то указывать не обычным способом:

У Вас, возможно, проблемы в настройках проектов. В идеале должно быть так: в билд системе указывается что plugin зависит от parser , а parser зависит от mimetic . Для сборки plugin билд система прописывает где искать хиадеры обоих библиотек, а для линковки какие либы линковать и в каком порядке. Если все это делать руками, то можно упороться, особенно при развесистых зависимостях.

Читайте также:  Windows 10 destroy spy rutracker

Источник

Linux shared library that uses a shared library undefined symbol

two shared libraries liba.so and libb.so. liba.so uses libb.so. All c files are compiled with -fPIC. Linking uses -shared. When we call dlopen on liba.so it cannot find symbols in libb.so. we get the «undefined symbol» error. We can dlopen libb.so with no errors. We know that liba is finding libb because we don’t get a file not found error. We get a file not found error when we delete libb.so. We tried -lutil and no luck.

oh yeah. gcc 4.1.2

update: We use rpath when linking liba so it can find libb.

ldd liba.so returns:

is it significat that there is no .# at the end of libb.

2 Answers 2

You can easily check where libb.so is expected to be with ldd command:

If it’s not found , libb.so ‘s path should be added to /etc/ld.so.conf or shell variable LD_LIBRARY_PATH .

Another way is setting rpath in the liba.so itself — it’s basically hardcoding its path so when the binary is started the dynamic linker would know where to search for the shared libraries.

If rpath is not set it will first search in LD_LIBRARY_PATH , then the paths mentioned in /etc/ld.so.conf (or /etc/ld.so.conf.d/). After adding to ls.so.conf don’t forget to execute /sbin/ldconfig

Dynamic linker searches the dependent shared libraries by their soname (if it’s set) — if soname is not set (with -Wl,-soname,libb.so.1 for example), it will be searched by library’s name.

Example: libb.so.1.0 is your actual library, having soname — libb.so.1 . You would normally have the following files structure:

where libb.so and libb.so.1 are symlinks.

You usually link to libb.so , when building some application or other library, depending on libb.so .

When the application is started (or dlopen is executed — your case) — the dynamic linker will search for file with name libb.so.1 — the soname of dependent library, if the soname is set, not libb.so .

That’s why you need that symlink libb.so.1 , pointing to the actual library.

If you use ld.so.conf and ldconfig , it will create the symlink with soname ‘s name, pointing to the library file, if this symlink is missing.

You can see ld-linux man page for more useful info.

If the library is found but some of the symbols are missing, try building libb.so with -Wl,—no-undefined option

It should give you an error if you missed to define some symbol.

Источник

GLib undefined symbol bug in Debian

Dec 4, 2018 · 2 min read

After a regular software upgrade, my Debian sid refused to start lightdm service. Viewing the log by running journalctl -xe , I saw something like this:

Following the discussion in that thread, I started inspecting some GLib files:

It turns out that my /lib/x86_64-linux-gnu/libglib-2.0.so.0 was a symlink to /lib/x86_64-linux-gnu/libglib-2.0.so.0.4800.1 , while my /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0 was a symlink to /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.5800.1 . One of them must belong to a wrong version.

Which GLib version do I have?

And the result is libglib2.0–0/unstable,now 2.58.1–2 amd64 [installed] .

SOLUTION

It is now c l ear that when upgrading the libglib2.0–0 package, Debian failed to clean the old one (2.48) completely. As /lib comes before /usr/lib , it is causing this problem. I tried to do dpkg-reconfigure libglib2.0–0 , but it didn’t help. So in the end I removed the files under /lib:

CAUSE

Now my lightdm works as expected. How did this happen?

In the bug report, Michael Biebl suspected that the files of an older version of GLib could have been introduced by a third party package. I do not think so. Let’s compare two file lists:

File list of package libglib2.0–0 in stretch of architecture amd64

File list of package libglib2.0–0 in sid of architecture amd64

The symlink libglib-2.0.so.0 and the file it links to, used to sit under /lib/x86_64-linux-gnu/ in stretch, but now under /usr/lib/x86_64-linux-gnu/ in sid. This change was introduced in 2.56.0–5. The installation script failed to clean the old ones.

Источник

Запускаю приложение — выдает undefined symbol

Добрый день, товарищи. Ситуация такая: есть сервер, на котором благополучно работает одна тулза некогда написанная на qt. Так вот. Появилась необходимость перенести все на новый сервер.
Все перенеслось, однако теперь на новом серве эта тулза не запускается и выдает :

Читайте также:  Оптимальная версия mac os для macbook pro 2010

undefined symbol _ZN9QListData11detach_growEPii

На старом серве стоит Debian Lenny, на новом и собственно у меня Debian Stable.
Чем вообще может быть вызвана данная ошибка, и что за этакий «символ»?

Я бы проверил какие версии Qtшных so’шек там и там

ты серьёзно это?

Пересобрать её не пробовал?

Может тулза не его, а исходники хз где.

ты всегда через через 5 слов читаешь?

Также не помешает полная переустановка всех qt’шных пакетов.

ССЗБ. ЗЫ как крайний вариант, собрать все нужные .so со старой тачки, перекинуть в отдельную папку на новом серве и юзать LD_LIBRARY_PATH.

Не думаю что встанет без проблем.

Надеюсь всё будет так: ты распакуешь руками пакетик в директорию с исполняемым файлом. Файло вначале посмотрит нужные soшки в текущей директории, возрадуется и перестанет материться. Или можно пакеты распаковать куда-нибудь и развлекаться с export LD_LIBRARY_PATH или как его там.

Собственно, думаю проблема действительно в версиях. Ещё такая штука, есть некий deb пакет, я так понимаю как раз с нужными версиями so’шек. Но вопрос: если собирали его в lenny, станет он без проблем на stable?

З.Ы. Тулза не моя, исходников х3 где.

Можно ручками распаковать содержимое в отдельную папочку (в /opt/, например, или в /usr/local/). Потом пути прописать правильно и все.

А если я их в отдельную папку, которую потом запихку в lib, так не покатит?

А если я их в отдельную папку, которую потом запихку в lib, так не покатит?

Нет так делать не стоит.

Только так и сработает. Искать либы в директории с исполняемым файлом умеет только винда.

Хм, а что мешает прописать -L. в ключах gcc?

Хм, а что мешает прописать -L. в ключах gcc?

Казалось бы, причём тут это

Не покатило. Распаковал деб пакет. И скинул папку из пакета в /usr/lib/

Я же писал ранее, что скидывать надо либо в /opt/’имя программы’/, либо в /usr/local/lib/ и писать скрипт для запуска программы, который будет устанавливать переменную LD_LIBRARY_PATH, добавляя в начало этот путь.

С LD_LIBRARY_PATH можно «скидывать» куда угодно.

Конечно можно. Главное не потерять потом и с системными файлами не спутать.

Спасибо. Буду рыть что такое LD_LIBRARY_PATH, и с чем его едят

Всем спасибо. Создал RunMapGetter.sh

Остался ещё один косяк. У проги есть конфиговский файл. В нем указан путь к папке с которой нужно работать тулзе. Так вот при запуске через

Относительными путями в программе. Если исполняемый файл был в /usr/bin, а переехал в /opt/progname/bin, и путь к конфигу зашит как ../../etc/prog.conf, то конфиг надо перенести в /opt/progname/etc/

Конфиг всегда лежил там, где и исполняемый файл. Там же он находится и сейчас.

Чем вообще может быть вызвана данная ошибка

Несовпадением версии Qt используемой для сборки и для запуска.

Внутренняя функция реализации шаблона QList. Ссылка на нее затянулась из заголовков, т.к. это шаблон (если бы был обычный класс, все обращения к деталям реализации остались бы в пределах Qt)

лучше проверить где действительно должен быть конфиг:

MapGetter.sh присутствует в /home/mobitee/mapgettool

strace -xf -eopen -o out.log RunMapGetter.sh

strace -xf -eopen -o out.log ./RunMapGetter.sh При условии что RunMapGetter.sh в текушей директрии.

если strace скажет, что программа ищет конфигурацию только по тому пути (i:\Project\MapGetter\files\), то можно попробовать такую штуку (допустим файл конфига называется config.cfg):

даже если так запустить?

Вижу что тут что-то дельное, но сразу объясню, в чем трабл ещё раз. Программа запускается. В конфиге указывается папка, с которой тулза должна работать. Конфиг лежит рядом с тулзой, и папка указана. Как только запускается тулза, она пишет с какой папкой работает. Так вот. Если я запускаю программу на старом сервере, все ок, пишет что работает с той папкой, которая в конфиге. А при запуске на новом сервере через .sh пишет что будет работать с папкой, ну совсем не той, что в конфигах, и путь к папке этой виндосовский. Предполагаю, что тулза писалась в винде, и путь там по дефоулту.

Что можете сейчас посоветовать?

strace и sed. Тулза конфиг похоже не находит, а где она его ищет скажет strace. Как отличаются пути до тулзы на старом и новом сервере?

Источник

Оцените статью