文章目录
-
-
- [方法一:给函数加 attribute((used)) 强制保留](#方法一:给函数加 attribute((used)) 强制保留)
- [方法二:加 attribute((section(".text.jump"))) + 链接脚本强制放入](#方法二:加 attribute((section(".text.jump"))) + 链接脚本强制放入)
- 方法三:关闭函数优化和链接时清除未使用代码
- 如果是纯汇编写的(`.S`)
- [最强一招:使用 `KEEP()` 保留段内所有代码](#最强一招:使用
KEEP()
保留段内所有代码) - 验证跳转函数是否真的保留
- 总结
-
方法一:给函数加 attribute((used)) 强制保留
如果你是用 C 写的(而不是纯汇编),这样做可以让函数即使没被调用也不被优化掉:
c
__attribute__((used))
void jump_to_ilm() {
asm volatile (
"lui t0, 0x60000\n"
"jr t0\n"
);
}
方法二:加 attribute((section(".text.jump"))) + 链接脚本强制放入
c
__attribute__((used, section(".text.jump")))
void jump_to_ilm() {
asm volatile (
"lui t0, 0x60000\n"
"jr t0\n"
);
}
并在链接脚本中加入:
ld
.text : {
KEEP(*(.text.jump))
*(.text)
}
方法三:关闭函数优化和链接时清除未使用代码
在编译时使用以下选项:
bash
riscv64-elf-gcc -O0 -Wl,--whole-archive -Wl,--no-gc-sections ...
或者最少加 -Wl,--gc-sections
时配合 KEEP()
保住关键段落。
如果是纯汇编写的(.S
)
确保该跳转代码出现在 _start
或其他被链接器引用的地方,否则链接器仍可能把你 .text
中的符号扔掉。
例如:
assembly
.section .text
.globl _start
_start:
lui t0, 0x60000
jr t0
_start
是入口符号,必须通过链接脚本 ENTRY(_start)
指定入口,否则编译器也可能不处理。
最强一招:使用 KEEP()
保留段内所有代码
在链接脚本中:
ld
.text : {
KEEP(*(.text.boot))
KEEP(*(.text.jump))
*(.text*)
}
只要你把函数放进 .text.jump
,它就不会被优化掉了。
验证跳转函数是否真的保留
你可以用 objdump
检查 ELF 文件:
bash
riscv64-elf-objdump -d bootrom.elf | less
确认是否有类似:
php-template
60000000 <_ilm_main>:
...
总结
方法 | 适用情况 | 是否推荐 |
---|---|---|
__attribute__((used)) |
写在 C 代码中 | 推荐 |
KEEP() + section |
写在链接脚本 + C/汇编都适用 | 强力推荐 |
直接放在 _start 中 |
简单项目 | 推荐 |
关闭优化(-O0 , --no-gc-sections ) |
调试期可用 | 有副作用,慎用 |