Open crepererum opened 3 years ago
Playing around with llvm-objcopy
instead, the situation becomes much clearer:
$ llvm-objcopy --version
llvm-objcopy, compatible with GNU objcopy
LLVM (http://llvm.org/):
LLVM version 10.0.1
Optimized build.
Default target: x86_64-pc-linux-gnu
Host CPU: broadwell
$ llvm-objcopy -O binary -R .stack -R .bss r-riscv-blink r-riscv-blink.bin
$ ls -lh r-riscv-blink{,.bin}
-rwxr-xr-x 2 tom tom 456K Jul 25 16:08 r-riscv-blink
-rwxr-xr-x 1 tom tom 259K Jul 26 20:34 r-riscv-blink.bin
Here, .stack
and .bss
must be remove to not blow up the file. Looking at the readelf
output again, it also becomes clear why. .bss
and .stack
are the only non-empty "alloc" section with an address around 10000000
, while the other "alloc" sections are located around 20000000
. That's exactly the 256MB delta.
Why is this not happening on C? Simply because the sections are not spread out that much:
$ readelf -S riscv-blink.elf
There are 17 section headers, starting at offset 0x1e28:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 20040000 001000 0001b0 00 AX 0 0 4
[ 2] .rodata PROGBITS 200401b0 0011b0 000000 00 WA 0 0 1
[ 3] .data PROGBITS 10000000 0011b0 000000 00 WA 0 0 1
[ 4] .bss NOBITS 10000000 000000 000000 00 WA 0 0 1
[ 5] .debug_info PROGBITS 00000000 0011b0 00015b 00 0 0 1
[ 6] .debug_abbrev PROGBITS 00000000 00130b 0000f1 00 0 0 1
[ 7] .debug_aranges PROGBITS 00000000 001400 000060 00 0 0 8
[ 8] .debug_ranges PROGBITS 00000000 001460 000048 00 0 0 8
[ 9] .debug_line PROGBITS 00000000 0014a8 000353 00 0 0 1
[10] .debug_str PROGBITS 00000000 0017fb 000186 01 MS 0 0 1
[11] .comment PROGBITS 00000000 001981 000022 01 MS 0 0 1
[12] .riscv.attributes RISCV_ATTRIBUTE 00000000 0019a3 00001c 00 0 0 1
[13] .debug_frame PROGBITS 00000000 0019c0 00006c 00 0 0 4
[14] .symtab SYMTAB 00000000 001a2c 000270 10 15 23 4
[15] .strtab STRTAB 00000000 001c9c 0000df 00 0 0 1
[16] .shstrtab STRTAB 00000000 001d7b 0000aa 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
So how can the section addressed be controlled?
Ah, now I get it:
The issue is that one part is the spiflash, the other one the RAM but everything must be one chunk for the flashing process (or at least the way it is implemented). So two question now remain:
.bss
and .data
segment at all?I observed the issue with riscv64-linux-gnu-
toolchain from ArchLinux repo, but at the same time everything was ok with riscv64-unknown-elf-
toolchain from SiFive.
On my machine right now:
$ cargo update # to fix .eh_frame_hdr problem
$ cargo run --release
$ cd target/riscv32i-unknown-none-elf/release/
$ ls -lh r-riscv-blink{,.bin}
-rwxr-xr-x 2 disasm users 72K Jul 27 00:53 r-riscv-blink
-rwxr-xr-x 1 disasm users 2.4K Jul 27 00:54 r-riscv-blink.bin
Probably something is wrong with .stack
section flags, but I have no idea what is the real reason and why different toolchains behave differently.
This seems to be a known (and fixed) issue: https://github.com/rust-lang/rust/issues/73201
Introduced in nightly-2020-05-22
by LLVM update https://github.com/rust-lang/rust/pull/67759, fixed in nightly-2020-06-08
by https://github.com/rust-lang/rust/pull/73072
Present in stable 1.45.0 and 1.45.1, fixed in beta 1.46.0.
Thanks a lot for investigating. I'll try out the Rust beta (which by now should contain the fix) next week and will report my findings.
I can confirm that I'm using the Arch Linux toolchain, not the one SiFive provides. So if the Rust beta does not fix the issue, I will try to change that and see if that helps.
Turns out that the behavior I saw before with ArchLinux toolchain is a different story... It worked like that long before May 2020. As for the issue described here, I can reproduce it with any toolchain I have.
Abstract
The binary that is flashed via the rust example is over 250MB large, too large for the target system. The C example does NOT suffer from this issue.
Reproduction
cd r-riscv-blink
cargo build --release
(although the issue also exists w/o the release flag)Technical Details
So while the input ELF (
r-riscv-blink
) has a somewhat expected size for an unstripped Rust program, the output binary (r-riscv-blink.bin
) is just huge. If we look at the ELF file:Nothing too large here (largest is
.text.dummy
with 256kB). However, what is bizzare is the following:This looks much better. Is the stack section somewhat broken? Version info: