尝试使用dlopen加载库时未定义的符号

Luc*_*lon 8 c++ linker compilation shared-libraries dlopen

我正在尝试加载一个共享库(插件)我在Linux ARM平台下使用dlopen提供了(封闭源代码).我正在尝试加载这种方式:

void* handle = dlopen(<library_path>/<library_name>, RTLD_NOW);
Run Code Online (Sandbox Code Playgroud)

结果是此消息失败:

Failed to load <library_path>/<library_name>: undefined symbol: <symbol_name>.
Run Code Online (Sandbox Code Playgroud)

我试图用nm查看库内部,但似乎lib被剥离,找不到符号.我也试过使用readelf -s,事实上,我得到了这个结果:

12663: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND <symbol_name>
Run Code Online (Sandbox Code Playgroud)

通过阅读,我得到readelf -s返回所有符号,包括在它引用的库中定义的那些符号.

这个问题的答案对我来说并不完全清楚:这是一个应该在库中的符号,它不存在,因为它是以错误的方式编译的,或者这是一个我应该在其他地方找到的符号?readelf -d的输出似乎表明我提供了所有需要的共享库.可能这个错误与我正在编译可执行文件的方式中的错误有关,或者这与加载程序无关?

另外,我读到了每列的含义,但这些值非常奇怪.你如何解释这个符号描述?为什么地址为0?为什么键入NOTYPE?

j_k*_*bik 5

未定义的符号:X表示始终应该从一个已加载的库中导出X,但事实并非如此.您应该找到所请求的库符号并链接到它.

您应该知道此消息始终是库的问题的结果,这不是错误.图书馆应该知道如何获得它的所有符号.如果不是,您可以将可执行文件链接到所需的库,因此在加载插件时,已知请求的符号.

此错误可能有更复杂的原因.如果插件和主应用程序都链接到库,那么尝试链接它可能会以未定义的符号结束.如果主应用程序和插件使用不同版本的库(即插件使用较新版本),则可能会发生这种情况.然后在加载插件时,旧版本已加载,因此加载器假定一切正常,但较新版本可能包含新符号.如果插件使用它们,您将得到未定义的符号错误.


Ale*_*lov 5

如果应用程序的链接命令中静态库的顺序错误,也会出现此问题。Unix ld 链接器要求在引用该函数的库之后指定实现该函数的库。

当我尝试从自定义位置获取 libz 库(不是来自主机的标准 libz,而是从源代码手动构建)来构建 libtesseract 共享库时,我遇到了这个麻烦。我在下面举了一个例子:

错误的链接顺序(-lz 在 -llept 之前):

$ g++  -fPIC -DPIC -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbeginS.o  -Wl,--whole-archive ....(some libs) -Wl,--no-whole-archive  -L/home/build/jenkins/workspace/tesseract/zlib/bin/lib -L/home/build/jenkins/workspace/tesseract/leptonica/bin/lib -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/x86_64-linux-gnu -lz -llept -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-linux-gnu/5/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o  -g -O2   -Wl,-soname -Wl,libtesseract.so.4 -o .libs/libtesseract.so.4.0.1
Run Code Online (Sandbox Code Playgroud)

用“nm -D”检查:

$ nm -D .libs/libtesseract.so.4.0.1 | grep deflateInit
                 U deflateInit_
Run Code Online (Sandbox Code Playgroud)

使用“dlopen”检查:

Cannot load ./tesseract/src/api/.libs/libtesseract.so.4.0.1 (./tesseract/src/api/.libs/libtesseract.so.4.0.1: undefined symbol: deflateInit_)
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为链接器正在循环中处理命令行中传递的所有静态库,并跳过任何前面的静态库未使用的库。由于在检查 libz.a 时,链接器发现所有已检查的库都没有使用 libz.a 中的任何函数,因此链接器只是“忘记”libz.a。

正确的链接顺序(-lz 在 -llept 之后):

$ g++  -fPIC -DPIC -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/crtbeginS.o  -Wl,--whole-archive ....(some libs) -Wl,--no-whole-archive  -L/home/build/jenkins/workspace/tesseract/zlib/bin/lib -L/home/build/jenkins/workspace/tesseract/leptonica/bin/lib -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/x86_64-linux-gnu  -llept -lz -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-linux-gnu/5/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o  -g -O2   -Wl,-soname -Wl,libtesseract.so.4 -o .libs/libtesseract.so.4.0.1
Run Code Online (Sandbox Code Playgroud)

用“nm -D”检查:

$ nm -D .libs/libtesseract.so.4.0.1 | grep deflateInit
000000000041fb5b T deflateInit_
000000000041fba3 T deflateInit2_
Run Code Online (Sandbox Code Playgroud)

“dlopen”这次没有显示这个错误。