我有一个过程,其中一个.o
文件构建时没有任何.eh_frame
或.debug_frame
部分(通过汇编程序),但有其他类型的调试信息,例如.debug_info
。显然这会触发gdb停止使用基于该对象的任何函数展开的帧指针(rbp
),并且它会产生无效的回溯(它根本不清楚它是如何尝试解开堆栈的)
现在这个二进制文件中的函数正确设置了堆栈框架(即rbp
正确指向框架的底部),如果GDB只是用它来展开,一切都会很好。有什么方法我可以告诉它忽略dwarf2
信息并使用基于帧指针的展开?
答案 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设置为其来自调用方的值-这为我修复了参数。
多次调用该函数可以启用多个功能可能是可以的。在我的情况下,这些命令up
和frame
一次迭代后就开始工作。您可能还需要设置rsp
。
警告:没有简单的方法可以返回(向下)