有没有人知道为C应用程序创建一个可在微控制器(Cortex-M3)上运行的调用树的工具?它可以从源代码(非理想),目标代码(首选解决方案)或运行时(可接受)生成。我看过gprof,但是仍然有很多东西需要它才能在嵌入式系统上运行。
额外的好处是该工具还可以提供最大堆栈深度。
更新:解决方案最好是免费的。
答案 0 :(得分:4)
实现这一目标的一个好方法是使用属于RVCT(不 free)的ARM链接器(armlink)的--callgraph
选项。
有关详情,请callgraph documentation。
我从其中一条评论中意识到您正在寻找基于gcc的解决方案,但事实并非如此。但它可能仍然有用。
答案 1 :(得分:3)
从源代码中,即使您尚未使用Doxygen来记录代码,也可以使用Doxygen和GraphViz。可以对其进行配置,使其包含所有函数和方法,无论它们是否具有文档注释。安装AT& T Graphviz后,Doxygen将包含大多数功能和方法的调用和调用图。
从目标代码来看,我没有现成的答案。我认为这将是高度依赖于目标的,因为即使存在调试信息,它也必须解析目标代码以查找调用和其他堆栈用户。在最坏的情况下,这种方法似乎需要有效地模拟目标。
在目标硬件的运行时,您的选择将部分取决于存在哪种嵌入式操作系统,以及它如何管理每个线程的堆栈。
一种常见的方法是将每个堆栈初始化为似乎不太可能通常存储在自动变量中的已知值。然后,中断处理程序或线程可以检查堆栈并测量近似的高水位线。
即使没有预先填充堆栈并且稍后将其移动以寻找足迹,中断也可以仅对堆栈指针的当前值(对于每个线程)进行采样并保持其最大观察范围的记录。这将需要存储每个线程SP的副本,并且中断处理程序将不需要做很多工作来维护信息。当然,它必须访问所有活动线程的已保存状态。
我不知道有哪个工具明确地这样做。
如果您正在使用Micrium中的μC/ OS-II作为您的操作系统,您可以查看他们的μC/ Probe产品。我自己没有使用它,但它声称允许连接的PC近乎实时地观察程序和操作系统状态信息。如果需要它可以适应另一个RTOS,我不会感到惊讶。
答案 2 :(得分:3)
从源代码调用图表是没有问题的,如上面提到的编译器或doxygen可以从源代码生成此信息。大多数现代编译器都可以生成一个调用图,作为编译过程的一部分。
在以前的嵌入式项目中,我用一个模式填充了该堆栈并运行了一个任务。检查堆栈破坏我的模式的点。使用模式重新加载堆栈并运行下一个任务。这使你的代码非常ssslloowww ....但是是免费的。它并不完全准确,因为所有数据都在整个时间内超时,并且代码在错误处理程序中花费了大量时间。
在某些处理器上,您可以获得一个跟踪窗格,以便您可以监视代码封面,如果您的处理器需要全速运行以进行测试,那么您也可以监控代码封面,并且您也不能允许使用已检测的代码。不幸的是,这些类型的工具非常昂贵。如果你有钱,请看Green Hills Time machine。这使得所有类型的调试都更容易。
答案 3 :(得分:2)
我没有使用过这些,但你知道吗:
由于他们分析源代码,因此不会计算堆栈深度。
注意,Doxygen可以执行“调用图”和“调用图”,但我相信这些是按函数运行的,并且只显示每个函数中一定数量“跳”的树。
编译器工具可能支持堆栈深度和/或调用树生成。例如,对于Renesas micros,有一个名为Call Walker的实用程序。
答案 4 :(得分:2)
我的calltree图生成器,使用cscope和dot在bash中实现。
可以生成上游调用者,下游调用者和函数之间的调用关联的图形。您可以将其设置为以多种方式查看图形,包括xfig,.png查看器和动态点可视化工具“zgrviewer”。
http://toolchainguru.blogspot.com/2011/03/c-calltrees-in-bash-revisited.html
答案 5 :(得分:1)
答案 6 :(得分:1)
只是一个想法。是否可以在虚拟机(如Valgrind)中运行它并获取堆栈样本?
答案 7 :(得分:1)
它非常好用。
Visual Studio将执行类似操作(但它不是免费的)。我使用Visual Studio来处理嵌入式项目;使用makefile项目我可以完成除VS IDE中的调试之外的所有工作。
答案 8 :(得分:1)
我已经在another discussion中提出了关于嵌入式开发的这种方法,但如果你真的需要一个调用图,以及堆栈使用信息,以及所有这些免费,我个人会考虑使用开源模拟器来模拟整个事物,同时通过向模拟器本身添加一些钩子来检测目标代码,以获取此数据。
我不熟悉这个特定的目标,但是有大量的开源ARM仿真器可用(freshmeat,sourceforge,google),你可能最感兴趣的是与call / ret和push / pop相关的操作码? 例如,请查看skyeye。
因此,即使您发现扩展编译器或模拟器以提供此信息并不简单,仍应该可以创建一个简单的脚本来查找入口点和所有调用/ rets,以及作为与堆栈使用相关的操作码。
当然,关于堆栈使用的唯一可靠信息将来自运行时检测,最好是执行所有重要的代码路径。
答案 9 :(得分:0)
一个非常轻松的工具:Egypt
答案 10 :(得分:0)
答案 11 :(得分:-1)
我知道这是一个非常古老的问题,但有人可能会用同样的问题偶然发现这个......
我最近尝试了一个Python脚本,它分析应用程序的汇编程序版本,提取堆栈使用情况和调用树,并报告最大堆栈使用情况。在我的构建系统中,我然后使用它来创建一个完全相同大小的堆栈。
我只在小型应用程序中使用它,但它似乎适用于AVR8,MSP430和Cortex-M3。显然,存在严格的限制:没有间接调用(没有函数指针,没有虚函数),没有递归,使用堆栈的汇编程序指令模式仅限于我在GCC输出中找到的内容。如果不满足这些限制,脚本将报告错误。
Python源代码是24k,免费(增强版许可证),速度不是很快,而且还在开发中。如果您有兴趣,请与我联系。