11

有谁知道一些工具可以为将在微控制器(Cortex-M3)上运行的 C 应用程序创建调用树?它可以从源代码(不理想)、目标代码(首选解决方案)或运行时(可接受)生成。我看过 gprof,但仍然缺少很多东西要让它在嵌入式系统上工作。

一个额外的好处是该工具还提供了最大的堆栈深度。

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

4

12 回答 12

5

实现此目的的一种好方法是使用--callgraphARM 链接器 (armlink) 的选项,它是 RVCT 的一部分(不是免费的)。

有关更多详细信息 - callgraph 文档

我从其中一条评论中意识到您正在寻找基于 gcc 的解决方案,但事实并非如此。但它可能仍然有帮助。

于 2009-06-11T04:44:33.393 回答
4

从源代码中,您可以使用DoxygenGraphViz,即使您还没有使用 Doxygen 来记录您的代码。可以对其进行配置,使其包含所有功能和方法,无论它们是否具有文档注释。安装 AT&T Graphviz 后,Doxygen 将包含大多数函数和方法的调用图和调用者图。

从目标代码中,我没有现成的答案。我想这将是高度依赖于目标的,因为即使存在调试信息,它也必须解析目标代码以查找调用和其他堆栈用户。在最坏的情况下,这种方法似乎需要有效地模拟目标。

在目标硬件上运行时,您的选择将部分取决于存在哪种嵌入式操作系统,以及它如何管理每个线程的堆栈。

一种常见的方法是将每个堆栈初始化为一个已知值,该值似乎不太可能通常存储在自动变量中。然后中断处理程序或线程可以检查堆栈并测量近似的高水位线。

即使没有预先填充堆栈并随后遍历堆栈以查找足迹,中断也可以仅对堆栈指针的当前值(对于每个线程)进行采样并记录其最大观察范围。这将需要存储每个线程 SP 的副本,并且中断处理程序不需要做太多工作来维护信息。当然,它必须访问所有活动线程的已保存状态。

我不知道有什么工具可以明确地做到这一点。

如果您碰巧使用Micrium的 µC/OS-II作为您的操作系统,您可以看看他们的 µC/Probe 产品。我自己没有使用过它,但它声称允许连接的 PC 近乎实时地观察程序和操作系统状态信息。如果需要的话,如果它可以适应另一个 RTOS,我不会感到惊讶。

于 2009-06-11T01:09:54.797 回答
4

如上所述,来自源代码的调用图没有问题,您的编译器或 doxygen 可以从源代码生成此信息。大多数现代编译器可以生成调用图作为编译过程的一部分。

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

在某些处理器上,您可以获得一个跟踪 pod,以便您可以监控代码覆盖率,如果您的处理器需要全速运行以进行测试,并且您也不能使用检测代码,那该怎么办。不幸的是,这些类型的工具非常昂贵。如果你有钱,看看Green Hills Time machine 。这使得所有类型的调试都更容易。

于 2009-06-11T09:15:17.307 回答
2

我的调用树图形生成器,用 bash 实现,使用 cscope 和 dot。

可以生成上游调用者、下游调用者以及函数之间的调用关联的图表。您可以将其设置为以多种方式查看图形,包括 xfig、.png 查看器和动态点可视化工具“zgrviewer”。

http://toolchainguru.blogspot.com/2011/03/c-calltrees-in-bash-revisited.html

于 2011-03-02T17:18:29.620 回答
2

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

由于他们分析源代码,因此他们不计算堆栈深度。

请注意,Doxygen 可以做“调用图”和“调用者图”,但我相信这些是每个函数,并且只显示每个函数的特定数量的“跳跃”树。

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

于 2009-06-14T01:47:28.667 回答
2

查看StackAnalyzer

于 2009-06-11T00:07:30.727 回答
1

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

于 2009-06-11T00:33:35.447 回答
1

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

我不熟悉这个特定的目标,但是有很多可用的开源 ARM 模拟器(freshmeat、sourceforge、google),您可能最感兴趣的是与 call/ret 和 push/pop 相关的操作码?例如查看skyeye

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

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

于 2009-06-14T02:37:22.837 回答
1

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

它工作得很好。

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

于 2009-06-14T02:07:32.283 回答
0

一个很轻的工具:埃及

于 2011-02-27T12:37:00.783 回答
0

使用了解:http ://www.scitools.com/

它不是免费的,并且在源代码(而不是运行时)上运行,但它可以运行,运行良好,并且得到很好的支持。

它会告诉你比想知道你的代码更多的信息。

于 2011-09-23T18:04:13.307 回答
-1

我知道这是对一个非常古老的问题的回应,但有人可能会偶然发现这个问题......

我最近试验了一个 Python 脚本,它分析应用程序的汇编版本,提取堆栈使用情况和调用树,并报告最大堆栈使用情况。然后在我的构建系统中,我使用它来创建一个完全相同大小的堆栈。

我只将它用于小型应用程序,但它似乎适用于 AVR8、MSP430 和 Cortex-M3。显然,有严格的限制:没有间接调用(没有函数指针,没有虚函数),没有递归,并且使用的堆栈使用汇编程序指令模式仅限于我在 GCC 的输出中找到的内容。如果不满足这些限制,脚本将报告错误。

Python 源代码为 24k,免费(增强许可证),速度不是很快,仍在开发中。如果您有兴趣,请与我联系。

于 2016-04-29T19:34:35.477 回答