简体   繁体   中英

Creating a static library with Rust to link it to an arm-none-eabi C code firmware

I have an existing C firmware for a Nordic nRF52832 BLE microcontroller. I'd like to link some new code to it, that I wrote in Rust.

When I try to do so, the linker complains that I have two different definitions of the stack:

/nix/store/m7gf0nzixwgqk21an0fxc047qa0mvbng-gcc-arm-embedded-7-2018-q2-update/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: .stack_dummy has both ordered [`.stack_sizes' in /home/matthias/source/tbconnect/modem/target/thumbv7em-none-eabihf/release/libtbmodem.a(alloc-314aba8dbd2706e9.alloc.deuukmti-cgu.0.rcgu.o)] and unordered [`.stack' in .sdk/modules/nrfx/mdk/gcc_startup_nrf52.o] sections

I guess the important part here is that the linker tells me that there is a .stack_dummy in the SDK Nordic provides for the BLE microcontroller, and the Rust library provides its own definition of a stack.

Actually I would expect, that code compiled as a library, does not provide a definition of a stack. How would I link several libraries into a project if all of them define a stack? Am I completely wrong with that assumption?

So I'm wondering whether I'm completely wrong in my definition of the Rust library.

Cargo.toml:

[package]                                                                        
name = "tbmodem"                                                                 
version = "0.1.0"                                                                                          
edition = "2018"                                                                 
publish = false                                                                  

[lib]                                                                            
crate-type = ["staticlib"]                                                       

[profile.dev]                                                                    
panic = "abort"                                                                  

[profile.release]                                                                
panic = "abort"                                                                  

[dev-dependencies]                                                               
timebomb = "0.1.2"

The code then gets compiled with cargo build --release --target thumbv7em-none-eabihf

It looks like an incompatibility between GCC and LLVM when computing stack sizes.

The .stack_sizes section contains LLVM stack metadata: llc -stack-size-section option . These seem to be pairs of function pointers and sizes in the same order as the .text sections (hence the ordered in the error message).

In a GCC linker script I find ( /usr/share/doc/gcc-arm-none-eabi/examples/ldscripts/gcc.ld on Debian stretch, yours may or may not look different):

    /* .stack_dummy section doesn't contains any symbols. It is only
     * used for linker to calculate size of stack sections, and assign
     * values to stack symbols later */
    .stack_dummy (COPY):
    {
            *(.stack*)
    } > RAM

    /* Set stack top to end of RAM, and stack limit move down by
     * size of stack_dummy section */
    __StackTop = ORIGIN(RAM) + LENGTH(RAM);
    __StackLimit = __StackTop - SIZEOF(.stack_dummy);
    PROVIDE(__stack = __StackTop);

    /* Check if data + heap + stack exceeds RAM limit */
    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")

So GCC uses dummy sections with the required stack sizes, and putting them together in .stack_dummy in any order should result in the total stack size needed. Because .stack_sizes matches *(.stack*) , the GCC linker tries to put the LLVM sections in .stack_dummy , but that fails.

So you can either try to disable -stack-size-section in Rust, or modify the linker file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM