前言
2023年Zephyr开发者大会(ZDS)于6月27日至30日在捷克布拉格隆重举行。与以往两次不同,本次ZDS由Zephyr项目规划和管理,并作为首届嵌入式开源峰会(EOSS)的一部分进行。在这个令人期待已久的盛会中,全球Zephyr开发者们共同探讨了Zephyr实时操作系统(RTOS)的最新技术与发展趋势。作为一款开源、灵活和可扩展的嵌入式实时操作系统,Zephyr项目在2014年由英特尔发起,2016年作为Linux基金会项目正式面向公众启动,得到了全球范围内的广泛关注和采用。
ZDS 2023共70余个技术报告,涵盖了使用指导与展示、新功能与技术、架构修改与操作系统、多核异构与虚拟化、模拟器、测试、工业流程与代码管理、安全性、应用案例、工具与调试等丰富多样的内容。湖大嵌入式实验室的小伙伴们将对本次大会的所有技术报告进行逐一收集、整理与分享,尽最大努力为Zephyr开发者提供ZDS 2023技术报告的开发经验、实践成果以及解决方案的参考。
今天分享第66篇技术报告,由梅傲凌整理,题目为:
“利用编译器代码工具进行跟踪和分析”
作者简介
Gustavo Romero
一名自由和开放源码软件开发人员,拥有深厚的Linux背景,主要专注于内核和编译器开发、错误修复和性能。OpenJDK和Apache TVM贡献者。目前,工作重点是针对ARM MCU的Apache TVM ML编译器框架。
Kevin Townsend
嵌入式系统工程师,擅长基于Arm的系统、边缘/物联网安全、无线技术(BLE、802.15.4 等)和嵌入式软件设计。Zephyr RTOS的维护者:Arm Arch(32 位)、Trusted Firmware M Integration的维护者,以及zscilib(Zephyr 科学计算库)的作者。长期为嵌入式领域的多个开源项目做出贡献。
跟踪与分析是一种动态分析系统状态的行为,理论上,它们几乎可以捕获关于系统行为或状态的任何信息,就像它在现实生活/生产条件下运行一样——然而,它们会导致“观察者效应”,这意味着当你跟踪和剖析代码时也会影响运行时间。但是,如果设计和理解得当,这些干扰可能可以忽略不计。
动机
首先,我们希望跟踪和分析没有任何经济或者许可上的障碍,这个工作不依赖于额外的硬件,或专门的、昂贵的工具/软件(例如J-Link等)例如,我们也有gprof在 Zephyr 中的某些平台上运行,但因为平台限制,要在这些文件中获取时间戳很难。
我们想以非常低的级别和完整的方式显示内核或应用程序代码中的函数何时被调用。
我们想要拥有一个类似于Linux perf和ptrace的简单的CLI工具来进行跟踪和分析。
编译工具中的植入
GCC和Clang可以支持几种类型的代码工具,包括
最后,它们收集的数据我们几乎都可以用来进行跟踪分析。
其中,这里有两组有趣的flags。
这里第一组flag是该工具的功能和排除的相关标志文件和功能,第二组flag是补丁功能入口。
对于第一组中的 -finstrument-functions,GCC 差不多会在每个函数的入口和出口为其调用一种具体功能来处理程序所有功能中,那么有了这个机制,就可以使用利用它来设计跟踪。
Zephyr的工具子系统
跟踪方面
当调用网站上的某个函数时,一个钩子将被调用,并且它的参数将是这个函数,它的地址表示从何处调用。有了这些,我们就可以在Zyphyr上设计工具子系统。
我们决定对环形缓冲区进行跟踪。主要是两种工作模式,一种工作模式是一个跟踪缓冲区,一旦监听停止,全部停止追踪。而另一种工作模式就像环形缓冲区,让您可以继续监听活动,但最久远的活动将会删除,我们只保留最新的活动,所以很像一个环形缓冲器。
分析方面
当函数被调用(“已发现”)时,每个函数和以及差异都会记录一个时间戳。值在函数退出时计算,并累积每个函数启发式来摒弃函数和函数的空闲空间(按名称、调用次数等)。
我们在多个事件与缓冲区大小之间进行了平衡:
数据传输方面
我们仍然采用同步的方式,但我们确实希望同时以异步和同步模式来使用不同的频道。例如SWD(臂专用),USB,以太网。这些设备可广泛使用,而且有更宽的带宽。
如何启动Zephyr的工具子系统?
①向prj.conf中添加以下配置
②为保留子系统boards/<board>.overlay定义一个新的DT节点
打开工具子系统后产生的影响如下图所示:
Zaru的介绍:zephyr工具子系统的CLI工具
名称:zaru ,类似于strainer(一种用于过滤或排水的工具)。
使用Python编写。
使用CTF元数据和libbabeltrace2以及Python3绑定。
命令包括:status, reboot, trace, 和 profile。
后端包括:控制台/文本,Perfetto,PDF等。
数据可视化的示例
Perfetto,这是一个在Android环境下非常常见的GUI,下面是Perfetto输出的一个示例。
我们想用perfetto显示我们在Zephyr中添加的类似于Linux中的ftrace的功能。
动态功能工具(DFI)
我们可以开始使用动态工具,这是非常有趣又具有实验性的工作。我们的想法是不在编译时生成钩子,而是在运行时完全(比如JIT),编译器只在函数的序言处添加给定的空间。这样一来运行时开销更少,仅为特定的函数启用,同时生成的代码可以非常灵活,甚至从主机生成并根据需要注入到目标,这对于跟踪函数很有用。
缺点:我们只是修补了函数的入口而没有修补出口,这意味着我们需要调整堆栈和堆栈中的返回地址以允许正确返回钩子。
我们在代码中实现了某种汇编程序。
然后为了测试它,我们创建了一个简单的函数。
以下是未进行修补的函数。
以下是已经进行修补的函数。
现在这个函数将在入口和返回处调用钩子。