【ARM/RISCV 嵌入式 编译系列 16 -- GCC 进制优化编译的常用方法】

文章目录

方法一:给函数加 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 调试期可用 有副作用,慎用
相关推荐
xiaohua100928 分钟前
JVM内存优化-jemalloc
java·jvm
Escalating_xu1 小时前
【mmap 进程间通信】从共享内存到跨进程唤醒:用互斥锁、条件变量控制多个进程
java·linux·开发语言·jvm
雪落漂泊1 小时前
C++智能指针
开发语言·jvm·c++
落魄大学生之流水线上谋生计1 小时前
JVM内存结构、垃圾回收算法与类加载机制详解
jvm·算法
wuminyu2 小时前
Kafka配置TLS/SSL加密传输时零拷贝失效分析
java·linux·c语言·jvm·c++
0+11115 小时前
Linux --线程概念与控制
linux·运维·服务器·jvm
零依赖极客20 小时前
《30 天手搓 ARM 架构零依赖纯 C 推理引擎》课程介绍与大纲
c语言·开发语言·arm开发·人工智能·嵌入式硬件·ai编程
新时代牛马1 天前
ATF/ TEE / REE 与ARM 异常级别EL 安全体系完整篇:TrustZone硬件到 SMC 进OP-TEE的全链路
arm开发·python·安全
瀚高PG实验室1 天前
瀚高数据库V9.0.5数据脱敏完整配置步骤
jvm·数据库·postgresql·瀚高数据库
T1mzhou1 天前
ARM64 Linux 6.10 内核驱动(13):bus.c / driver.c 总线两张表,驱动怎么挂上去
linux·服务器·c语言·arm开发·arm