2010-05-03 29 views
16

Tôi có một chương trình phụ thuộc vào một thư viện được chia sẻ mà nó hy vọng sẽ tìm thấy sâu bên trong một cấu trúc thư mục. Tôi muốn chuyển thư viện được chia sẻ đó ra và vào một nơi tốt hơn. Trên OS X, điều này có thể được thực hiện với install_name_tool. Tôi không thể tìm thấy một tương đương cho Linux.Làm cách nào để thay đổi tên tệp của thư viện được chia sẻ sau khi xây dựng chương trình phụ thuộc vào nó?

Để tham khảo, readelf -d myprogram spits ra đầu ra diễn giải như sau:

Dynamic section at offset 0x1e9ed4 contains 30 entries: 
    Tag  Type       Name/Value 
0x00000001 (NEEDED)      Shared library: [this/is/terrible/library.so] 
0x00000001 (NEEDED)      Shared library: [libGL.so.1] 
0x00000001 (NEEDED)      Shared library: [libGLU.so.1] 
0x00000001 (NEEDED)      Shared library: [libstdc++.so.6] 
(continues in an uninteresting fashion) 

(và theo yêu cầu, ldd myprogram :)

linux-gate.so.1 => (0x0056a000) 
    this/is/terrible/library.so => not found 
    libGL.so.1 => /usr/lib/mesa/libGL.so.1 (0x0017d000) 
    libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00a9c000) 
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00710000) 
    (etc, etc) 

và tôi muốn Errata "này/là/khủng khiếp/library.so "để được" chia sẻ/library.so ". Lưu ý rằng, nếu chương trình còn lại trong vị trí "được xây dựng" của nó, nơi đường dẫn tương đối này/là/terrible/library.so thực sự tồn tại, thì ldd có thể tìm thấy nó, như bạn mong đợi.

Tôi biết về RPATH và nó không phải là những gì tôi đang tìm kiếm, tôi không cần phải thay đổi đường dẫn tìm kiếm trên toàn cầu.

+0

Vì vậy, bạn đang nói rằng đường dẫn "this/is/terrible /" không được đặt là đường đi? Đây có phải là một phần của SONAME của thư viện không? Tôi không nghĩ rằng có install_name trên Linux. –

+0

Vâng, nó sẽ là một phần của SONAME, được giới thiệu bởi trình liên kết dựa trên đường dẫn ban đầu khi nó được liên kết. – ZorbaTHut

+0

bạn cũng có thể đăng đầu ra 'ldd./Yourprogram' không? –

Trả lời

5

HT - điều này có thể hữu ích.

HT là trình chỉnh sửa tệp/trình xem/phân tích cho tệp thi hành. Mục tiêu là kết hợp chức năng cấp thấp của trình gỡ rối và khả năng sử dụng của các IDE. Chúng tôi dự định triển khai tất cả các tính năng chỉnh sửa (hex-) và hỗ trợ các định dạng tệp quan trọng nhất.

Tôi không thể tìm thấy điều gì khác biệt so với giải pháp của ZorbaTHut, nhưng có thể đặt tên với độ dài khác và vẫn giữ nguyên nhị phân.

gelf - điều này cũng hữu ích.

GElf là một API độc lập cấp ELF chung cho thao tác- các tệp đối tượng ELF. GElf cung cấp một mặt phổ biến duy nhất, phổ biến để xử lý các tệp đối tượng định dạng ELF 32 bit và 64 bit.

+0

Tốt. HT là không thực tế đối với tôi vì tôi cần một giải pháp CLI. gelf trông hoàn toàn thực tế - giả sử nó hoạt động - Tôi chỉ cần viết mã thực tế xung quanh nó. Câu trả lời tốt nhất cho đến nay. – ZorbaTHut

+7

Cập nhật: patchelf (http://nixos.org/patchelf.html) có vẻ là cách để đi ngay bây giờ. –

+0

bản vá (hiện tại) không có tính năng này. nó chỉ cho phép bạn loại bỏ hoàn toàn các phụ thuộc, hoặc thiết lập RPATH (khác với việc thay đổi tên của một lib được chia sẻ) – hraban

-3

Bạn có thể sử dụng LD_LIBRARY_PATH để thay đổi đường dẫn tìm kiếm cho các thư viện được chia sẻ. Nếu chương trình của bạn phụ thuộc vào một đường dẫn tương đối cụ thể như ví dụ của bạn cho thấy, bạn sẽ vẫn cần phải có cấu trúc thư mục đó. Nói cách khác, bạn có thể di chuyển thư viện từ /home/user/dev/project/this/is/terrible/library.so sang /usr/local/lib/this/is/terrible/library.so nhưng không được để /usr/local/lib/library.so

Nếu bạn có thể tạo lại chương trình, bạn có thể thay đổi đường dẫn tương đối mà nó sử dụng cho lib.

Có một số thông tin thêm về libs chia sẻ trong Linux tại http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

+0

Không giúp ích gì trong trường hợp của tôi. Tôi đang dùng một chương trình đã được xây dựng rồi cố gắng triển khai nó cho các hệ thống của người khác. Trước tiên, tôi không muốn muck về với LD_LIBRARY_PATH trên hệ thống của họ. Thứ hai, như bạn đề cập, điều đó sẽ không thực sự loại bỏ tiền tố này/là/khủng khiếp /, chỉ cho phép tôi thêm một tiền tố khác ở trước nó. Chương trình của tôi chỉ phụ thuộc vào cấu trúc thư mục đó vì đó là nơi mà nó tìm kiếm DLL - đó chính xác là những gì tôi đang cố thay đổi :) – ZorbaTHut

