在开发以MCU为核心的嵌入式系统时,当软件程序向预设的数据结构(通常是一个固定长度的缓冲区)之外的程序调用堆栈的内存地址范围写入数据时,就会发生堆栈缓冲区溢出。这几乎必然会损坏附近的数据,甚至会改变返回函数。如果是有意为之,则这就是我们熟知的堆栈粉碎。防范堆栈缓冲区溢出的一种方法是使用堆栈canary,因其类似于在煤矿中使用金丝雀侦测毒气而得名。目前,在以IAR Embedded Workbench为代表的领先开发工具的所有最新版本中,均已支持堆栈保护功能。
堆栈保护功能已经成为最新嵌入式开发工具中必要的功能,但要在诸如IAR Embedded Workbench for Arm这样的行业标杆工具中实现堆栈保护,就要使用一种启发式算法来确认一个函数是否需要堆栈保护。如果任何函数内定义的局部变量为数组类型或包含数组类型成员的结构类型,则该函数就需要堆栈保护。此外,如果任何局部变量的地址被传播到函数之外,则该函数也需要堆栈保护。
如果一个函数需要堆栈保护,那么该函数的局部变量将被按序排放,将数组类型的变量在函数堆栈中被放置在尽可能高的地址。在这些变量之后,会放置一个canary元素。在函数入口处,canary被初始化。初始化值取自全局变量 __stack_chk_guard。在函数退出时,代码会验证canary元素是否仍然包含初始化值。如果该数值被改变,函数 __stack_chk_fail就会被调用。
以被广泛使用的IAR Embedded Workbench for Arm嵌入式开发工具为例,使用Project>Options>C/C++ Compiler>Code>Stack protection选项,即可针对被认定为需要保护的函数启用堆栈保护。
或者,您也可以使用Project>Options>C/C++ Compiler>Extra Options页面,指定 --stack_protection命令行来启用堆栈保护功能。
在实际应用实现堆栈保护
要使用堆栈保护,开发人员必须在应用中定义以下对象:
• extern uint32_t __stack_chk_guard
全局变量 __stack_chk_guard在第一次使用前必须被初始化。如果初始化值是随机的,则安全性会更高。
• __interwork __nounwind __noreturn void __stack_chk_fail(void)
__stack_chk_fail函数的作用是通知发生了错误,然后终止应用。请注意,这个函数的返回地址将指向失效函数。
armsrclibruntime目录下的文件stack_protection.c提供了 __stack_chk_guard和 __stack_chk_fail函数的参考模板。
总结
由于今天全球半导体供应链紧张状况尚未得到缓解,因此许多MCU等嵌入式应用需要利用开发工具来保持核心技术和器件供应上的灵活性,并最大限度地在不同硬件平台上重用已完成的软件。在这种情况下,无论是MCU芯片开发商还是嵌入式系统工程师,都需要利用那些已被业界最广泛使用的开发工具,如IAR Embedded Workbench for Arm。由于这些工具也是其开发商和行业领先的MCU供应商多年合作的成果,可以针对不同的硬件资源体系和应用环境给出相应的帮助,如IAR Embedded Workbench中的堆栈保护功能,因此可以以更短的研发周期,来实现嵌入式开发人员的研发目标。
关键字:嵌入式 开发工具 堆栈
引用地址:
如何利用现代嵌入式开发工具中的堆栈保护功能
推荐阅读最新更新时间:2024-11-21 07:32
研究人员确定最佳锂金属电池堆栈压力 显著提高性能
据外媒报道,一个由材料科学家和化学家组成的研究团队确定了锂金属电池(LMB)在电池运行期间需要承受的最佳堆栈压力,可产生最佳性能。该研究团队成员主要来自加州大学圣地亚哥分校(University of California San Diego)、密歇根州立大学(Michigan State University)、爱达荷州国家实验室(Idaho National Laboratory)和通用汽车研发中心(General Motors Research and Development Center)。 (图片来源:加州大学圣地亚哥分校) 用锂金属代替石墨做电池负极是部分电池研发领域的终极目标。这些锂金属电池将有可能把当前最
[汽车电子]
解决软件和硬件接口问题的嵌入式系统设计实例
解决软件和硬件接口问题的嵌入式系统设计实例 嵌入式系统设计中,软件和硬件的接口问题经常困扰软件开发工程师。正确理解接口在处理器与高级语言开发环境方面的约束条件,可以加速整个系统设计,并为改进系统的质量、性能和可靠性以及缩短开发周期和减少成本提供保证,本文从两个设计实例的比较入手,介绍了嵌入式系统的设计原则以及关于寄存器及其域的种种考虑。 嵌入式系统设计通常分为两个部分:硬件设计和软件开发。这两部分任务通常由不同的设计小组负责,相互间很少有覆盖的地方。由于软件小组很少涉足前面的硬件设计,采用这种方式进行开发经常会遇到问题,特别是硬件与软件开发环境之间的接口性能较差时,会导致系统开发时间延长、开发成本提高,最终推迟产品的上市。 最理
[嵌入式]
嵌入式驱动移植之IIC总线驱动移植
移植环境 主机开发环境:ubuntu12.04 BootLoader:u-boot-1.1.6 kernel:linux-2.6.30.4 CPU:s3c2440 开发板:TQ2440 移植步骤 在2.6.30.4 的内核中已经存在了 IIC 总线的驱动,只需要将其配置好,然后编译出内核镜像,就可以使用 IIC 总线了,在 TQ2440 中存在 IIC 总线的 EEPROM(AT24C02),可以通过对其的读写测试 IIC 总线是否驱动上。 1、配置内核 Device Drivers --- * I2C support --- --- I2C support * I2C device inter
[单片机]
Synopsys设计平台获得TSMC工艺认证,支持高性能7nm+工艺技术
Synopsys设计平台用于高性能、高密度芯片设计 重点: Synopsys设计平台获得TSMC工艺认证,支持高性能7-nm FinFET Plus工艺技术,已成功用于客户的多个设计项目。 针对7-nm FinFET Plus工艺的极紫外光刻技术,IC Compiler II 进行了专门的优化,进一步节省芯片面积。 采用TSMC的Wafer-on-Wafer®(WoW)技术,平台内全面支持多裸晶芯片堆叠集成,从而提高生产效率,加快实现大批量生产。 2018年5月10日,中国 北京——全球第一大芯片自动化设计解决方案提供商及全球第一大芯片接口IP供应商、信息安全和软件质量的全球领导者Synopsys(N
[嵌入式]
对堆栈8字节对齐问题的讨论
一.为什么要保证堆栈8字节对齐 AAPCS规则要求堆栈保持8字节对齐。如果不对齐,调用一般的函数也是没问题的。但是当调用需要严格遵守AAPCS规则的函数时可能会出错。 例如调用sprintf输出一个浮点数时,栈必须是8字节对齐的,否则结果可能会出错。 实验验证: #include stdio.h #include string.h float fff=1.234; char buf ; int main(void) { sprintf(buf, %.3f\n\r ,fff);//A while(1); } 1.在A处设置断点,让程序全速运行至A 2.在MDK中修改MSP的值使MSP满足8字节对齐 3.全速运行程序,观察buf中的字
[单片机]
Perst嵌入式数据库存储结构分析与研究
引言
Perst是McObject公司发布的一款非常袖珍的开源嵌入式数据库,是一个简单,快速,便捷,面向对象,适合java与.Net的数据库。Perst不需要专门的编译器与预处理器,支持ACID事务 。对于在资源受限的移动设备(如手机,PDA等)上存储大量数据和对数据进行频繁的I/O操作往往要消耗很多的设备资源。由于移动设备内存小,性能较差,如果采用关系数据库(如 SQLServer2000,Oracle)管理数据,仅靠其有限的内存资源是不能运行这些数据库管理系统的,这样就有必要采用一些特殊的数据库系统。 Perst数据库正是为这类设备研究开发的,它们是如何在资源受限的设备上完成大量数据的访问操作。其实这些设备的系统资源主
[嵌入式]
对话奇手科技CEO:AI为终端服务 关键是嵌入式
奇手科技CEO Sang Won Lee接受新浪科技专访 新浪科技 韩大鹏 华为从2015年开始就在旗舰机型上引入了指关节触控,即通过指关节敲击屏幕,可完成区域截屏、滚动截屏、录屏等复杂操作,而这项技术来自Qeexo奇手科技。近日,新浪科技对奇手科技CEO Sang Won Lee进行了专访。 已应用于华为OPPO等终端 “华为几乎所有中高端手机都搭载了FingerSense指关节技术”,Sang告诉新浪科技,这是全球首款能够识别指尖、指关节、指甲以及手写笔等不同触屏输入方式的软件解决方案,智能手机厂商可以通过植入该技术为用户提供更简便的交互体验,例如截屏功能、录屏工具,以及通过字母手势快速启动应用等。 此外,另一项Ea
[嵌入式]
嵌入式Linux操作系统的驱动程序开发要点
在Linux操作系统下有3类主要的设备文件类型:块设备、字符设备和网络设备。这种分类方法可以将控制输入/输出设备的驱动程序与其他操作系统软件分离开来。 字符设备与块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般紧接着发生。块设备则不然,它利用一块系统内存作为缓冲区,若用户进程对设备的请求能满足用户的要求,就返回请求的数据;否则,就调用请求函数来进行实际的I/O操作。块设备主要是针对磁盘等慢速设备设计的,以免耗费过多的CPU时间用来等待。网络设备可以通过BSD套接口访问数据。 每个设备文件都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有2个设备号,第一个是主设备号,标识驱动程序;第二个是
[应用]