加入" -rpath,/ usr / lib目录"在共享库的编译选项将导致段错误 [英] adding "-rpath,/usr/lib" in the build options of a shared library cause a segfault

查看:638
本文介绍了加入" -rpath,/ usr / lib目录"在共享库的编译选项将导致段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Hello World程序。

I have a hello world program.

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

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

我以链接到库 libmicroxml.so -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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