我有很少的基准,比如fft,dijkstra。我想收集所有库函数和用户定义函数的堆栈大小。 C代码也可用。
我在硬件中管理缓存,所以我需要每个小函数的精确堆栈大小,变量。
答案 0 :(得分:1)
如果使用最近的GCC进行编译,您可以将-fstack-usage标记传递给gcc
(除了优化标记,如果有的话):
基于每个函数为程序生成编译器输出堆栈使用信息。转储的文件名是通过将.su附加到auxname来实现的。 auxname是从输出文件的名称生成的,如果明确指定并且它不是可执行文件,否则它是源文件的基本名称。条目由三个字段组成:
功能的名称。 一些字节。 一个或多个限定符:
static
,dynamic
,bounded
。限定符
static
表示该函数静态操作堆栈:在函数入口处为帧分配固定数量的字节,并在函数出口处释放;否则在功能中不进行堆栈调整。第二个字段是固定的字节数。限定符
dynamic
表示函数动态操作堆栈:除了上面描述的静态分配之外,还在函数体中进行堆栈调整,例如围绕函数调用推送/弹出参数。如果限定符bounded
也存在,则这些调整的数量在编译时受限,第二个字段是函数使用的堆栈总量的上限。如果不存在,则这些调整的数量在编译时不受限制,第二个字段仅表示有界部分。
您还可以传递-Wstack-usage=
len warning flag,其中:
如果函数的堆栈使用量可能大于 len 字节,则发出警告。用于确定堆栈使用的计算是保守的。在确定是否发出警告时,编译器会包含通过
alloca
,可变长度数组或相关构造分配的任何空间。
最后,您可以考虑使用MELT来自定义编译器。例如,您可以考虑使用 MELT扩展来扩展GCC,以便在每个函数中检测动态堆栈的使用情况。
当然,如果你想要库的相同信息,你应该从他们的源代码重新编译它们。
BTW,某些函数或某些函数调用事件的堆栈使用可能是不明确的(当然取决于优化标志和目标系统),因为GCC 有时能够tail call优化和功能inlining(即使是不合格的inline
!)和/或function cloning。此外,编译器神奇地知道一些少数 C standard library函数(printf
,memset
,....),这些函数可能会使用某些内部builtin函数来编译它们。最后,使用link-time optimizations(使用-flto
)编译了几个软件(以及越来越多的库),然后单个函数的堆栈使用没有很好地定义(因为它们经常被内联)。
因此,我不确定您的问题是否符合精确的意义。你可以改写它并激励和改进它。