2013-10-11 6 views
10

Ich habe ein Hallo Welt-Programm.das Hinzufügen von "-rpath,/usr/lib" in den Build-Optionen einer gemeinsam genutzten Bibliothek verursacht einen segfault

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

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

ich hinzufügen -lmicroxml im Build des Programms in der Verknüpfungsphase, um libmicroxml.so

in die Bibliothek zu verknüpfen, wenn ich mein Programm starte ich einen Segmentation Fault bekommen. Der Segmentierungsfehler bezieht sich auf die Last des libmicroxml.so. hier nach dem Strace meiner helleo Welt Programmausführung:

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 

Im Build der libmicroxml Bibliothek fand ich sie DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC im Build der Bibliothek (in der Verknüpfungsphase) verwenden.

entfernte ich die -rpath,/usr/lib aus den Optionen, so dass die neuen DSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC

wird und dann die Bibliothek, die ich wieder aufbauen und dann startete ich die Welt Programm hallo und die Segmentierungsfehler verschwinden.

Ich baute mit mips_gcc-4.6-linaro_uClibc-0.9.33.2

Dieses Problem mit meinem alten gcc nicht mips_gcc-4.3.3+cs_uClibc-0.9.30.1

die -rpath,/usr/lib aus den Verknüpfungsoptionen Kann man erklären, warum das Entfernen reproduziert die segfault in der Last der Bibliothek beheben?

+1

'' 'main' gibt kein' int' '' – Kninnug

+0

@Kninnug das ist nicht die Ursache meines Problems. Wie auch immer ich eine Rückkehr zu meiner Hauptfunktion hinzugefügt habe – MOHAMED

+0

Was ist die Ausgabe von "locate libmicroxml.so" auf Ihrem PC? – stdcall

Antwort

11

Von der Spur scheint es Ihrem Programm lädt verschiedene Binärdateien von den gleichen Modulen, die angeblich von der gleichen Version sein:

/lib/libc.so.0 (Größe: 413.076 Bytes) vs./usr/lib/libc.so.0 (Größe: 425.968 Bytes).

/lib/libgcc_s.so.1 (Größe: 78232 Byte) vs./usr/lib/libgcc_s.so.1 (Größe: 169712 Byte).

Dies geschieht wahrscheinlich, weil, wenn Sie die -rpath im Modul Link verwenden, können Sie es zwingen, die Module von /usr/lib zu laden, aber der Standard-Suchpfad, die Ihr Programm verwendet wird /lib (gemäß der dlopen Dokumentation bei http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html).

Also: Ihr Programm lädt /usr/lib/libmicroxml.so.1 (beachten Sie, dass es /lib/libmicroxml.so.1 nicht finden konnte, obwohl es zuerst nach diesem Pfad gesucht hat). Dann lädt es weiterhin die benötigten Module (und libc) von /lib, und schließlich, weil libmicroxml das Laden dieser Module von /usr/lib erfordert (wegen der Build-Argumente geliefert), werden sie auch von diesem Pfad geladen.

Sobald Sie zwei verschiedene Bibliotheken mit demselben Namen und derselben Schnittstelle (da sie von derselben Version sind) zusammen geladen haben, können Sie nicht wissen, welche Version welcher Funktion aufgerufen wird, und dies kann zu Inkonsistenzen führen.

Ich denke, Sie können dies entweder so wie Sie getan haben, oder indem Sie das gleiche -rpath Argument zum Build Ihres Programms hinzufügen.

Der Grund -rpath löst dieses Problem zu entfernen, ist, dass, wenn die benötigten Module für libmicroxml Laden, die Lader suchen zuerst /lib als Standard erstes Verzeichnis (da kein anderes Verzeichnis angegeben wurde), und da die Module in diesem Ordner bereits geladen sind Es gibt keinen Konflikt.

In jedem Fall ist diese Situation von zwei verschiedenen Binärdateien für das gleiche Modul mit der gleichen Version auf dem gleichen Laufwerk sehr ungesund.

Wie für die GCC-Version kann ich nur davon ausgehen, dass die richtige libc oder libgcc mit dem vorherigen GCC verwendet (oder sogar installiert) und ersetzt durch den neueren GCC, aber ich konnte keine Dokumentation finden, um das zu unterstützen.

1

sieht Ihr DSOFLAGS wie folgt aus:

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

Sie versuchen Haben wie diese Zusammenstellung?

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

Sie können dann verwenden Sie diese Zeile und CC und CFLAGS in einem Makefile einfach zu machen kompilieren, wenn Sie in der Lage sind, es auf diese Weise zu kompilieren. Es gibt auch ein paar andere Möglichkeiten, um zu verlinken.

Gute Informationen unter this Link.