Closed Dirbaio closed 3 years ago
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @jonas-schievink (or someone else) soon.
If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.
Please see the contribution instructions for more information.
I'm trying to replicate this on any of my projects without success, any idea if there are more conditions than reported here to trigger the bug?
We were seeing this only with GNU LD, but @Dirbaio also saw it with LLD. Maybe the linker or linker version matters?
If I follow the instructions in the first post, I still don't reproduce this issue; the ELF looks fine in both debug and release modes, and I get the same thing in other projects too. I'm using rustc 1.46.0, but I'm sure I've generated non-aligned images for ages without issue.
@Dirbaio, could you double check your env
doesn't have any stale settings like RUST_FLAGS or something, just in case? Alternatively could you possibly zip up a minimal crate which demonstrates this problem?
I'm using rust nightly from rustup, and lld from Arch Linux repos. (not sure if rust uses system's lld or bundles its own though)
[dirbaio@mars nrfconnect]$ rustc --version
rustc 1.48.0-nightly (d006f5734 2020-08-28)
[dirbaio@mars nrfconnect]$ ld.lld --version
LLD 10.0.1 (compatible with GNU linkers)
[dirbaio@mars nrfconnect]$ pacman -Qo $(which ld.lld)
/usr/bin/ld.lld is owned by lld 10.0.1-1
Nothing about rust in env.
Repro is literally cargo generate
and changing memory.x
. Attached tarball with everything in target
as is. -> repro.tar.gz
Just cargo build
and llvm-objdump -x target/thumbv7m-none-eabi/debug/repro
Aha, I can duplicate this using nightly but not on stable. Looks like this is an LLVM regression in nightly, then? Rust uses its own copy of LLD by default, it doesn't require one on the system.
I did some more investigation.
[dirbaio@mars repro]$ ld.lld --help | grep magic
--nmagic Do not page align sections, link against static libraries.
--no-nmagic Page align sections (default)
--no-omagic Do not set the text data sections to be writable, page align sections (default)
-N Alias for --omagic
-n Alias for --nmagic
--omagic Set the text and data sections to be readable and writable, do not page align sections, link against static libraries
STABLE
rustc 1.46.0 (04488afe3 2020-08-24):
LOAD off 0x00001000 vaddr 0x00027000 paddr 0x00027000 align 2**12
filesz 0x00000acc memsz 0x00000acc flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
rustc 1.46.0 (04488afe3 2020-08-24) with --nmagic:
LOAD off 0x000000b4 vaddr 0x00027000 paddr 0x00027000 align 2**2
filesz 0x00000a7c memsz 0x00000a7c flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
rustc 1.46.0 (04488afe3 2020-08-24) with -zmax-page-size=0x1000
LOAD off 0x00001000 vaddr 0x00027000 paddr 0x00027000 align 2**12
filesz 0x00000acc memsz 0x00000acc flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
rustc 1.46.0 (04488afe3 2020-08-24) with -zmax-page-size=0x10000 ===> BROKEN!!
PHDR off 0x00000034 vaddr 0x00020034 paddr 0x00020034 align 2**2
filesz 0x000000c0 memsz 0x000000c0 flags r--
LOAD off 0x00000000 vaddr 0x00020000 paddr 0x00020000 align 2**16
filesz 0x000000f4 memsz 0x000000f4 flags r-x
LOAD off 0x00007000 vaddr 0x00027000 paddr 0x00027000 align 2**16
filesz 0x00000acc memsz 0x00000acc flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
NIGHTLY
rustc 1.48.0-nightly (d006f5734 2020-08-28) ===> BROKEN!!
PHDR off 0x00000034 vaddr 0x00020034 paddr 0x00020034 align 2**2
filesz 0x00000100 memsz 0x00000100 flags r--
LOAD off 0x00000000 vaddr 0x00020000 paddr 0x00020000 align 2**16
filesz 0x00000134 memsz 0x00000134 flags r--
LOAD off 0x00007000 vaddr 0x00027000 paddr 0x00027000 align 2**16
filesz 0x00000400 memsz 0x00000400 flags r--
LOAD off 0x00007400 vaddr 0x00027400 paddr 0x00027400 align 2**16
filesz 0x00000550 memsz 0x00000550 flags r-x
LOAD off 0x00007950 vaddr 0x00027950 paddr 0x00027950 align 2**16
filesz 0x00000180 memsz 0x00000180 flags r--
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
rustc 1.48.0-nightly (d006f5734 2020-08-28) with --nmagic
LOAD off 0x000000f4 vaddr 0x00027000 paddr 0x00027000 align 2**2
filesz 0x00000400 memsz 0x00000400 flags r--
LOAD off 0x000004f4 vaddr 0x00027400 paddr 0x00027400 align 2**2
filesz 0x00000550 memsz 0x00000550 flags r-x
LOAD off 0x00000a44 vaddr 0x00027950 paddr 0x00027950 align 2**2
filesz 0x00000180 memsz 0x00000180 flags r--
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
rustc 1.48.0-nightly (d006f5734 2020-08-28) with -zmax-page-size=0x1000
LOAD off 0x00001000 vaddr 0x00027000 paddr 0x00027000 align 2**12
filesz 0x00000400 memsz 0x00000400 flags r--
LOAD off 0x00001400 vaddr 0x00027400 paddr 0x00027400 align 2**12
filesz 0x00000550 memsz 0x00000550 flags r-x
LOAD off 0x00001950 vaddr 0x00027950 paddr 0x00027950 align 2**12
filesz 0x00000180 memsz 0x00000180 flags r--
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
rustc 1.48.0-nightly (d006f5734 2020-08-28) with -zmax-page-size=0x10000 ===> BROKEN!!
PHDR off 0x00000034 vaddr 0x00020034 paddr 0x00020034 align 2**2
filesz 0x00000100 memsz 0x00000100 flags r--
LOAD off 0x00000000 vaddr 0x00020000 paddr 0x00020000 align 2**16
filesz 0x00000134 memsz 0x00000134 flags r--
LOAD off 0x00007000 vaddr 0x00027000 paddr 0x00027000 align 2**16
filesz 0x00000400 memsz 0x00000400 flags r--
LOAD off 0x00007400 vaddr 0x00027400 paddr 0x00027400 align 2**16
filesz 0x00000550 memsz 0x00000550 flags r-x
LOAD off 0x00007950 vaddr 0x00027950 paddr 0x00027950 align 2**16
filesz 0x00000180 memsz 0x00000180 flags r--
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**64
filesz 0x00000000 memsz 0x00000000 flags rw-
The exact commit that changed this is https://github.com/llvm/llvm-project/commit/87383e408d41623ada41e2bbc371b037fa29e894 . Apparently it's for compat with GCC linker and with systems with bigger pages. It's not a nightly regression.
IMO the right fix is --nmagic
.
The alternative is adding -zmax-page-size=0x1000
to restore the old smaller alignment, but someone might need even lower alignment. There are chips out there with flash pages smaller than 0x1000. eg nrf51 is 0x400.
Configuration problem: bors.toml: not found
Yeah, no bors in here. Let's just merge it then, shall we? ;)
If one switches to using the gnu linker (ld) instead of llvm because of this bug: https://github.com/rust-lang/rust/issues/88704 then you get this:
= note: arm-none-eabi-gcc.exe: error: unrecognized command line option '--nmagic'
linker switched using this .cargo/config.toml snippet.
[target.thumbv7m-none-eabi]
rustflags = [
"-C", "linker=arm-none-eabi-gcc",
...
Is there a solution that also works for gnu ld ?
Try replacing arm-none-eabi-gcc
with arm-none-eabi-ld
:
[target.thumbv7m-none-eabi]
rustflags = [
"-C", "linker=arm-none-eabi-ld",
--nmagic
is a flag in the GNU linker[1], so it should work.
Try replacing
arm-none-eabi-gcc
witharm-none-eabi-ld
:
doh! yes, overlooked that... I'll give it a whirl and report back as time permits.
I have to use 'gcc' because other arguments need to be passed to it, for map file and for keeping generated assembly files.
[target.thumbv7m-none-eabi]
rustflags = [
"-C", "linker=arm-none-eabi-gcc",
"-C", "link-arg=-nostartfiles",
"-C", "link-arg=-Wl,--print-memory-usage",
"-C", "link-arg=-Wl,-Map=out.map",
"-C", "link-arg=-Wl,--verbose",
"-C", "save-temps",
"--emit", "asm",
]
a solution that works is to use a build.rs file:
// for GNU LD
println!("cargo:rustc-link-arg-bins=-Wl,--nmagic");
// for LLVM
//println!("cargo:rustc-link-arg-bins=--nmagic");
but you have to know which linker you're using to uncomment the right line. Some automatic way of doing it would be ideal.
Without this, the linker places some extra program header entries that can confuse flashing tools.
Many thanks to @jonas-schievink for pointing me to this flag in Matrix.
How to reproduce the bug
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
ORIGIN = 0x00027000
inmemory.x
cargo build
llvm-objdump -x target/thumbv7em-none-eabihf/debug/repro
Program header entries will look something like this:
The entry at 0x00020000 causes flashing tools (probe-rs at least) to flash data at 0x00020000, corrupting whatever's there. This happens whenever flash ORIGIN is not a multiple of 0x10000.
With
--nmagic
, program headers are correct and flashing does what it's supposed to do: