强制GDB使用基于帧指针的展开

时间:2017-03-11 19:54:25

标签: debugging x86 gdb

我有一个过程,其中一个.o文件构建时没有任何.eh_frame.debug_frame部分(通过汇编程序),但有其他类型的调试信息,例如.debug_info 。显然这会触发gdb停止使用基于该对象的任何函数展开的帧指针(rbp),并且它会产生无效的回溯(它根本不清楚它是如何尝试解开堆栈的)

现在这个二进制文件中的函数正确设置了堆栈框架(即rbp正确指向框架的底部),如果GDB只是用它来展开,一切都会很好。有什么方法我可以告诉它忽略dwarf2信息并使用基于帧指针的展开?

2 个答案:

答案 0 :(得分:3)

  

如果gcc只是用它来放松,一切都会很棒。

你的意思是GDB。

我在~/.gdbinit中使用以下例程来展开$rbp框架链:

define xbt
  set $xbp = (void **)$arg0
  while 1
    x/2a $xbp
    set $xbp = (void **)$xbp[0]
  end
end

使用您想要开始的初始基址指针地址调用它,例如xbt $rbp以使用当前基指针。

这并不像允许GDB这样做(无法访问参数或本地人),但它确实至少获得了呼叫追踪。

为了让GDB忽略现有的DWARF展开信息,您必须将其修补并构建自己的GDB。

P.S。使用--strip-dwo帮助。

<强>更新

  

剥离为何不可行?

好吧,--strip-dwo只会删除.dwo个部分,并且这不是展开信息的地方(它位于.eh_frame.debug_frame部分)

也就是说,尝试使用.debug_frame删除strip -g bad.o - 如果您的文件只有错误.debug_frame但正确(或缺失){{ 1}},然后删除.eh_frame应该有用。

.debug_frame不会删除strip,因为展开时通常需要该信息。

如果.eh_frame也不好,可能能够使用.eh_frame将其删除。

有关展开here的更多信息。

答案 1 :(得分:0)

我发现了一个非常简单的hack,足以满足我的目的。 在我的情况下,有一个功能无法与up命令一起使用。

以下是步骤:

set $rip = *((void**)$rbp+ 1)
set $rbp = *((void**)$rbp)

第一行手动修补指令指针。这似乎与在gdb上调用up类似,但是函数参数仍然损坏。第二行将rbp设置为其来自调用方的值-这为我修复了参数。

多次调用该函数可以启用多个功能可能是可以的。在我的情况下,这些命令upframe一次迭代后就开始工作。您可能还需要设置rsp

警告:没有简单的方法可以返回(向下)