我有一个你好世界的节目.
@H_403_4@我在链接阶段在程序的构建中添加-lmicroxml,以便链接到库libmicroxml.so @H_403_4@当我启动我的程序,我得到一个细分错误.分段故障与libmicroxml.so的负载有关.这里之后我的helleo世界程序的执行执行:
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- printf("hello world! \n");
- return 0;
- }
@H_403_4@在libmicroxml库的构建中,我发现它们在库的构建中(在链接阶段)使用DSOFLAGS = -Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC. @H_403_4@我从选项中删除了-rpath /usr/lib,所以新的是DSOFLAGS = -Wl,-son,libmicroxml.so.1 -shared -fPIC @H_403_4@然后我重建图书馆,然后我启动了你好世界的程序,并且分割错误消失. @H_403_4@我用mips_gcc-4.6-linaro_uClibc-0.9.33.2构建 @H_403_4@这个问题不是用我的旧gcc mips_gcc-4.3.3 cs_uClibc-0.9.30.1 @H_403_4@可以解释为什么从链接选项中删除-rpath /usr/lib来解决库中加载的segfault?
- 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,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,0) = 0x777b3000
- old_mmap(0x777b3000,1572,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED,3,0) = 0x777b3000
- old_mmap(0x777c3000,1648,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,"\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"...,147456,0) = 0x7778f000
- old_mmap(0x7778f000,76928,0) = 0x7778f000
- old_mmap(0x777b2000,408,0x13000) = 0x777b2000
- close(3) = 0
- munmap(0x777dd000,4096) = 0
- open("/lib/libc.so.0",O_RDONLY) = 3
- fstat(3,st_size=413076,"\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"...,503808,0) = 0x77714000
- old_mmap(0x77714000,405592,0) = 0x77714000
- old_mmap(0x77787000,7572,0x63000) = 0x77787000
- old_mmap(0x77789000,21036,MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,0) = 0x77789000
- close(3) = 0
- munmap(0x777dd000,4096) = 0
- open("/usr/lib/libgcc_s.so.1",st_size=169712,"\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"...,237568,0) = 0x776da000
- old_mmap(0x776da000,169036,0) = 0x776da000
- old_mmap(0x77713000,1776,0x29000) = 0x77713000
- close(3) = 0
- munmap(0x777dd000,4096) = 0
- open("/usr/lib/libc.so.0",st_size=425968,"\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"...,516096,0) = 0x7765c000
- old_mmap(0x7765c000,418924,0) = 0x7765c000
- old_mmap(0x776d2000,8176,0x66000) = 0x776d2000
- old_mmap(0x776d4000,21784,0) = 0x776d4000
- close(3) = 0
- munmap(0x777dd000,...}) = 0
- close(3) = 0
- stat("/lib/ld-uClibc.so.0",st_size=28976,...}) = 0
- open("/lib/libc.so.0",...}) = 0
- close(3) = 0
- old_mmap(NULL,0) = 0x777dd000
- set_thread_area(0x777e4440) = 0
- mprotect(0x77787000,PROT_READ) = 0
- mprotect(0x776d2000,PROT_READ) = 0
- mprotect(0x777da000,PROT_READ) = 0
- --- SIGSEGV (Segmentation fault) @ 0 (0) ---
- +++ killed by SIGSEGV +++
- Segmentation fault
解决方法
从跟踪中,您的程序似乎加载了相同模块的不同二进制文件,这些模块应该是相同的版本:
@H_403_4@/lib/libc.so.0(size:413076 bytes)vs. /usr/lib/libc.so.0(size:425968 bytes).
@H_403_4@/lib/libgcc_s.so.1(size:78232 bytes)vs. /usr/lib/libgcc_s.so.1(size:169712 bytes).
@H_403_4@这可能是因为当您在模块链接中使用-rpath时,强制它从/usr/lib加载模块,但是您的程序使用的默认搜索路径是/ lib(根据http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html的dlopen文档).
@H_403_4@所以:你的程序加载/usr/lib/libmicroxml.so.1(注意,它找不到/lib/libmicroxml.so.1,虽然它首先搜索这个路径).然后它继续从/ lib加载它需要的模块(libgcc和libc),最后,因为libmicroxml需要从/usr/lib加载这些模块(因为提供了构建参数),所以它们也从这个路径加载.
@H_403_4@一旦将两个具有相同名称和接口的不同库(因为它们具有相同的版本)加载在一起,就不能知道调用哪个函数的版本,这可能会导致不一致.
@H_403_4@我想你可以按照你所做的方式来解决这个问题,或者通过在程序的构建中添加相同的-rpath参数.
@H_403_4@删除-rpath解决这个问题的原因是,当加载libmicroxml所需的模块时,加载程序首先搜索/ lib作为默认的第一个目录(因为没有指定其他目录),并且由于该文件夹中的模块已经加载,所以没有冲突.
@H_403_4@在任何情况下,在同一驱动器上具有相同版本的同一模块的两个不同二进制文件的情况是非常不健康的.
@H_403_4@对于GCC版本,我只能假设正确的libc或libgcc与以前的GCC一起使用(甚至安装了),并被更新的GCC替代,但是我找不到文档来支持.