c - 如果该数据仅在 C 函数返回时可用,如何使用 LLDB 自动捕获输出数据?

标签 c debugging lldb

我编译了没有任何源代码的二进制文件,但我知道它包含具有以下签名的 C 函数

void generateMoreData ( char * destination, long size )

该函数的符号在 LLDB 调试器中可见,我想捕获所有生成的数据。

目前我知道我可以通过以下方式捕获数据:

  1. 我设置了一个断点break set -ngenerateMoreData
  2. 一旦遇到断点,我就会检查 $rdi$rsi 的值,因为 System V 的 x86_64 ABI(由 Linux、BSD、macOS 和Solaris)在这些寄存器中传递前两个参数。
  3. 然后我继续使用线程跳出直到函数返回。
  4. 最后,我可以使用 x -c COUNT ADDRESS 转储数据,其中 COUNT$rsiADDRESS< 的值 步骤 (2) 中所示的 $rdi

这工作正常,但我想自动化整个过程并遇到两个问题:

  • 问题 A:仅当输入函数 $rdi$rsi 时包含我需要的值,但当函数返回时不再包含我需要的值,因为使用了这些寄存器函数,从而失去其初始值。

  • 问题 B:我可以使用 break command add 设置在遇到断点时执行的命令,但这些命令不能包含线程跳出,因为这命令继续执行,并且第一个继续执行的命令停止处理断点命令,因此该命令之后设置的任何命令都不会执行。

最佳答案

找出步骤 B 断点地址的一种更简单的方法是利用父帧中的 pc 值始终是该帧的返回 pc 的事实。所以我们可以让断点 1 的命令来解决这个问题。由于当您到达第二个断点时,您没有使用当前帧中的任何信息,因此您并不关心是否在返回处停止或在返回之后停止。

您必须记住首先清除旧的断点,但是使用 lldb 中的命名断点很容易做到这一点:

break set -G true -n generateMoreData --skip-prologue false
breakpoint name configure SecondBreakpoint -G true -C "x -o generateMoreData.txt --append-outfile -c \`$size\` $destination" -C "break delete SecondBreakpoint"
break command add 1
> expr long $destination = $arg1
> expr long $size = $arg2
> up
> break set -N SecondBreakpoint -a $pc 
> DONE

请注意,我们不必将命令添加到我们创建的断点中,因为我将其添加到名称中,因此新断点将从该名称继承它们。

我还使用了 $arg1$arg2 而不是 $rsi$rdi。这只是一个方便的 lldb 别名,以防您不记得哪个是哪个......

此外,如果可能从多个线程调用此函数,解决此问题会变得更加困难。然后,您需要获取当前线程并设置线程特定的断点。此外,如果要递归调用此函数,则必须为每个返回帧设置不同的 $size 和 $destination 值。

如果您开始尝试处理此类问题,最好对断点使用 Python 回调。然后,您不必像 Mecki 的聪明解决方案那样存储要在返回时打印的数据,而是可以维护一个小的 Python 数据结构,该结构会记住每个帧/线程组合的 $size 和 $destination,并在每个调用都会返回。

关于c - 如果该数据仅在 C 函数返回时可用,如何使用 LLDB 自动捕获输出数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54682602/

相关文章:

c - 我如何在 C 中对文本文件中的记录进行排序?

c - Linux 上的 0x4000000 sigaction 标志是什么?

lldb 没有在我的断点处停止

c++ - 无法检查 lldb 中的 std::string 变量

c - 什么是 C 中可以展示不同 linux 调度程序(noop、CFS、deadline)优缺点的好程序?

c - 程序是 32 位还是 64 位是什么意思?

c - 在 gdb 中包含 malloc.c 的源代码?

android - 在真实设备上使用 Eclipse 调试 Android 应用程序

debugging - 在客户环境中创建内存转储是否良好?

lldb - 无法使Mac OS X LLDB进程读取STDIN