嵌入式软件的调用树

11

有没有人知道一些能够为运行在微控制器 (Cortex-M3) 上的 C 应用程序创建调用树的工具?可以从源代码(不是理想的解决方案)、目标代码(首选解决方案)或运行时(可接受)生成。我已经查看了 gprof,但仍然有很多东西缺失,无法在嵌入式系统上运行。

额外的好处是,该工具还能够给出最大堆栈深度。

更新:最好是免费的解决方案。

12个回答

5
一种实现这个目标的好方法是使用 ARM 链接器 (armlink),并使用其中的 --callgraph 选项 (RVCT 的一部分,非免费)。
更多细节请查看 - 调用图文档
我从评论中了解到您正在寻找基于 gcc 的解决方案,但这可能仍然有所帮助。

4
从源代码中,即使您没有使用Doxygen来记录代码,您也可以使用DoxygenGraphViz。可以配置它以包括所有函数和方法,无论它们是否有文档注释。安装AT&T Graphviz后,Doxygen将为大多数函数和方法包括调用和调用者图形。
对于目标代码,我没有一个准备好的答案。我想这将高度依赖于目标,因为即使有调试信息,它也必须解析目标代码以查找调用和其他堆栈用户。在最坏的情况下,这种方法似乎需要有效地模拟目标。
在目标硬件上运行时,您的选择部分取决于嵌入式操作系统的类型以及它如何为每个线程管理堆栈。
常见的方法是将每个堆栈初始化为已知值,该值似乎不太可能存储在自动变量中。然后,中断处理程序或线程可以检查堆栈并测量近似高水位标记。
即使不预先填充堆栈并稍后遍历以查找足迹,中断也可以只对堆栈指针的当前值进行采样(对于每个线程),并记录其最大观察范围。这将需要存储每个线程SP的副本,并且中断处理程序不需要太多工作来维护信息。当然,它必须访问所有活动线程的保存状态。我不知道有没有这样的工具。如果您恰好正在使用Micrium的µC/OS-II作为操作系统,您可以看一下他们的µC/Probe产品。我自己没有使用过它,但它声称允许连接的PC几乎实时地观察程序和操作系统状态信息。如果需要,我不会感到惊讶它能够适应其他实时操作系统。

4

如上所述,从源代码生成调用图对于您的编译器或doxygen来说并不是问题。大多数现代编译器可以在编译过程的一部分中生成调用图。

在以前的嵌入式项目中,我使用一个模式填充了堆栈并运行了一个任务。检查堆栈破坏我的模式的程度。重新加载带有模式的堆栈并运行下一个任务。这会使您的代码非常缓慢...但是是免费的。它不是完全准确的,因为所有数据都会超时,代码会花费大量时间在错误处理程序中。

在某些处理器上,您可以获取跟踪探针,以便监视代码覆盖率等内容,如果您的处理器需要以全速运行进行测试,并且您也不能使用插装代码。不幸的是,这些类型的工具非常昂贵。如果您有足够的资金,请看看Green Hills Time machine。这将使各种调试更加容易。


2

好的建议,当然我在问题中忘记加上“最好是免费”的条件了。看起来他们没有将ARM/gcc列为支持的组合,但是再说一遍,elf文件就是elf文件,所以我会联系他们并询问它是否可以工作。 - Ron
他们确实声称支持ARM elf。我非常确定GCC和ARM自己的编译器使用相同的ABI,所以似乎很可能可以工作。另一个问题可能是对thumb模式的支持,因为Cortex系列实际上只启用了thumb模式。 - RBerteig
支持,让我知道GCC不受支持,但可以支付额外费用包含它。给您提供数字并不在我的职权范围内,但这绝对不是免费的。 - Ron

2

我没有使用过这些工具,但你知道吗:

由于它们分析源代码,所以它们不会计算堆栈深度。

请注意,Doxygen可以生成“调用图”和“调用者图”,但我认为这些仅针对每个函数,并且仅显示从每个函数到某个“跳数”的树。

编译器工具可能支持堆栈深度和/或调用树生成。例如,对于瑞萨微控制器,有一个名为Call Walker的实用程序。


2

1

只是一个想法。能否在虚拟机中运行它(如Valgrind),并获取堆栈样本?


1

Eclipse with CDT具有C/C++索引并将显示调用图。 据我所知,您不需要能够在Eclipse中构建才能使索引器工作,只需确保所有源文件都在项目中即可。

它的效果相当好。

Visual Studio也可以做类似的事情(但它不是免费的)。 我使用Visual Studio开发嵌入式项目; 使用一个makefile项目,除了在VS IDE中进行调试外,我可以完成所有工作。


1

我已经在关于嵌入式开发的另一个讨论中建议过这种方法,但如果你真的需要一个调用图,以及堆栈使用信息,并且所有这些都是免费的,我个人会考虑使用开源仿真器来模拟整个过程,同时通过向仿真器本身添加一些钩子来对目标代码进行仪器化,以获取这些数据。

我不熟悉这个特定的目标,但有很多开源ARM仿真器可用(freshmeat、sourceforge、google),你可能主要感兴趣的是与调用/返回和推/弹相关的操作码?例如,看看skyeye

因此,即使你发现扩展编译器或仿真器以提供此信息并不直接,仍然可以创建一个简单的脚本来查找入口点和所有调用/返回,以及与堆栈使用相关的操作码。

当然,关于堆栈使用的唯一可靠信息将来自运行时仪器化,最好是练习所有重要的代码路径。


0

使用 Understand: http://www.scitools.com/

它不是免费的,需要在源代码上运行,但它工作得很好,支持也很好。

它可以告诉你比你想知道的更多关于你的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接