2013-10-11 17 views
10

Tôi có một chương trình thế giới xin chào.thêm "-rpath,/usr/lib" vào tùy chọn xây dựng của thư viện được chia sẻ gây ra sự phân biệt

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

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

tôi thêm -lmicroxml trong việc xây dựng các chương trình trong giai đoạn liên kết để liên kết đến các thư viện libmicroxml.so

khi tôi khởi động chương trình của tôi tôi nhận được một lỗi segmentation. lỗi phân đoạn có liên quan đến tải trọng của libmicroxml.so. ở đây sau khi strace thực hiện chương trình thế giới helleo tôi:

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 

Trong xây dựng các thư viện libmicroxml tôi thấy họ sử dụng DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC trong việc xây dựng các thư viện (trong giai đoạn liên kết).

tôi loại bỏ các -rpath,/usr/lib từ các tùy chọn như vậy mới là DSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC

Và sau đó tôi xây dựng lại thư viện và sau đó tôi đưa ra chương trình thế giới chào và lỗi segmentation biến mất.

tôi đang xây dựng với mips_gcc-4.6-linaro_uClibc-0.9.33.2

vấn đề này không được sao chép với gcc cũ của tôi mips_gcc-4.3.3+cs_uClibc-0.9.30.1

Bất kỳ một thể giải thích tại sao loại bỏ các -rpath,/usr/lib từ các tùy chọn liên kết sửa chữa segfault trong tải của thư viện?

+1

'' 'main' không trả về' int' '' – Kninnug

+0

@Kninnug đây không phải là nguyên nhân của sự cố của tôi. bất kỳ cách nào tôi thêm một trở lại chức năng chính của tôi – MOHAMED

+0

đầu ra của "xác định vị trí libmicroxml.so" trên PC của bạn là gì? – stdcall

Trả lời

11

Từ dấu vết có vẻ như tải chương trình của bạn mã nhị phân khác nhau của các module tương tự, mà có nghĩa vụ phải của cùng một phiên bản:

/lib/libc.so.0 (kích thước: 413.076 byte) vs/usr/lib/libc.so.0 (kích thước: 425.968 byte).

/lib/libgcc_s.so.1 (kích thước: 78232 byte) so với/usr/lib/libgcc_s.so.1 (kích thước: 169712 byte).

này có lẽ xảy ra vì khi bạn sử dụng -rpath trong liên kết mô-đun, bạn buộc nó để tải các module từ /usr/lib, nhưng con đường tìm kiếm mặc định mà sử dụng chương trình của bạn là /lib (Theo tài liệu dlopen tại http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html).

Vì vậy: Chương trình của bạn tải /usr/lib/libmicroxml.so.1 (lưu ý rằng chương trình không thể tìm thấy /lib/libmicroxml.so.1, mặc dù trước tiên nó đã tìm kiếm đường dẫn này). Sau đó, nó tiếp tục tải các mô-đun cần thiết (libgcclibc) từ /lib và cuối cùng, vì libmicroxml yêu cầu tải các mô-đun này từ /usr/lib (vì các đối số xây dựng được cung cấp), chúng cũng được tải từ đường dẫn này.

Khi bạn có hai thư viện khác nhau có cùng tên và giao diện (vì chúng cùng phiên bản) được tải cùng nhau, bạn không thể biết phiên bản nào của hàm nào được gọi và điều này có thể gây ra mâu thuẫn.

Tôi đoán bạn có thể giải quyết vấn đề này theo cách bạn đã làm hoặc bằng cách thêm cùng một đối số -rpath vào việc xây dựng chương trình của bạn.

Lý do loại bỏ -rpath giải quyết vấn đề này là khi tải các module cần thiết cho libmicroxml, bộ nạp đầu tiên tìm kiếm /lib như thư mục đầu tiên mặc định (vì không có thư mục khác đã được chỉ định), và kể từ các module trong thư mục này đã được tải không có xung đột.

Trong mọi trường hợp, tình huống này có hai tệp nhị phân khác nhau cho cùng một mô-đun có cùng phiên bản trên cùng một ổ đĩa là rất không lành mạnh. Đối với phiên bản GCC, tôi chỉ có thể giả định rằng libc hoặc libgcc đúng được sử dụng (hoặc thậm chí được cài đặt) với GCC trước đó, và được thay thế bằng GCC mới hơn, nhưng tôi không thể tìm thấy tài liệu để hỗ trợ điều đó.

1

DSOFLAGS của bạn trông như thế này:

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

Bạn hãy thử biên dịch như thế này?

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

Sau đó, bạn có thể sử dụng dòng này và CC và CFLAGS trong Makefile để biên dịch đơn giản, nếu bạn có thể biên dịch theo cách này. Có một vài cách khác để liên kết, là tốt.

Thông tin tốt tại liên kết this.

Các vấn đề liên quan