When I compile following rust code:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
loop {}
}
fn mult(a: u32, b: u32) -> u32 {
return a * b;
}
#[no_mangle]
fn main() -> u32 {
return mult(3, 4);
}
via command
rustc --target riscv32i-unknown-none-elf -Ctarget-feature=+m -O simple.rs
and then run
llvm-objdump -d simple
I get following output without any instructions:
simple: file format ELF32-riscv
But when I do
rustc --target riscv32i-unknown-none-elf -Ctarget-feature=+m -O --emit asm simple.rs
and look into resulting simple.s
file I see:
.text
.attribute 4, 16
.attribute 5, "rv32i2p0_m2p0"
.file "simple.5d8cddf570d1dcfb-cgu.0"
.section .text.rust_begin_unwind,"ax",@progbits
.hidden rust_begin_unwind
.globl rust_begin_unwind
.p2align 2
.type rust_begin_unwind,@function
rust_begin_unwind:
.LBB0_1:
j .LBB0_1
.Lfunc_end0:
.size rust_begin_unwind, .Lfunc_end0-rust_begin_unwind
.section .text.main,"ax",@progbits
.globl main
.p2align 2
.type main,@function
main:
li a0, 12
ret
.Lfunc_end1:
.size main, .Lfunc_end1-main
.section ".note.GNU-stack","",@progbits
I have tried installing RISC-V GNU Toolchain and compiling similar C programs, then running llvm-objdump
and this way I got output with instructions as expected.
I have also tried to find in the binary these instructions present in simple.s
via their opcodes programmatically and to no avail.
What am I doing wrong? Why does disassembly differ from simple.s
? How do I get rustc to compile a binary with actual instructions?
The default linker script likely uses the symbol _start
as the program entry point, not main
. (I have not been able to verify this on a RISC-V target.) Legacy linker behavior if the _start
symbol is missing is to use the lowest text address instead (which is determined by section placement even if there is no code). Rust links with --gc-sections
, so the final binary does not contain your main
code even it is included in the assembly.
If I rename main
to _start
, I get some machine code in the output binary, but of course this is unlikely to work because the required initialization is missing.
The Rust RISC-V team suggests using the riscv-rt
crate and the [#entry]
macro.