Search code examples
assemblyrustriscv

No output out of llvm-objdump for rustc compiled RISC-V32IM binary


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?


Solution

  • 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.