Let's use as a simplified example crate foo
, with the following Cargo.toml:
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[lib]
name = "foo"
crate-type = ["cdylib"]
[profile.release]
panic = "abort"
strip = true
And src/lib.rs:
#![no_std]
#[cfg(not(test))]
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
extern "C" { fn panic_nonexistent() -> !; }
unsafe { panic_nonexistent() }
}
#[no_mangle]
pub unsafe extern "C" fn foo_cpy(src: *const u8, dst: *mut u8, len: usize) {
core::ptr::copy_nonoverlapping(src, dst, len)
}
It gets compiled to libfoo.so
. But when we inspect it, we get:
$ ldd libfoo.so
statically linked
$ readelf -Ws libfoo.so
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND memcpy
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __cxa_finalize
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
6: 0000000000001100 15 FUNC GLOBAL DEFAULT 9 foo_cpy
Is it correct that the generated shared library uses external memcpy
, but does not link to anything?
Usually it works fine, since memset
is a standard symbol and usually present during linking process. But when I tried to create a different shared library which links both libc
and libfoo
, I get the following warning:
Relink `libfoo.so' with `/lib/x86_64-linux-gnu/libc.so.6' for IFUNC symbol `memcpy'
I "solved" this issue by explicitly linking libfoo
to libc
using build script, but shouldn't it be done automatically by compiler when I build it for x86_64-unknown-linux-gnu
?
Is it possible to forcibly inline implementation of built-in intrinsics like memcpy
to get a truly static shared library?