2013-10-03 14 views
6

Tôi đã viết một thư viện được chia sẻ với một số phiên bản không tương thích. Tôi đã thay đổi SONAME, vì vậy chúng được gọi là:Phát hiện hai phiên bản không tương thích ABI của thư viện được chia sẻ của tôi được tải vào một chương trình

  • lib_mylib.so.1.0.0 (thư viện cũ)
  • lib_mylib.so.2.0.0

Có một số chức năng chỉ trong mylib. so.1, một số khác chỉ có trong mylib.so.2 và nhiều chức năng là phổ biến (nhưng một số đã thay đổi số đối số)

Và tôi sợ rằng có thể liên kết cả hai phiên bản của mylib vào một ứng dụng, ví dụ khi bản thân ứng dụng lớn và bao gồm nhiều thư viện. Khi ứng dụng được xây dựng lại một phần, có thể có tình trạng như vậy:

  • Application
  • app_lib1.so (được xây dựng với mylib.so.1 - Phiên bản đầu tiên của lib của tôi)
  • app_lib2.so (được xây dựng lại với mylib.so.2 - phiên bản thứ hai)

Tôi đã thấy ứng dụng có cả hai phiên bản được nạp vào nó (ldd báo cáo cả hai).

Vì vậy, có thể thêm một số mã kiểm tra vào mylib.so.2 để phát hiện rằng có cả hai phiên bản của thư viện đã được tải và chúng có xung đột ABI/Giao diện. (Tôi không thể sửa đổi lib_mylib.so.1 để thêm nội dung nào đó vào đó)

Trả lời

1

Bạn có thể phân tích cú pháp /proc/self/maps để nhận danh sách các đối tượng hiện đang được tải.

+0

Tôi chỉ có thể phân tích cú pháp '/ proc/self/maps' trong hàm tạo của thư viện của tôi. Tôi nghĩ rằng có thể, tại thời điểm chạy hàm khởi tạo của tôi từ thư viện thứ hai, thư viện đầu tiên sẽ chưa được nạp vào bộ nhớ (trường hợp 1: mylib2 sớm hơn mylib1 trong danh sách libs; trường hợp 2: mylib1 sẽ được tải bằng cách sử dụng dlopen tại một thời gian sau) – osgx

3

Bạn có thể sửa đổi thư viện phiên bản 2 của mình để giải quyết một số biểu tượng phiên bản 1 cụ thể (dlsym(3)) trong khi khởi động và gặp lỗi khi tìm thấy.

Ví dụ:

extern __attribute__((constructor)) void _version_check2() 
{ 
    if (dlsym(RTLD_DEFAULT, "version_1_function")) 
     abort(); 
} 

Một giải pháp duyên dáng hơn là để cho phiên bản 2 thư viện bắt chước hành vi của phiên bản 1, nhưng đó giới thiệu mã di sản.

EDIT

Để có bằng chứng trong tương lai, bạn cũng có thể giới thiệu một phiên bản biến tĩnh và tất cả các cuộc gọi chức năng sẽ kiểm tra nếu nó phù hợp với hiện tại. Sau đó, trong các phiên bản tương lai, bạn chỉ cần thay đổi giá trị của biến đó và bị lỗi nếu không khớp.

EDIT 2

Bạn cũng có thể gọi chức năng này trên mỗi phiên bản 2 chức năng để sớm hay muộn khi phiên bản 1 được nạp treo ứng dụng của bạn.

+0

Hoặc có thể là "dlopen" (RTLD_NOLOAD, "lib_mylib.so.1.0.0") cụ thể của Linux. – rodrigo

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