Reputation: 65016
I have a process where one .o
file is built without any .eh_frame
or .debug_frame
section (via an assembler) but with other types of debug info such as .debug_info
. Apparently this triggers gdb to stop using frame-pointer (rbp
) based unwinding for any functions from that object, and it produces invalid backtraces (it isn't clear how it is trying to unwind the stack at all).
Now the functions in this binary set up the stack frame properly (i.e., rbp
points to correctly to the base of the frame) and if GDB were just to use that to unwind, everything would be great. Is there some way I can tell it to ignore the dwarf2
info and use frame-pointer based unwinding?
Upvotes: 5
Views: 3320
Reputation: 401
I've found a very simple hack that was good enough for my purposes.
In my case there is a single function that didn't work with up
command.
Here are the steps:
set $rip = *((void**)$rbp+ 1)
set $rbp = *((void**)$rbp)
First line manually patches the instruction pointer. This seems similar to calling up
on gdb, but function arguments are still broken. Second line sets rbp to it's value from caller - this fixes arguments for me.
It's probably ok to call this multiple times to go up multiple functions. In my case after single iteration of these commands up
and frame
start to work. You might also need to set rsp
.
Warning: there is no easy way to go back (down)
Upvotes: -1
Reputation: 213829
if gcc were just to use that to unwind, everything would be great.
You mean GDB.
I use the following routine in my ~/.gdbinit
to unwind $rbp
frame chain:
define xbt
set $xbp = (void **)$arg0
while 1
x/2a $xbp
set $xbp = (void **)$xbp[0]
end
end
Call it with the initial base pointer address you want to start from, e.g., xbt $rbp
to use the current base pointer.
This isn't as good as allowing GDB to do it (no access to parameters or locals), but it does get at least the call trace.
For making GDB to ignore existing DWARF unwind info, you'll have to patch it out and build your own GDB.
P.S. Using --strip-dwo
will not help.
Update:
why stripping isn't feasible?
Well, --strip-dwo
only strips .dwo
sections, and that's not where unwind info is (it's in .eh_frame
and .debug_frame
sections).
That said, you should try to strip .debug_frame
with strip -g bad.o
-- if your file only has bad .debug_frame
but correct (or missing) .eh_frame
, then removing .debug_frame
should work.
strip
doesn't remove .eh_frame
because that info is usually required for unwinding.
If .eh_frame
is also bad, you may be able to remove it with objcopy
.
Some more info on unwinding here.
Upvotes: 5