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

Gdb 测量峰值堆栈指针值及其PC位置,gdb,stack,profiling,valgrind,benchmarking,Gdb,Stack,Profiling,Valgrind,Benchmarking,对于不同二进制文件的分析,我需要测量实际堆栈内存使用的峰值(不仅仅是保留的堆栈页面,还有实际使用的内存)。我正在用gdb尝试以下内容 watch $sp commands silent if $sp < $spnow set $spnow=$sp set $pcnow=$pc print $spnow print $pcnow end c watch$sp 命令 沉默的 如果$sp

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

watch $sp
commands
silent
if $sp < $spnow
  set $spnow=$sp
  set $pcnow=$pc
  print $spnow
  print $pcnow
  end
c
watch$sp
命令
沉默的
如果$sp<$spnow
设置$spnow=$sp
设置$pcnow=$pc
立即打印$spnow
打印$pcnow
结束
C
当应用于
ls
时,它似乎“起作用”,除了像
ls
这样的短时间运行的程序外,它实际上似乎没有进展,但它被困在诸如“来自/usr/lib/libc.so.6的strcoll\u l()中”之类的函数中。也许这种方法太慢了

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

对于不同二进制文件的分析,我需要测量实际堆栈内存使用的峰值

您的GDB方法

  • 仅适用于单线程程序
  • 太慢而不实用(
    watch$sp
    命令强制GDB单步执行程序)
如果您只关心页面粒度上的堆栈使用情况(我认为您应该——程序使用1024字节还是2000字节的堆栈真的重要吗?),那么更快的方法是在循环中运行程序,在程序成功运行时减少其
ulimit-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

我需要精确的限制,因为我想弄清楚哪些编译器优化会导致堆栈使用的微小变化(即使在字节范围内,.data和.text大小)

我认为这样做是愚蠢的

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


一个I/NO改变内联决策可以在递归程序中增加100s KBS的堆栈使用,并且对上面任何一个因素的微小改变都可以改变该决定。

如果<代码> Mase对你来说足够快,你应该考虑修补它,以在每次超过最大值时捕获堆栈跟踪。ing块应该都在那里。谢谢你的想法。我需要精确的限制,因为我想弄清楚是什么编译器优化导致了堆栈使用的微小变化(即使在字节范围内。还有.data和.text大小)。我想知道..使用
perf
并检查页面错误是否有效(或触发新堆栈内存映射的任何事件),在堆栈向下增长一页时收到通知?这应该会产生类似的结果我同意您的编辑。我只想测量一组特定程序(部件)的数字,以获取一些数字放入此表中,并在稍后争辩说,由于您所述的原因,这不是一个真正有用的数字。但我认为这一努力并没有真正得到回报,所以我将放弃我的计划。@Johanneschaub litb如果您只记录sp的值,x86-64上的红色区域也将取消您的测量值。函数允许u为本地存储在sp之外存储多达128个字节。因此,为了全面起见,您需要查看访问该范围内存的机器代码,可能使用rsp的负偏移量,也可能使用其他寄存器的偏移量。@mark啊,我明白了。因此,我想我将回过头来定性地讨论影响(如果我们阻止内联、持续传播等,会有什么变化)而不仅仅是测量。我想这将更科学真实。我试图做的实际事情是调查这种互操作/与影响更严重的高级合成后端结果的比较。