加入" -rpath,/ usr / lib目录"在共享库的编译选项将导致段错误 [英] adding "-rpath,/usr/lib" in the build options of a shared library cause a segfault
问题描述
我有一个Hello World程序。
I have a hello world program.
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("hello world! \n");
return 0;
}
我以链接到库 libmicroxml.so $ C添加
-lmicroxml
在联动阶段的程序的构建$ C>
I add -lmicroxml
in the build of the program in the linkage phase in order to link to the library libmicroxml.so
当我启动我的节目,我得到一个分段错误。分割故障libmicroxml.so 相关的负荷。我helleo世界程序执行后strace的位置:
when I launch my program I get a segmentation fault. the segmentation fault is related to the load of the libmicroxml.so
. here after the strace of my helleo world program execution:
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库的构建,我发现他们使用 DSOFLAGS =轮候册,-soname,libmicroxml.so.1,-rpath,/ usr / lib目录-shared -fPIC
在库的构建(在联动阶段)。
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).
我删除了 -rpath,/ usr / lib目录
从选项使新的 DSOFLAGS =轮候册,-soname,libmicroxml。 so.1 -shared -fPIC
I removed the -rpath,/usr/lib
from the options so the new one is DSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC
然后我重建库,然后我公司推出的Hello World程序和分段错误的消失
And then I rebuild the library and then I launched the hello world program and the segmentation fault disappear.
我米,建筑 mips_gcc-4.6-linaro_uClibc-0.9.33.2
这问题不是我的旧的gcc转载 mips_gcc-4.3.3 + cs_uClibc-0.9.30.1
This issue is not reproduced with my old gcc mips_gcc-4.3.3+cs_uClibc-0.9.30.1
任何一个可以解释为什么删除 -rpath,/ usr / lib目录
从链接选项修复库的负荷段错误?
Can any one explain why removing the -rpath,/usr/lib
from the linkage options fix the segfault in the load of the library?
推荐答案
从跟踪看来你的程序加载相同的模块,这应该是同一版本的不同的二进制文件:
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
(大小:413076字节)。 VS / usr / lib目录/ libc.so.0
(大小:425968字节)。
/lib/libc.so.0
(size: 413076 bytes) vs. /usr/lib/libc.so.0
(size: 425968 bytes).
/lib/libgcc_s.so.1
(大小:78232字节)。 VS / usr / lib目录/ libgcc_s.so.1
(大小:169712字节)。
/lib/libgcc_s.so.1
(size: 78232 bytes) vs. /usr/lib/libgcc_s.so.1
(size: 169712 bytes).
这可能是因为,当你在模块链接使用 -rpath
,你强迫它从 / usr / lib目录<加载模块/ code>,但你的程序使用
/ lib目录
(据在<一个文件的dlopen文档默认搜索路径href=\"http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html\">http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html).
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).
所以:你的程序加载 /usr/lib/libmicroxml.so.1
(注意,它找不到 / lib中/ libmicroxml。 so.1
,虽然它搜索这个路径优先)。然后继续加载它要求( libgcc中
和的libc
)从 / lib目录<模块/ code>,最后,因为
libmicroxml
要求从 / usr / lib目录
(因为提供构建参数),他们还装载从这个路径。
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). 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.
一旦你有相同的名称和接口两个不同的库(因为它们是同一版本)一起加载,你可以不知道哪个版本的哪个函数被调用,这可能会导致不一致。
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.
我想你可以解决这个问题不是你做的方式,或通过添加相同 -rpath
参数程序的版本。
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
解决这个问题是加载在 libmicroxml
所需的模块,加载程序时,首先搜索 / lib目录
作为默认的第一个目录(因为没有指定其他目录),由于此文件夹中的模块已加载有没有发生冲突。
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.
在任何情况下,这种情况具有用于与相同的驱动器上相同的版本相同的模块两个不同的二进制的是非常不健康
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.
至于海湾合作委员会的版本,我只能假设,正确的libc或libgcc中使用了(甚至安装)与previous GCC,以及较新的海湾合作委员会取代,但我找不到文件,以支持
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.
这篇关于加入&QUOT; -rpath,/ usr / lib目录&QUOT;在共享库的编译选项将导致段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!