Assembly 为什么获取某些链接器变量的地址会在使用LLVM的Rust中停止SAMD21的执行,而在使用GCC的C中则不会?
我想让我的Arduino MKRZero在生锈的地方工作。我成功地使LED闪烁,下一步是将全局数据从文本复制到数据 我定义了以下链接器变量: 生锈Assembly 为什么获取某些链接器变量的地址会在使用LLVM的Rust中停止SAMD21的执行,而在使用GCC的C中则不会?,assembly,arduino,linker,rust,Assembly,Arduino,Linker,Rust,我想让我的Arduino MKRZero在生锈的地方工作。我成功地使LED闪烁,下一步是将全局数据从文本复制到数据 我定义了以下链接器变量: 生锈 extern{ 静态uu堆栈顶部:u32; 静态mut_uuetext:u32; 静态mut uu数据u开始uu:u32; 静态多数据端:u32; 静态多机bss启动:u32; 静态mut uu bss uu end uuu:u32; } C extern uint32\u t\u etext; 外部uint32\u t\u数据\u启动\u; 外
extern{
静态uu堆栈顶部:u32;
静态mut_uuetext:u32;
静态mut uu数据u开始uu:u32;
静态多数据端:u32;
静态多机bss启动:u32;
静态mut uu bss uu end uuu:u32;
}
C
extern uint32\u t\u etext;
外部uint32\u t\u数据\u启动\u;
外部uint32\u t\u数据\u结束\u;
外部uint32\U t\U bss\U start\U;
外部uint32\u t\u bss\u end\u;
外部uint32_t____StackTop;
长话短说,锈迹代码
let mut pSrc:*mut u32;
pSrc=&mut\uu etext;
导致执行停止,即LED不闪烁。注释掉该行并继续执行将BSS段归零的代码
let mut pDest:*mut u32;
pDest=&mut\u bss\u start\u;
使闪烁代码正常工作。就我所见,获取链接器变量\uuu etext
的地址会停止执行,但是获取\uu bss\u start\uu
的地址是可以的
此版本的C版完全没有问题:
uint32_t *pSrc, *pDest;
pSrc = &__etext;
pDest = &__data_start__;
// <fill pDest with pSrc>
for (pDest = &__bss_start__; pDest < &__bss_end__; pDest++)
{
*pDest = 0;
}
请参阅每个中的build.sh
脚本,以准确查看命令的运行情况。
数据布局是从命令获取的
clang--target=thumbv6m none-eabi-S-emit llvm empty.c-o empty.ll
C代码的存储库是,Rust代码是。有问题的行是src/main.rs:38
我已经包括了arm none-eabi objdump-Cd的输出,用于1)C代码,2)带有注释错误行的Rust代码,以及3)运行错误行的Rust代码。然而,我无法很好地读取程序集,无法解析它来识别我的错误
我想我的下一步将是对C代码使用LLVM,而不是GCC,以查看这是否会导致任何问题,或者只是从Rust生成一个C库并在我的C main中调用它。在MKRZero上附加调试器将很困难,因此我可能不得不购买一个常规的zero或其他SAMD21断开板,并在其上进行尝试。您是否可以反汇编(arm which objdump-D)有问题的二进制文件,并显示链接器为这些链接器变量生成的特定值?如果我不得不猜测,这可能是因为Rust以某种方式验证指针,而超过.text
部分末尾的指针无效。我已使用与代码的arm none aebi objdump-CD
结果更新了存储库。
{
"llvm-target" : "thumbv6m-none-eabi",
"data-layout" : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
"linker" : "arm-none-eabi-gcc",
"pre-link-args" : [ "-nostartfiles", "-Tlayout.ld" ],
"target-endian" : "little",
"target-pointer-width": "32",
"arch" : "arm",
"os" : "none",
"executables" : true
}