rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.73k stars 12.5k forks source link

libcore on riscv64gc-unknown-none-elf contains problematic .sdata section #120685

Open dreiss opened 7 months ago

dreiss commented 7 months ago

libcore on riscv64gc-unknown-none-elf contains a ".sdata" section filled with (apparently) read-only constants, which causes problems on some embedded platforms. Because it is a single monolithic section (as opposed to .sdata.* or .srodata.*), any output binary that requires any part of it will include the section in its entirety. Because it is mutable (as opposed to .srodata or .srodata.*), it requires mutable RAM, which can be scarce. (In fact, I'm trying to use Rust in an environment that doesn't support mutable global variables at all.)

It would be much better for the objects in this section to go into individual .srodata.* sections so (1) they can be included or excluded from the binary individually, and (2) they can be placed in read-only memory. Another option for objects that are only used by one function would be to put them in the .text.* sections that contain those functions so PC-relative loads can be used to load them. (I think this is the convention on ARM.)

Reproduce with https://github.com/dreiss/rust_sdata_repro , revision 6dde765a933eb27b6b2cb81f77a539d7eafe88b7 (which is basically just a riscv-rt skeleton with a call to core::ffi::CStr::from_bytes_with_nul), by running cargo build --release , then extracting the binary's data section with objdump -s -j.data target/riscv64gc-unknown-none-elf/release/sd-test . For example, you can see the string "INFINITY", which is not used by code in this application.

The functions that reference .sdata are:

core::ffi::c_str::CStr::from_bytes_until_nul
core::ffi::c_str::CStr::from_bytes_with_nul
<core::fmt::builders::PadAdapter as core::fmt::Write>::write_str
core::fmt::float::<impl core::fmt::Debug for f32>::fmt
core::fmt::float::<impl core::fmt::Debug for f64>::fmt
core::fmt::num::exp_u128
core::fmt::num::fmt_u128
core::fmt::num::imp::exp_u64
core::fmt::num::imp::fmt_u64
core::fmt::num::parse_u64_into
core::num::dec2flt::decimal::parse_decimal
core::num::dec2flt::<impl core::str::traits::FromStr for f32>::from_str
core::num::dec2flt::<impl core::str::traits::FromStr for f64>::from_str
core::num::dec2flt::parse::parse_number
core::num::flt2dec::strategy::dragon::format_exact
<core::panic::panic_info::PanicInfo as core::fmt::Display>::fmt
<core::ptr::alignment::Alignment as core::fmt::Debug>::fmt
core::slice::memchr::memchr_aligned
core::slice::memchr::memrchr
core::str::converts::from_utf8
core::str::converts::from_utf8_mut
<core::time::Duration as core::fmt::Debug>::fmt::fmt_decimal
<T as core::any::Any>::type_id

Meta

rustc --version --verbose:

rustc 1.75.0 (82e1608df 2023-12-21)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-unknown-linux-gnu
release: 1.75.0
LLVM version: 17.0.6

Reproduces on nightly as well.

bjorn3 commented 7 months ago

As far as I can tell LLVM never uses .srodata: https://github.com/search?q=repo%3Allvm%2Fllvm-project%20srodata&type=code It also seems to always use a single section .sdata section rather than .sdata.*. This would need to be fixed in LLVM.

dreiss commented 6 months ago

For folks building their own libcore, this can be fixed by compiling with the unstable flag "-Zllvm_module_flag=SmallDataLimit:u32:0:Error". But for folks using pre-compiled toolchains, this doesn't help.

workingjubilee commented 2 months ago

cc embedded RISCV team: @almindor @dkhayes117 @romancardenas @MabezDev @jessebraham you're not listed for RISCV64gc-unknown-none-elf for some reason but eh close enough.