【问题标题】:How does gdb implement call functiongdb如何实现调用功能
【发布时间】:2020-07-15 18:15:30
【问题描述】:

当我在 arm linux 中使用 gdb 调试进程时,我可以使用像 call write(123,"abc",3) 这样的调用

gdb 如何将该调用注入进程并恢复全部?

【问题讨论】:

  • 考虑断点在 Linux ARM 设备上的工作方式。调试器已经在断点处打断了代码执行,所以只需按照ARM ABI对参数进行封送处理,调用指定的入口点即可。返回值通常在寄存器中,被转换为显示,调试器等待你的下一条指令。
  • 这个问题太宽泛了。见:github.com/eklitzke/ptrace-call-userspace
  • GDB 是一个开源实用程序,建议阅读源代码,从:https://www.gnu.org/software/gdb/current/ 开始,然后通过:git clone git://sourceware.org/git/binutils-gdb.git 检索源代码并可以通过:sudo apt install git 安装git

标签: c gdb ptrace


【解决方案1】:

gdb 如何将该调用注入进程并全部恢复?

GDB 可以使用ptrace 系统调用读取和写入劣质(正在调试的)进程内存。

所以它会读取并在自己的内存中保存一些来自下级的指令块(比如 100 个字节)。

然后它用 new 指令覆盖这个块,看起来像:

r0 = 123
r1 = pointer to "abc"
r2 = 3
BLR write
BKPT

现在 GDB 保存当前的低级寄存器,设置 ip 指向它刚刚编写的指令块,然后恢复低级。

Inferior 执行指令直到到达断点,此时 GDB 重新获得控制权。它现在可以查看返回寄存器以了解write 返回的内容并打印出来。 GDB现在恢复了原来的指令和原来的寄存器值,我们又像什么都没发生一样回来了。

附:这是对“低级调用函数”如何工作的一般描述;我并没有声称这正是它的工作原理。

还有一些复杂的情况:如果write 回调到 GDB 覆盖的代码,它就无法工作。所以实际上 GDB 使用了一些其他的机制来获得合适的“scratch area”。此外,"abc" 字符串也需要暂存区。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 2022-07-04
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 2021-01-08
    • 2018-07-19
    相关资源
    最近更新 更多