We don’t allow questions seeking recommendations for software libraries, tutorials, tools, books, or other off-site resources. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(12)
实现此目的的一个好方法是使用 ARM 链接器 (armlink) 的
--callgraph
选项,该链接器是 RVCT 的一部分(不是免费)。有关更多详细信息 - 调用图文档。
我从其中一条评论中意识到您正在寻找基于 gcc 的解决方案,但这不是。 但它可能仍然有帮助。
One good way to achieve this is by using the
--callgraph
option to the ARM linker (armlink) that is part of RVCT (not free).For more details - callgraph documentation.
I realize from one of the comments that you are looking for a gcc-based solution, which this isn't. But it may still be helpful.
从源代码中,您可以使用 Doxygen 和 GraphViz 即使您尚未使用 Doxygen 来记录代码。 可以对其进行配置,使其包含所有函数和方法,无论它们是否有文档注释。 安装 AT&T Graphviz 后,Doxygen 将包含大多数函数和方法的调用和调用者图。
从目标代码来看,我没有现成的答案。 我想这将高度依赖于目标,因为即使存在调试信息,它也必须解析目标代码以查找调用和其他堆栈用户。 在最坏的情况下,这种方法似乎需要有效地模拟目标。
在目标硬件上运行时,您的选择将部分取决于存在哪种类型的嵌入式操作系统,以及它如何管理每个线程的堆栈。
一种常见的方法是将每个堆栈初始化为一个已知值,该值似乎不太可能通常存储在自动变量中。 然后,中断处理程序或线程可以检查堆栈并测量近似的高水位线。
即使没有预先填充堆栈并随后遍历它来查找足迹,中断也可以仅对堆栈指针的当前值(对于每个线程)进行采样,并保留其最大观察范围的记录。 这将需要存储每个线程 SP 的副本,并且中断处理程序不需要做太多工作来维护信息。 当然,它必须访问所有活动线程的已保存状态。
我不知道有什么工具可以明确执行此操作。
如果您碰巧使用 Micrium 的 µC/OS-II 作为操作系统,您可以看看他们的 µC/Probe 产品。 我自己没有使用过它,但它声称允许连接的 PC 近乎实时地观察程序和操作系统状态信息。 如果需要的话,如果它能够适应另一个实时操作系统,我不会感到惊讶。
From source code, you can use Doxygen and GraphViz even if you don't already use Doxygen to document your code. It is possible to configure it so that it will include all functions and methods whether or not they have documentation comments. With AT&T Graphviz installed, Doxygen will include call and caller graphs for most functions and methods.
From object code, I don't have a ready answer. I would imagine that this would be highly target dependent since even with the debug information present, it would have to parse the object code to find calls and other stack users. In the worst case, that approach seems like it would require effectively simulating the target.
At runtime on the target hardware your choices are going to depend in part on what kind of embedded OS is present, and how it manages stacks for each thread.
A common approach is to initialize each stack to a known value that seems unlikely to be commonly stored in automatic variables. An interrupt handler or a thread can then inspect the stack(s) and measure an approximate high water mark.
Even without pre-filling the stack and later walking it to look for footprints, an interrupt could just sample the current value of the stack pointer (for each thread) and keep a record of its greatest observed extent. That would require storage for a copy of each threads SP, and the interrupt handler wouldn't have very much work to do to maintain the information. It would have to access the saved states of all the active threads, of course.
I don't know of a tool that does this explicitly.
If you happen to be using µC/OS-II from Micrium as your OS, you might take a look at their µC/Probe product. I haven't used it myself, but it claims to allow a connected PC to observe program and OS state information in near real time. I wouldn't be surprised if it is adaptable to another RTOS if needed.
源代码中的调用图没有问题,如上所述,您的编译器或 doxygen 可以从源代码中生成此信息。 大多数现代编译器可以生成调用图作为编译过程的一部分。
在之前的嵌入式项目中,我用一个模式填充了该堆栈并运行了一个任务。 检查堆栈到哪一点破坏了我的模式。 使用模式重新加载堆栈并运行下一个任务。 这使得你的代码非常ssslloowww ....但是是免费的。 它并不完全准确,因为所有数据一直在超时,并且代码在错误处理程序中花费了大量时间。
在某些处理器上,您可以获得跟踪容器,以便可以监视代码覆盖率,如果您的处理器需要全速运行来测试并且您也不能使用检测代码,那么又会怎样呢? 不幸的是,这些类型的工具非常昂贵。 如果你有钱的话,看看Green Hills Time machine。 这使得所有类型的调试变得更加容易。
Call graphs from source code is no problem as mentioned above your compiler or doxygen can generate this information from source code. Most modern compilers can generate a call graph as part of the compile process.
On a previous embedded projects I filled that stack with a pattern and ran a task. Check up to which point the stack destroyed my pattern. Reload stack with pattern and run the next task. This makes your code very ssslloowww .... but is free. It is not fully accurate because all the data is timing out the whole time and the code spends lots of time in error handlers.
On some processors you can get a trace pod so that you can monitor code cover and what not if your processor needs to run at full speed to test and you can also not use instrumented code. Unfortunately these types of tools are very expensive. Look at Green Hills Time machine if you have money. This make all types of debugging easier.
查看StackAnalyzer。
Check out StackAnalyzer.
我没有使用过这些,但是你知道吗:
calltree
cflow
由于他们分析源代码,因此他们不计算堆栈深度。
请注意,Doxygen 可以执行“调用图”和“调用者图”,但我相信这些是每个函数的,并且仅显示每个函数的树到一定数量的“跳跃”。
编译器工具可以支持堆栈深度和/或调用树生成。 例如,对于 Renesas micros,有一个名为 Call Walker。
I haven't used these, but are you aware of:
calltree
cflow
Since they analyse the source code, they don't calculate stack depth.
Note, Doxygen can do "call graphs" and "caller graphs" but I believe these are per-function and only show the tree up to a certain number of "hops" from each function.
Stack depth and/or call tree generation may be supported by compiler tools. For example, for Renesas micros there is a utility called Call Walker.
我的调用树图生成器,在 bash 中使用 cscope 和 dot 实现。
可以生成上游调用者、下游被调用者以及函数之间的调用关联的图表。 您可以将其设置为以多种方式查看图形,包括 xfig、.png 查看器和动态点可视化工具“zgrviewer”。
http://toolchainguru.blogspot.com/2011/03 /c-calltrees-in-bash-revisited.html
My calltree graph generator, implemented in bash, using cscope and dot.
Can generate graphs of upstream callers, downstream callees, and call-associations between functions. You can set it up to view graphs in a number of ways, including xfig, .png viewers, and the dynamic dot visualiztion tool "zgrviewer".
http://toolchainguru.blogspot.com/2011/03/c-calltrees-in-bash-revisited.html
只是一个想法。 是否可以在虚拟机(如 Valgrind)中运行它并获取堆栈样本?
Just a thought. Is it possible to run it in a virtual machine (like Valgrind) and take stack samples ?
带有 CDT 的 Eclipse 具有 C/C++ 索引,并将向您显示调用图。 据我所知,您不需要能够在 Eclipse 中构建以使索引器正常工作,只需确保所有源文件都在项目中即可。
它工作得非常好。
Visual Studio 也会做类似的事情(但它不是免费的)。 我使用 Visual Studio 来处理嵌入式项目; 使用 makefile 项目我可以完成除了在 VS IDE 中调试之外的所有工作。
Eclipse with CDT has C/C++ indexing and will show you a call graphs. As far as I know, you don't need to be able to build in Eclipse to get the indexer to work, just make sure all your source files are in the project.
It works pretty nicely.
Visual Studio will do similar (but it's not free). I use Visual Studio to work on embedded projects; using a makefile project I can do all the work except debugging in the VS IDE.
我已经在关于嵌入式开发的另一个讨论中建议了这种方法,但是如果您确实需要调用图以及堆栈使用信息,并且所有这些都是免费的,我个人会考虑使用开源模拟器来模拟整个过程,同时通过向模拟器本身添加一些钩子来检测目标代码得到这个数据。
我不熟悉这个特定的目标,但是有大量可用的开源 ARM 模拟器(freshmeat、sourceforge、google),并且您可能最感兴趣的是与 call/ret 和 push/pop 相关的操作码?
例如,查看 skyeye。
因此,即使您发现扩展编译器或模拟器来提供此信息并不简单,仍然应该可以创建一个简单的脚本来查找入口点和所有调用/rets,以及相关的操作码堆栈使用。
当然,有关堆栈使用情况的唯一可靠信息将来自运行时检测,最好是执行所有重要的代码路径。
I have suggested this approach already in another discussion about embedded development, but if you really need a callgraph, as well as stack use info, and all this for free, I would personally consider using an open source emulator to simulate the whole thing, while instrumenting the object code by adding a handful hooks to the emulator itself to get this data.
I am not familiar with this particular target, but there is a whole number of open source ARM emulators available (freshmeat, sourceforge, google), and you are probably mostly interested in opcodes related to call/ret and push/pop?
For example check out skyeye.
So, even if you find that it's not straightforward to extend a compiler or an emulator to provide this information, it should still be possible to create a simple script in order to look for the entrypoint and all calls/rets, as well as opcodes related to stack usage.
Of course, the only reliable information on stack usage is going to come from runtime instrumentation, preferably exercising all important code paths.
一个非常轻便的工具:Egypt
A pretty light tool: Egypt
使用理解: http://www.scitools.com/
它不是免费的,并且在源代码上运行(不是运行时),但是它有效,工作良好,并且得到了很好的支持。
它会告诉你比你想了解的更多的代码。
Use Understand: http://www.scitools.com/
It's not free, and runs on source (not runtime), but it works, it works well, and it's well supported.
It will tell you much more than could ever want to know about your code.
我知道这是回答一个非常古老的问题,但有人可能会偶然发现同样的问题...
我最近尝试了一个 Python 脚本,它分析应用程序的汇编版本,提取堆栈使用情况和调用树,以及报告最大堆栈使用量。 然后,在我的构建系统中,我使用它来创建一个完全相同大小的堆栈。
我只在小型应用程序上使用它,但它似乎适用于 AVR8、MSP430 和 Cortex-M3。 显然,有严格的限制:没有间接调用(没有函数指针,没有虚函数),没有递归,并且使用的堆栈使用汇编程序指令模式仅限于我在 GCC 输出中找到的内容。 如果不满足这些限制,脚本将报告错误。
Python 源代码为 24k,免费(boost 许可证),速度不是很快,并且仍在开发中。 如果您有兴趣,请联系我。
I know this is reponding to a very old question, but someone might stumble upon this with the same question...
I recently experimented with a Python script that analyses the assembler version of the application, extracts the stack usage and the call tree, and reports the maximum stack use. In my build system I then use this to create a stack of exactly that size.
I used it only on small applications, but it seems to work OK for AVR8, MSP430, and Cortex-M3. Obviously, there are strict limitations: no indirect calls (no function pointers, no virtual functions), no recursion, and stack-using assembler instruction patterns that are used are limited to what I found in GCC's output. If these limitations are not met, the script will report an error.
The Python source is 24k, free (boost license), not very fast, and still under development. Contact me if you are interested.