Tôi đã biên soạn một chương trình Rust cho armv7-unknown-linux-gnueabihf
và tôi muốn nó chạy trên hệ thống có cài đặt glibc 2,16. Thật không may khi chạy nó Tôi nhận được lỗi này:Làm thế nào tôi có thể biên dịch một chương trình Rust để nó không sử dụng __cxa_thread_atexit_impl?
./foo: /lib/libc.so.6: version `GLIBC_2.18' not found (required by ./foo)
Chạy objdump -T foo
tiết lộ rằng biểu tượng chỉ cần từ glibc 2.18 là:
00000000 w DF *UND* 00000000 GLIBC_2.18 __cxa_thread_atexit_impl
Rust makes __cxa_thread_atexit_impl
a weak symbol (như được thấy bởi ít w
cờ từ objdump
), tuy nhiên GCC dường như là ngu ngốc và mặc dù tất cả các biểu tượng từ GLIBC_2.18 đều yếu nhưng nó vẫn khiến GLIBC_2.18 trở thành một yêu cầu mạnh mẽ. Bạn có thể thấy rằng với readelf
:
$ readelf -V foo
...
Version needs section '.gnu.version_r' contains 5 entries:
Addr: 0x0000000000001e4c Offset: 0x001e4c Link: 6 (.dynstr)
000000: Version: 1 File: ld-linux-armhf.so.3 Cnt: 1
0x0010: Name: GLIBC_2.4 Flags: none Version: 9
0x0020: Version: 1 File: librt.so.1 Cnt: 1
0x0030: Name: GLIBC_2.4 Flags: none Version: 5
0x0040: Version: 1 File: libgcc_s.so.1 Cnt: 4
0x0050: Name: GCC_4.3.0 Flags: none Version: 10
0x0060: Name: GCC_3.0 Flags: none Version: 7
0x0070: Name: GCC_3.5 Flags: none Version: 6
0x0080: Name: GCC_3.3.1 Flags: none Version: 4
0x0090: Version: 1 File: libc.so.6 Cnt: 2
0x00a0: Name: GLIBC_2.18 Flags: none Version: 8
0x00b0: Name: GLIBC_2.4 Flags: none Version: 3
0x00c0: Version: 1 File: libpthread.so.0 Cnt: 1
0x00d0: Name: GLIBC_2.4 Flags: none Version: 2
ý rằng GLIBC_2.18
nói Flags: none
. Nó sẽ nói Flags: WEAK
. May mắn thay tôi tìm thấy an amazing page where someone shows how to fix this. Thật không may nó liên quan đến hex chỉnh sửa nhị phân!
Rẽ bù đắp điều đó .gnu.version_r
bảng (0x001e4c
), thêm các mục nhập bù đắp cho GLIBC_2.18
(0x00a0
), sau đó thêm một offset cho cờ trường của struct tại địa chỉ đó (0x04
). Điều đó cho phép 0x001EF0
. Tại địa chỉ đó, phải có hai byte không: 0x0000
. Thay đổi chúng thành 0x0200
.
Xác nhận với readelf
:
Version needs section '.gnu.version_r' contains 5 entries:
Addr: 0x0000000000001e4c Offset: 0x001e4c Link: 6 (.dynstr)
000000: Version: 1 File: ld-linux-armhf.so.3 Cnt: 1
0x0010: Name: GLIBC_2.4 Flags: none Version: 9
0x0020: Version: 1 File: librt.so.1 Cnt: 1
0x0030: Name: GLIBC_2.4 Flags: none Version: 5
0x0040: Version: 1 File: libgcc_s.so.1 Cnt: 4
0x0050: Name: GCC_4.3.0 Flags: none Version: 10
0x0060: Name: GCC_3.0 Flags: none Version: 7
0x0070: Name: GCC_3.5 Flags: none Version: 6
0x0080: Name: GCC_3.3.1 Flags: none Version: 4
0x0090: Version: 1 File: libc.so.6 Cnt: 2
0x00a0: Name: GLIBC_2.18 Flags: WEAK Version: 8
0x00b0: Name: GLIBC_2.4 Flags: none Version: 3
0x00c0: Version: 1 File: libpthread.so.0 Cnt: 1
0x00d0: Name: GLIBC_2.4 Flags: none Version: 2
thành công! Ngoại trừ nó vẫn không hoạt động:
./foo: /lib/libc.so.6: weak version `GLIBC_2.18' not found (required by ./foo)
./foo: relocation error: ./foo: symbol __cxa_thread_atexit_impl, version GLIBC_2.18 not defined in file libc.so.6 with link time reference
thế nào là phiên bản yếu vẫn cần ?! Tôi không thể đợi glibc chết.
Có cách nào để Rust tạo chương trình mà không sử dụng biểu tượng này không?
Chấp nhận khi mọi thứ khủng khiếp là cách duy nhất [chúng được cải tiến] (https://www.musl-libc.org/). Xin lỗi nếu tôi xúc phạm bất kỳ nhà phát triển GNU nào. – Timmmm
Bạn đang cố ý xúc phạm * rất * người có thể trả lời câu hỏi của bạn. Tôi sẽ thứ hai @tumdum và đề nghị bạn loại bỏ các bộ phận phản tác dụng. Là một câu trả lời một phần, có * là * lý do chính xác GLIBC hoạt động theo cách của nó. Và nếu bạn tin rằng Musl là câu trả lời, chính xác thì điều gì ngăn cản bạn sử dụng nó? –
'armv7-unknown-linux-muscl' không có sẵn như là một mục tiêu nhưng không may. Ngoài ra nếu tôi * có thể * có được điều này để làm việc glibc 2.4 là đủ tuổi (2006) mà đòi hỏi nó không phải là không hợp lý và nó tiết kiệm không gian so với muscl. Nếu không có cách nào xung quanh yêu cầu 2.18 (2013) thì muscl chắc chắn là một lựa chọn tốt hơn. – Timmmm