Gần đây chúng tôi đã được yêu cầu gửi một phiên bản Linux của một trong các thư viện của chúng tôi, trước đây chúng tôi đã phát triển dưới Linux và được giao cho Windows nơi triển khai thư viện thường dễ dàng hơn nhiều. Vấn đề chúng tôi gặp phải là loại bỏ các biểu tượng được xuất khẩu xuống chỉ những biểu tượng trong giao diện tiếp xúc. Có ba lý do chính đáng để thực hiện điều nàyTách thư viện chia sẻ linux
- Để bảo vệ các khía cạnh độc quyền của công nghệ khỏi tiếp xúc thông qua các ký hiệu đã xuất.
- Để ngăn người dùng gặp sự cố với tên biểu tượng xung đột.
- Để tăng tốc độ tải thư viện (ít nhất là tôi được thông báo).
Lấy một ví dụ đơn giản sau đó:
test.cpp
#include <cmath>
float private_function(float f)
{
return std::abs(f);
}
extern "C" float public_function(float f)
{
return private_function(f);
}
biên soạn với (g ++ 4.3.2, ld 2.18.93.20081009)
g++ -shared -o libtest.so test.cpp -s
và kiểm tra những biểu tượng với
nm -DC libtest.so
cung cấp cho
w _Jv_RegisterClasses
0000047c T private_function(float)
000004ba W std::abs(float)
0000200c A __bss_start
w __cxa_finalize
w __gmon_start__
0000200c A _edata
00002014 A _end
00000508 T _fini
00000358 T _init
0000049b T public_function
rõ ràng là không đủ. Vì vậy, tiếp theo chúng ta redeclare các chức năng công cộng như
extern "C" float __attribute__ ((visibility ("default")))
public_function(float f)
và biên dịch với
g++ -shared -o libtest.so test.cpp -s -fvisibility=hidden
mang đến cho
w _Jv_RegisterClasses
0000047a W std::abs(float)
0000200c A __bss_start
w __cxa_finalize
w __gmon_start__
0000200c A _edata
00002014 A _end
000004c8 T _fini
00000320 T _init
0000045b T public_function
đó là tốt, trừ std :: rằng abs được tiếp xúc. Vấn đề hơn là khi chúng tôi bắt đầu liên kết trong các thư viện (tĩnh) khác ngoài tầm kiểm soát của chúng tôi, tất cả các ký hiệu chúng tôi sử dụng từ các thư viện đó được xuất. Bên cạnh đó, khi chúng ta bắt đầu sử dụng STL container:
#include <vector>
struct private_struct
{
float f;
};
void other_private_function()
{
std::vector<private_struct> v;
}
chúng tôi kết thúc với nhiều xuất khẩu bổ sung từ Thư viện C++
00000b30 W __gnu_cxx::new_allocator<private_struct>::deallocate(private_struct*, unsigned int)
00000abe W __gnu_cxx::new_allocator<private_struct>::new_allocator()
00000a90 W __gnu_cxx::new_allocator<private_struct>::~new_allocator()
00000ac4 W std::allocator<private_struct>::allocator()
00000a96 W std::allocator<private_struct>::~allocator()
00000ad8 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_Vector_impl::_Vector_impl()
00000aaa W std::_Vector_base<private_struct, std::allocator<private_struct> >::_Vector_impl::~_Vector_impl()
00000b44 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_M_deallocate(private_struct*, unsigned int)
00000a68 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_M_get_Tp_allocator()
00000b08 W std::_Vector_base<private_struct, std::allocator<private_struct> >::_Vector_base()
00000b6e W std::_Vector_base<private_struct, std::allocator<private_struct> >::~_Vector_base()
00000b1c W std::vector<private_struct, std::allocator<private_struct> >::vector()
00000bb2 W std::vector<private_struct, std::allocator<private_struct> >::~vector()
NB: Với optimisations trên bạn sẽ cần phải chắc chắn rằng các vector là thực sự được sử dụng để trình biên dịch không tối ưu hóa các biểu tượng không sử dụng.
Tôi tin rằng đồng nghiệp của tôi đã được quản lý để xây dựng một giải pháp ad-hoc liên quan đến các file phiên bản và sửa đổi các tiêu đề STL xuất hiện để làm việc, nhưng tôi muốn hỏi (!):
Có cách nào sạch thế nào để loại bỏ tất cả các ký hiệu không cần thiết (các biểu tượng IE không phải là một phần của chức năng thư viện được trưng ra) từ một thư viện được chia sẻ Linux? Tôi đã thử khá nhiều tùy chọn cho cả g ++ và ld với rất ít thành công vì vậy tôi muốn các câu trả lời được biết là hoạt động hơn là được tin tưởng.
Đặc biệt:
- Biểu tượng từ (nguồn đóng) thư viện tĩnh không được xuất khẩu.
- Ký hiệu từ thư viện chuẩn không được xuất.
- Ký hiệu không công khai từ các tệp đối tượng không được xuất.
giao diện xuất khẩu của chúng tôi là C.
Tôi biết trong những câu hỏi tương tự khác trên SO:
- NOT sharing all classes with shared library
- How to REALLY strip a binary in MacOs
- GNU linker: alternative to --version-script to list exported symbols at the command line?
nhưng h ave có rất ít thành công với câu trả lời.
Trên liên kết tĩnh của thư viện hệ thống: Việc bạn làm điều đó là bất hợp pháp. Đó là, vì [(e)] (http://www.eglibc.org/) [GLIBC] (http://www.gnu.org/software/libc/) được cấp phép theo [LGPL] (http://opensource.org/licenses/LGPL-3.0) và vì giấy phép đó áp dụng cho tất cả mã sử dụng ngoại trừ nếu được liên kết động, bằng cách liên kết tĩnh bạn tạo mã của mình được bao gồm bởi LGPL và được yêu cầu cung cấp nguồn (cho bất kỳ ai bạn đã cung cấp nhị phân và họ yêu cầu các nguồn). Điều này không áp dụng cho libgcc và libstdC++, đặc biệt không áp dụng cho bất kỳ mã nào sử dụng API công khai, cho dù liên kết như thế nào. –
Tôi nhận thức được điều này và không đề cập đến các biểu tượng từ glibc, tất cả các ký hiệu trên được tạo ra bởi mẫu instantiation từ thư viện chuẩn C++ và, bởi sự cần thiết, được tạo ra trong các tệp đối tượng của tôi. t trong thư viện!). –