Fix remaining inline/tailcall unwinding breakage for x86_64
authorLuis Machado <luis.machado@linaro.org>
Sat, 25 Apr 2020 03:32:44 +0000 (00:32 -0300)
committerLuis Machado <luis.machado@linaro.org>
Mon, 27 Apr 2020 12:04:55 +0000 (09:04 -0300)
commit991a3e2e9944a4b3a27bd989ac03c18285bd545d
treeeeb5a348ca16d779b3e32ef4d12c678d55a3a569
parent714e6c969ff1ce0fdb0cd3703d41ef2fef424535
Fix remaining inline/tailcall unwinding breakage for x86_64

Commit 5939967b355ba6a940887d19847b7893a4506067 fixed inline
frame unwinding breakage for some targets (aarch64, riscv, s390...)
but regressed a few amd64 testcases related to tailcalls.

Given the following example situation...

Frame #-1 - sentinel frame
Frame # 0 - inline frame
Frame # 1 - normal frame

... suppose we're at level #1 and call into dwarf2_tailcall_sniffer_first.

We'll attempt to fetch PC, which used to be done via the gdbarch_unwind_pc call
(before 5939967b355ba6a940887d19847b7893a4506067), but now it is being handled
by the get_frame_register function.

gdbarch_unwind_pc will attempt to use frame #1's cache to retrieve information
about the PC. Here's where different architectures behave differently.

x86_64 will find a dwarf rule to retrieve PC from memory, at a CFA + offset
location. So the PC value is readily available and there is no need to
create a lazy value.

For aarch64 (and others), GCC doesn't emit an explicit location for PC, so we
eventually will find that PC is DWARF2_FRAME_REG_UNSPECIFIED. This is known
and is handled by GDB by assuming GCC really meant DWARF2_FRAME_REG_SAME_VALUE.

This means we'll attempt to fetch the register value from frame #0, via a call
to frame_unwind_got_register, which will trigger the creation of a lazy value
that requires a valid frame id for frame #0.

We don't have a valid id for frame #0 yet, so we assert.

Given the above, the following patch attempts to handle the situation without
being too hacky. We verify if the next frame is an inline frame and if its
frame id has been computed already. If it hasn't been computed yet, then we
use the safer get_frame_register function, otherwise we use the regular
gdbarch_unwind_pc hook.

gdb/ChangeLog:

2020-04-27  Luis Machado  <luis.machado@linaro.org>

* dwarf2/frame-tailcall.c (dwarf2_tailcall_sniffer_first): Handle
problematic inline frame unwinding situation.
* frame.c (frame_id_computed_p): New function.
* frame.h (frame_id_computed_p): New prototype.
gdb/ChangeLog
gdb/dwarf2/frame-tailcall.c
gdb/frame.c
gdb/frame.h