如何阻止Rust为MIPS裸函数内联汇编自动追加break指令?
问题原因
你给裸函数内联汇编添加了options(noreturn),相当于告知Rust编译器该函数永远不会返回,编译器会默认在汇编块末尾插入不可达陷阱指令(MIPS平台对应break),避免执行流意外跑飞引发安全问题。你编写的汇编实际通过jr $ra正常返回,和noreturn的语义冲突,是额外指令生成的根本原因。你测试的Clang C代码没有额外指令,是因为Clang的naked函数语义不会主动在汇编块末尾插入不可达陷阱,和Rust的语义设计不同。
解决方案
方案1:移除noreturn选项(最推荐)
既然你的函数会正常返回,直接删除汇编选项里的noreturn即可,修改后的代码如下:
#[naked] pub unsafe extern "C" fn test() { asm!( ".set noreorder", "jr $ra", "li $v0, 0x123", ) }
修改后编译不会再生成额外的break指令,完全符合你的预期。
方案2:使用全局汇编(万能方案)
如果你的函数确实不需要返回,或者想要完全避免Rust对汇编内容做任何修改,可以改用全局汇编实现整个函数,Rust编译器不会对全局汇编的内容做任何插入或修改:
use core::arch::global_asm; // 直接用全局汇编定义整个函数 global_asm!( r#" .global test .type test, @function test: .set noreorder jr $ra li $v0, 0x123 .size test, . - test "# ); // 声明函数签名供Rust代码调用 extern "C" { fn test(); }
方案3:全局关闭不可达陷阱插入(不推荐)
如果需要保留noreturn语义,又不想插入陷阱,可以在你的自定义目标配置中添加LLVM参数全局关闭该特性:
{ // 原有配置不变,新增以下行 "llvm-args": ["-trap-unreachable=false"] }
该方案会全局关闭所有不可达位置的陷阱插入,可能降低其他代码的运行安全性,非必要不建议使用。
内容的提问来源于stack exchange,提问作者Filipe Rodrigues
相关产品推荐
相关产品推荐

