символ не найден (ldd), но он есть (nm)

Мое приложение жалуется на символ, который не может найти:

fatal: relocation error: file /foo/libxslt4c.so.113: symbol __1cDstdEcout_: referenced symbol not found (bar.c:1330)

И ldd говорит то же самое:

ldd -d /bar/libxmllib.so
        libc.so.1 =>     /lib/sparcv9/libc.so.1
        [...]
        libxml4c.so.58 =>        /foo/libxml4c.so.58
        libxslt4c.so.113 =>      /foo/libxslt4c.so.113
        [...]
        /platform/SUNW,SPARC-Enterprise/lib/sparcv9/libc_psr.so.1
        /lib/sparcv9/../libm/sparcv9/libm_hwcap1.so.2
        symbol not found: __1cDstdEcout_                (/foo/libxslt4c.so.113)
        symbol not found: __1cDstdEcerr_                (/foo/libxslt4c.so.113)

Однако символ есть - вот что говорит nm:

nm /foo/libxslt4c.so.113.0 | grep __1cDstdEcerr_
[10915] |                   0|                   0|OBJT |GLOB |0    |UNDEF  |__1cDstdEcerr_

Но как видите: Shndx=UNDEF. Что это значит? Я думал, что если что-то не определено, то его вообще нет. Но почему-то он есть, хотя мое приложение не может его найти.

Система: Solaris 10 / UltraSPARC Мое приложение и все библиотеки 64-битные, /foo находится в LD_LIBRARY_PATH_64 (/bar — нет).

edit: Между тем я знаю, что UNDEF похож на «необходимо разрешить в другой библиотеке». И я также нашел библиотеку, которая действительно имеет символ _1cDstdEcerr — это libCstd.so, которая находится в /usr/lib. Или, если быть более точным (поскольку нам нужен 64-битный вариант) /usr/lib/64. Таким образом, он находится в одном из системных путей поиска библиотек по умолчанию, которые показаны crle. Теперь вопрос: как не разрешить символ, если библиотека, содержащая его, находится в пути поиска системы?


person thorstenhirsch    schedule 18.02.2014    source источник
comment
Система не ищет символы во всех возможных библиотеках в пути к библиотеке, а только в тех, на которые ссылается программа или общий объект, как указано в elfdump -d /bar/libxmllib.so.   -  person alanc    schedule 19.02.2014


Ответы (1)


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

Если у тебя есть

LDFLAGS += -lCstd

в вашем Makefile, тогда он должен был быть передан, и компоновщик поступил бы правильно (при условии, что вы используете стандартные правила компиляции, которые добавляют $(LDFLAGS) к вызову вашего компилятора и компоновщика).

person James McPherson    schedule 18.02.2014
comment
Спасибо, но мое приложение на самом деле является проприетарным программным обеспечением от IBM. Конечно, я не уверен в их LDFLAGS, но я почти уверен, что они построили программу правильно; проблема скорее в моей среде Solaris. - person thorstenhirsch; 19.02.2014
comment
Проблема почти наверняка не в вашей среде Solaris, а в способе создания приложения. Вы можете исследовать запутанные внутренности приложения, используя elfdump -d /path/to/application. Запись RUNPATH или RPATH поможет вам выяснить, где он ищет libCstd.so. Иногда (я видел это с плохо упакованным программным обеспечением GNU на Solaris) вы можете обнаружить, что путь выполнения — тарабарщина. К счастью... для решения подобных проблем можно использовать утилиту elfedit. Один из специалистов по компоновке Solaris написал очень полезный обширный пост об этом инструменте: goo.gl/RgxIy8. - person James McPherson; 19.02.2014
comment
Вы совершенно правы. IBM решила проблему и прислала нам новую библиотеку. Большое спасибо, Джеймс! - person thorstenhirsch; 03.03.2014