在共享库的构build选项中添加“-rpath,/ usr / lib”会导致段错误

我有一个你好世界计划。

#include <stdio.h> #include <stdlib.h> int main() { printf("hello world! \n"); return 0; } 

我在链接阶段的程序-lmicroxml中添加-lmicroxml以链接到库libmicroxml.so

当我启动我的程序时,我得到了一个分段错误。 分段故障与libmicroxml.so的加载有关。 在我的helleo世界计划执行的strace之后:

  strace ./test execve("./test", ["./test"], [/* 11 vars */]) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777de000 stat("/etc/ld.so.cache", 0x7f944760) = -1 ENOENT (No such file or directory) open("/lib/libmicroxml.so.1", O_RDONLY) = -1 ENOENT (No such file or directory) open("/lib/libmicroxml.so.1", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/lib/libmicroxml.so.1", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=4129, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000 read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\4p\0\0\0004"..., 4096) = 4096 old_mmap(NULL, 69632, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x777b3000 old_mmap(0x777b3000, 1572, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x777b3000 old_mmap(0x777c3000, 1648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x777c3000 close(3) = 0 munmap(0x777dd000, 4096) = 0 open("/lib/libgcc_s.so.1", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=78232, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000 read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0006\320\0\0\0004"..., 4096) = 4096 old_mmap(NULL, 147456, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7778f000 old_mmap(0x7778f000, 76928, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x7778f000 old_mmap(0x777b2000, 408, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x13000) = 0x777b2000 close(3) = 0 munmap(0x777dd000, 4096) = 0 open("/lib/libc.so.0", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=413076, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000 read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\253`\0\0\0004"..., 4096) = 4096 old_mmap(NULL, 503808, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77714000 old_mmap(0x77714000, 405592, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x77714000 old_mmap(0x77787000, 7572, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x63000) = 0x77787000 old_mmap(0x77789000, 21036, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77789000 close(3) = 0 munmap(0x777dd000, 4096) = 0 open("/usr/lib/libgcc_s.so.1", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=169712, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000 read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\307\220\0\0\0004"..., 4096) = 4096 old_mmap(NULL, 237568, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x776da000 old_mmap(0x776da000, 169036, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x776da000 old_mmap(0x77713000, 1776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x29000) = 0x77713000 close(3) = 0 munmap(0x777dd000, 4096) = 0 open("/usr/lib/libc.so.0", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=425968, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000 read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\267`\0\0\0004"..., 4096) = 4096 old_mmap(NULL, 516096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7765c000 old_mmap(0x7765c000, 418924, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x7765c000 old_mmap(0x776d2000, 8176, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x66000) = 0x776d2000 old_mmap(0x776d4000, 21784, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x776d4000 close(3) = 0 munmap(0x777dd000, 4096) = 0 open("/lib/libc.so.0", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=413076, ...}) = 0 close(3) = 0 stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=28976, ...}) = 0 open("/lib/libc.so.0", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0755, st_size=413076, ...}) = 0 close(3) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000 set_thread_area(0x777e4440) = 0 mprotect(0x77787000, 4096, PROT_READ) = 0 mprotect(0x776d2000, 4096, PROT_READ) = 0 mprotect(0x777da000, 4096, PROT_READ) = 0 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++ Segmentation fault 

在libmicroxml库的构build中,我发现它们在库的构build中(在链接阶段)使用DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC

我从选项中删除了-rpath,/usr/lib ,所以新的是DSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC

然后我重build图书馆,然后我启动了你好世界程序和分段错误消失

我用mips_gcc-4.6-linaro_uClibc-0.9.33.2

这个问题是不是与我的旧版本gcc mips_gcc-4.3.3+cs_uClibc-0.9.30.1

任何人都可以解释为什么从链接选项中删除-rpath,/usr/lib可以修复库加载中的段错误?

从跟踪看来,你的程序加载了相同模块的不同二进制文件,它们应该是相同的版本:

/lib/libc.so.0 (大小:413076字节) /usr/lib/libc.so.0 (大小:425968字节)。

/lib/libgcc_s.so.1 (大小:78232字节) /usr/lib/libgcc_s.so.1 (大小:169712字节)。

这可能是因为在模块链接中使用-rpath时,强制它从/usr/lib加载模块,但是程序使用的默认搜索路径是/lib (根据http:/的dlopen文档, /tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html )。

所以:你的程序加载/usr/lib/libmicroxml.so.1 (注意它找不到/lib/libmicroxml.so.1 ,尽管它先搜索了这个路径)。 然后继续从/lib加载它需要的模块( libgcclibc ),最后,因为libmicroxml需要从/usr/lib加载这些模块(因为提供了构建参数),所以也从这个路径加载它们。

一旦有两个具有相同名称和接口的不同库(因为它们的版本相同)加载在一起,就无法知道哪个版本的哪个函数被调用,这可能会导致不一致。

我想你可以按照你的方式解决这个问题,或者在程序的构建中加入相同的参数。

删除-rpath解决这个问题的原因是,当加载libmicroxml所需的模块时,加载器首先搜索/lib作为默认的第一个目录(因为没有指定其他目录),并且由于该文件夹中的模块已经加载,所以没有冲突。

在任何情况下,在同一个驱动器上为同一个模块使用两个不同的二进制文件是非常不健康的。

至于GCC版本,我只能假定正确的libc或libgcc被用于(甚至是安装)以前的GCC,并被新的GCC取代,但是我找不到支持这个的文档。

你的DSOFLAGS看起来像这样:

 DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC 

你有没有试过这样的编译?

 gcc -L/usr/lib -Wl,-rpath=/usr/lib -Wall -o test main.c -lmicroxml 

如果你可以这样编译,你可以在Makefile中使用这一行和CC和CFLAGS来编译。 还有其他一些方法可以链接。

良好的信息在这个环节。