我如何在gdb中的"打印到终端上的东西"中加上断点?

mar*_*tin 25 printf gdb breakpoints conditional-breakpoint

我想知道在一个巨大的应用程序里面打印某个消息.应用程序是如此庞大和陈旧,它使用所有可能的方式将文本打印到终端; 例如printf(),fprintf(stdout,...)等.

我写了在write()系统调用上设置了一个断点,但是由于使用write()的各种文件I/O操作,我遇到了太多的断点停止.

所以基本上我希望gdb在程序向终端输出内容时停止,但同时我不希望gdb在程序向文件写入内容时停止.

小智 26

使用检查第一个参数的条件断点.在64位x86系统上,条件是:

(gdb)b写1 == $ rdi

在32位系统上,它更复杂,因为参数在堆栈上,这意味着您需要将$ esp转换为int*并索引fd参数.此时的堆栈具有返回地址,长度,缓冲区和最后的fd.

这在硬件平台之间差异很大.

  • 美好的。对于阅读本文的任何人,请记住,如果您的输出发送到 STDERR 那么应该是“(gdb) b write if 2==$rdi” (3认同)
  • 我对此一团糟,发现FD号为“ *(int)($ esp + 4)”,字符串长度为“(int)*(int)($ esp + 12)”,最后字符串数据为“ *(int)($ esp + 8)”。因此对于STDOUT,您可以执行以下操作:如果1 == *(int)($ esp + 4)命令,则中断写入print(int)*(int)($ esp + 12)x / s *(int)($ esp + 8)结束但是,当我尝试在_huge_应用程序中实践使用此方法时,结果证明此方法并非万无一失,因为它无法处理重定向等,因此,如果该应用程序在stdout上使用dup2(),您可能会错过一些东西打印到标准输出。 (2认同)

ks1*_*322 14

使用gdb 7.0,您可以在syscall write()上设置条件断点:

(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [4])
(gdb) condition 1 $ebx==1
Run Code Online (Sandbox Code Playgroud)

$ ebx包含第一个系统调用参数 - 此处为FD编号

  • 注意:“printf”是缓冲的,因此您可能只能在连接的第二个“printf”调用上看到第一个“printf”的“write”。 (2认同)