91、【OS】【Nuttx】【启动】栈溢出保护:配置项添加
【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
接之前 blog
【OS】【Nuttx】【启动】栈溢出保护:配置项解析
分析了栈溢出保护配置项的一些内容,还有些没讲,下面补充完
ARMV7M_STACKCHECK
还是这张图,下面分析 help 里面内容,来看下栈溢出保护的一些细节
- 这个栈溢出检测机制使用了寄存器 R10 来保存栈底边界地址,注意这里的限定场景是 ARMV7M,如果换了个架构,可能就不一样了,另外,为什么选 R10 寄存器,之前 blog 【OS】【Nuttx】【启动】栈溢出保护:r10 寄存器 已经分析过
- 每次函数调用时,都会检查当前栈指针 SP 是否低于栈底边界值,以判断是否发生栈溢出,也就是之前经常画的这个图
- 启用此功能后,编译器会在每个函数入口和出口插入检测代码,会带来一些副作用,比如性能下降(因为每次函数调用都要检查),代码体积变大(插入了额外的汇编指令)
- 当前只支持如下平台:
STM32(意法半导体 Cortex-M 系列)
SAM3/4(Microchip 的 Cortex-M 系列)
SAMA5D(Microchip 的 ARM926EJ-S 平台)
这个功能的实现不复杂,鼓励开发者为其他平台提交补丁(基本要用内联汇编写,需要精通对应系列芯片架构) - 必须使用 gcc 工具链,并且要添加两个编译选项:
-finstrument-function:编译器在每个函数入口和出口插入自定义代码(用于栈溢出检查逻辑)
-ffixed-r10:告诉编译器不要使用 r10 寄存器,避免被编译器优化或破坏掉
配置项添加
在 bash 终端输入
./configure menuconfig
之前 blog 【OS】【Nuttx】【构建】配置 stm32 工程 讲过如何配置 configure 脚本。 如果没有配置 configure 脚本,在 nuttx 工程目录下用 make menuconfig 也是一样的
找到配置项 ARMV7M_STACKCHECK(上篇 blog 【OS】【Nuttx】【启动】栈溢出保护:配置项解析 已经介绍过)
按 Y 可勾选该配置项,可以发现还出来个子项(是否在栈溢出时打断点),现在先不分析这么多
点击保存,配置项会落入 .config 文件中
在 Nuttx 根目录下,bash 终端输入
make savemenuconfig
可生成配置文件 defconfig,可以看到 defconfig 配置文件中生成了配置项 ARMV7M_STACKCHECK
这里有点尴尬,因为是用的 make 配置操作的,但工程是用 cmake 构建的,配合上有点问题,下篇 blog 再讲下这里
编译选项添加
在 armv7-m_gcc.cmake 文件中,有两个编译选项被添加的过程
这里有两个点讲下:
- list(APPEND …):cmake 命令,用于向一个列表变量(这里是 PLATFORM_FLAGS)的末尾追加元素,这里追加的是编译选项
- add_compile_options: cmake 命令,用于将指定的编译器选项添加到当前 CMakeLists.txt 文件及其所有子目录中定义的目标,是全局性的,影响后续所有目标;它还有个兄弟 target_compile_options 命令,target_compile_options 是目标特定的,只影响明确指定的那个目标,这里添加的是 PLATFORM_FLAGS,属于平台编译选项,用全局性的 add_compile_options 也是比较合适的
今天先分析到这里,下篇 blog 分析上面那个问题,如何用 cmake 进行配置项添加