简体   繁体   English

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

[英]adding “-rpath,/usr/lib” in the build options of a shared library cause a segfault

I have a hello world program. 我有一个你好的世界计划。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("hello world! \n");
    return 0;
}

I add -lmicroxml in the build of the program in the linkage phase in order to link to the library libmicroxml.so 我在链接阶段的程序构建中添加了-lmicroxml ,以便链接到库libmicroxml.so

when I launch my program I get a segmentation fault. 当我启动程序时,我遇到了分段错误。 the segmentation fault is related to the load of the libmicroxml.so . 分段错误与libmicroxml.so的负载有关。 here after the strace of my helleo world program execution: 在我的helleo世界程序执行之后:

 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

In the build of the libmicroxml library I found they use DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC in the build of the library (in the linkage phase). 在libmicroxml库的构建中,我发现它们在库的构建中使用DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC (在链接阶段)。

I removed the -rpath,/usr/lib from the options so the new one is DSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC 我从选项中删除了-rpath,/usr/lib ,所以新的是DSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC

And then I rebuild the library and then I launched the hello world program and the segmentation fault disappear . 然后我重建了库,然后我启动了hello world程序,分段错误消失了

I m building with mips_gcc-4.6-linaro_uClibc-0.9.33.2 我用mips_gcc-4.6-linaro_uClibc-0.9.33.2

This issue is not reproduced with my old gcc mips_gcc-4.3.3+cs_uClibc-0.9.30.1 我的旧gcc mips_gcc-4.3.3+cs_uClibc-0.9.30.1不再复制此问题

Can any one explain why removing the -rpath,/usr/lib from the linkage options fix the segfault in the load of the library? 任何人都可以解释为什么从链接选项中删除-rpath,/usr/lib修复库中的段错误吗?

From the trace it seems your program loads different binaries of the same modules, which are supposed to be of the same version: 从跟踪看来,您的程序似乎加载了相同模块的不同二进制文件,它们应该是相同的版本:

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

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

This probably happens because when you use the -rpath in the module link, you force it to load the modules from /usr/lib , but the default search path which your program use is /lib (According to the dlopen documentation at http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html ). 这可能是因为当您在模块链接中使用-rpath时,强制它从/usr/lib加载模块,但程序使用的默认搜索路径是/lib (根据http:/的dlopen文档) /tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html )。

So: Your program loads /usr/lib/libmicroxml.so.1 (note that it couldn't find /lib/libmicroxml.so.1 , although it searched for this path first). 所以:你的程序加载/usr/lib/libmicroxml.so.1 (注意它找不到/lib/libmicroxml.so.1 ,尽管它首先搜索了这个路径)。 Then it continues to load the modules it requires ( libgcc and libc ) from /lib , and finally, because libmicroxml requires loading these modules from /usr/lib (because of the build arguments supplied), they are also loaded from this path. 然后它继续从/lib加载它需要的模块( libgcclibc ),最后,因为libmicroxml需要从/usr/lib加载这些模块(因为提供了构建参数),所以它们也从这个路径加载。

Once you have two different libraries with the same name and interface (because they're of the same version) loaded together, you can't know which version of which function is called, and this can cause inconsistencies. 一旦你有两个不同的库具有相同的名称和接口(因为它们是相同的版本)加载在一起,你不知道哪个版本的函数被调用,这可能会导致不一致。

I guess you can solve this either the way you did, or by adding the same -rpath argument to the build of your program. 我想你可以通过你的方式解决这个问题,或者通过在程序的构建中添加相同的-rpath参数来解决这个问题。

The reason removing -rpath solves this issue is that when loading the required modules for libmicroxml , the loader first searches /lib as the default first directory (since no other directory was specified), and since the modules in this folder are already loaded there's no conflict. 删除-rpath解决这个问题的原因是当加载libmicroxml所需的模块时,加载器首先搜索/lib作为默认的第一个目录(因为没有指定其他目录),并且由于此文件夹中的模块已经加载,所以没有冲突。

In any case, this situation of having two different binaries for the same module with the same version on the same drive is very unhealthy. 在任何情况下,在同一驱动器上具有相同版本的相同模块具有两个不同二进制文件的情况是非常不健康的。

As for the GCC version, I can only assume that the correct libc or libgcc were used (or even installed) with the previous GCC, and replaced by the newer GCC, but I could not find documentation to support that. 至于GCC版本,我只能假设正确的libc或libgcc与之前的GCC一起使用(或者甚至安装),并被更新的GCC取代,但我找不到支持它的文档。

Your DSOFLAGS looks like this: 您的DSOFLAGS如下所示:

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

Did you try compiling like this? 你尝试过编译吗?

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

You can then use this line and CC and CFLAGS in a Makefile to make compiling simple, if you're able to compile it this way. 然后,您可以在Makefile中使用此行和CC和CFLAGS来简化编译,如果您能够以这种方式编译它。 There a couple of other ways to link, as well. 还有其他几种链接方式。

Good information at this link. 这个链接的好信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM