使用Rust创建静态库以将其链接到arm-none-eabi C代码固件

4

我有一份现有的面向诺德克nRF52832 BLE微控制器的C语言固件。我想将自己用Rust编写的一些新代码链接到该固件上。

然而,当我尝试进行链接时,连接器会抱怨说我有两个不同定义的堆栈:

/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

我想这里重要的部分在于链接器告诉我,SDK Nordic为BLE微控制器提供了.stack_dummy,而Rust库提供了自己的栈定义。

实际上,我期望编译为库的代码不提供栈定义。如果所有库都定义栈,我将如何将它们链接到项目中呢?我的假设完全错误吗?

因此,我在想是否完全错误地定义了Rust库。

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"

代码随后使用cargo build --release --target thumbv7em-none-eabihf进行编译。

1个回答

3
看起来是在计算堆栈大小时,GCC和LLVM之间存在不兼容性。
`.stack_sizes` 部分包含LLVM堆栈元数据:llc -stack-size-section选项。这些似乎是函数指针和大小的一对,与.text部分的顺序相同(因此错误消息中有ordered)。
在GCC链接脚本中,我找到了以下内容(在Debian stretch上的/usr/share/doc/gcc-arm-none-eabi/examples/ldscripts/gcc.ld,您的可能会有所不同):
    /* .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")

GCC使用所需堆栈大小的虚拟节,并将它们以任何顺序放在`.stack_dummy`中,应该得到所需的总堆栈大小。因为`.stack_sizes`匹配`*(.stack*)`,所以GCC链接器尝试将LLVM节放在`.stack_dummy`中,但失败了。
因此,您可以尝试在Rust中禁用`-stack-size-section`,或修改链接器文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接