测量峰值堆栈指针值及其 PC 位置

Measure the peak stackpointer value and its PC location

为了分析不同的二进制文件,我需要测量峰值实际堆栈内存使用量(不仅仅是保留的堆栈页面,而是实际使用的内存)。我正在尝试使用 gdb

进行以下操作
watch $sp
commands
silent
if $sp < $spnow
  set $spnow=$sp
  set $pcnow=$pc
  print $spnow
  print $pcnow
  end
c

这在 "work" 应用于 ls 时, 除了 ,即使对于 运行 短程序也是如此 ls ,它实际上并没有出现进展,而是卡在了 "in strcoll_l () from /usr/lib/libc.so.6" 这样的函数中。这种方法可能太慢了。

我还查看了 valgrind massif 工具。它可以分析堆栈使用情况,但不幸的是似乎无法报告在程序的哪一部分遇到了峰值使用情况。

For an analysis of different binaries, I need to measure the peak actual stack memory usage

您的 GDB 方法

  • 仅适用于单线程程序
  • 太慢而不实用(watch $sp 命令强制 GDB 单步执行您的程序)。

如果您只关心页面粒度的堆栈使用情况(我认为您应该——真的关心程序使用 1024 字节还是 2000 字节的堆栈?),那么一个更快的方法是 运行 循环中的程序,减少它的 ulimit -s 而程序成功 运行s (你也可以二进制搜索,例如从默认 8MB 开始,然后尝试4, 2, 1, 512K, 等等,直到失败,然后增加堆栈限制以找到确切的值)。

对于/bin/ls

bash -c 'x=4096; while /bin/ls > /dev/null; do
         echo $x; x=$(($x/2)); ulimit -s $x || break; done'
4096
2048
1024
512
256
128
64
32
bash: line 1: 109951 Segmentation fault      (core dumped) /bin/ls > /dev/null

然后您可以通过查看 core 转储找到 $PC

I need the precise limits because I want to figure out what compiler optimizations cause what micro-changes to stack usages (even in the bytes range. along with .data and .text sizes).

我认为尝试这样做是徒劳的。

根据我的经验,堆栈使用受编译器内联决策的影响最大。这些反过来又受精确的编译器版本和调整、运行时间信息的存在(用于配置文件引导优化)以及被优化程序的精确源的影响最大。

对内联决策的 yes/no 更改可以在递归程序中增加 100 KB 的堆栈使用,并且对上述任何因素的微小更改都可以改变该决策。