7

Đăng một, khủng khiếp, giải pháp hacky dự kiến.

Các phụ thuộc thư viện được lưu trữ trong khối ELF được gọi là khối .depends. Định dạng của khối đó là một mảng lớn các cặp định danh/chuỗi ký tự, với chuỗi ký tự trỏ đến một chuỗi ký tự không có giá trị C tiêu chuẩn nằm ở đâu đó trong tệp nhị phân.

Bạn thấy nơi này đang diễn ra, phải không?

Đúng, miễn là đường dẫn mới bạn cần không lớn hơn đường dẫn cũ, bạn chỉ có thể tiếp cận ngay vào nhị phân và thực hiện thay thế chuỗi đơn giản. Đảm bảo không thêm hoặc xóa byte hoặc bạn sẽ phá vỡ toàn bộ nhị phân. Nếu bạn muốn an toàn hơn về nó, bạn thực sự có thể đi qua cấu trúc ELF để đảm bảo bạn có đúng vị trí - ngay bây giờ tôi chỉ kiểm tra để đảm bảo chuỗi nguồn hiển thị chính xác một lần.

ELF không bao gồm tổng kiểm tra, nhưng dường như không có trình tải thực sự xác minh nó, vì vậy nó "an toàn" - mặc dù lộn xộn - để bỏ qua.

"Giải pháp thực sự" sẽ là một tiện ích cho phép các thao tác tổng quát mức độ thấp của cấu trúc ELF. Gần như tôi có thể nói, không có tiện ích như vậy tồn tại, cho bất cứ điều gì ngoại trừ một vài trường hợp đặc biệt (RPATH, chủ yếu.) Tôi không giả vờ để biết làm thế nào khó khăn như một tiện ích sẽ được viết.

Tôi hoàn toàn sẽ thích một giải pháp tốt hơn cho điều này, nhưng, cho đến nay, điều này dường như hoạt động.

+1

Tôi co rúm lại khi nghĩ về các khối ELF chỉnh sửa hex, nhưng tôi cho rằng nó sẽ hoạt động. Nếu ứng dụng sẽ không được di chuyển sau khi cài đặt, bạn có thể symlink "shared/library.so" và "this/is/terrible/library.so". Tuy nhiên, tôi khuyên bạn nên xây dựng lại với các đường dẫn chính xác và phát hành bản vá/cập nhật cho người dùng chương trình của bạn như một giải pháp thân thiện với người dùng hơn nhiều. – bta

+0

Vấn đề thực sự với "xây dựng lại" là tôi không muốn gây ô nhiễm bố cục hệ thống xây dựng của mình với các yêu cầu kỳ lạ từ thời gian chạy, và tương tự như vậy tôi không muốn gây ô nhiễm bố cục thời gian chạy của tôi với các yêu cầu kỳ lạ từ thời gian xây dựng. Nó không phải là một vấn đề tương thích ở tất cả, nó chỉ là đảm bảo rằng cả bản thân mình và người dùng của tôi đang hạnh phúc. – ZorbaTHut

+0

Tôi không thấy cách xây dựng lại ứng dụng của bạn với một đối số nữa cho CC sẽ gây ô nhiễm môi trường xây dựng của bạn.Nhưng tôi đoán bạn nên biết tốt hơn sau đó tôi :-) – Stan

6

Chúng ta có thể sử dụng patchelf:

patchelf --replace-needed liboriginal.so.1 libreplacement.so.1 my-program 

Chúng tôi cũng có thể loại bỏ sự phụ thuộc:

patchelf --remove-needed libfoo.so.1 my-program 

Thêm một sự phụ thuộc:

patchelf --add-needed libfoo.so.1 my-program 

Hoặc thay đổi đường dẫn nơi để tìm kiếm cho các thư viện (rpath):

patchelf --set-rpath /path/to/lib:/other/path my-program 
Các vấn đề liên quan