rs6000, Fix Linux DWARF register mapping
authorCarl Love <cel@us.ibm.com>
Wed, 8 Nov 2023 16:32:58 +0000 (11:32 -0500)
committerCarl Love <cel@linux.ibm.com>
Wed, 8 Nov 2023 16:35:57 +0000 (11:35 -0500)
commit1bd70cb9f833660a249b0467fab3d07a97e21a07
tree1a373e87d87596f3d7f648b7ad5d67a83a412320
parent3c09fd57e6f825672964581e152bd50b507e5630
rs6000, Fix Linux DWARF register mapping

Overview of issues fixed by the patch.

The primary issue this patch fixes is the DWARF register mapping for
Linux.  The changes in ppc-linux-tdep.c fix the DWARF register mapping
issues.  The register mapping issue is responsible for two of the
five regression bugs seen in gdb.base/store.exp.

Once the register mapping was fixed, an underlying issue with the unwinding
of the signal trampoline in common-code in ifrun.c was found.  This
underlying bug is best described by Ulrich in the following description.

  The unwinder bug shows up on platforms where the kernel uses a trampoline
  to dispatch "calls to" the signal handler (not just *returns from* the
  signal handler).  Many platforms use a trampoline for signal return, and
  that is working fine, but the only platform I'm (Ulrich) aware of that
  uses a trampoline for signal handler calls is (recent kernels for)
  PowerPC.  I believe the rationale for using a trampoline here
  is to improve performance by avoiding unbalancing of the
  branch predictor's call/return stack.

  However, on PowerPC the bug is dormant as well as it is hidden
  by *another* bug that prevents correct unwinding out of the
  signal trampoline.  This is because the custom CFI for the
  trampoline uses a register number (VSCR) that is not ever used
  by compiler-generated CFI, and that particular register is
  mapped to an invalid number by the current PowerPC DWARF mapper.

The underlying unwinder bug is exposed by the "new" regression failures
in gdb.base/sigstep.exp.  These failures were previously masked by
the fact that GDB was not seeing a valid frame when it tried to unwind
the frames.  The sigstep.exp test is specifically testing stepping into
a signal handler.  With the correct DWARF register mapping in place,
specifically the VSCR mapping, the signal trampoline code now unwinds to a
valid frame exposing the pre-existing bug in how the signal handler on
PowerPC works.  The one line change infrun.c fixes the exiting bug in
the common-code for platforms that use a trampoline to dispatch calls
to the signal handler by not stopping in the SIGTRAMP_FRAME.

Detailed description of the DWARF register mapping fix.

The PowerPC DWARF register mapping is the same for the .eh_frame and
.debug_frame on Linux.  PowerPC uses different mapping for .eh_frame and
.debug_frame on other operating systems.  The current GDB support for
mapping the DWARF registers in rs6000_linux_dwarf2_reg_to_regnum and
rs6000_adjust_frame_regnum file gdb/rs6000-tdep.c is not correct for Linux.
The files have some legacy mappings for spe_acc, spefscr, EV which was
removed from GCC in 2017.

This patch adds a two new functions rs6000_linux_dwarf2_reg_to_regnum,
and rs6000_linux_adjust_frame_regnum in file gdb/ppc-linux-tdep.c to handle
the DWARF register mappings on Linux.  Function
rs6000_linux_dwarf2_reg_to_regnum is installed for both gdb_dwarf_to_regnum
and gdbarch_stab_reg_to_regnum since the mappings are the same.

The ppc_linux_init_abi function in gdb/ppc-linux-tdep.c is updated to
call set_gdbarch_dwarf2_reg_to_regnum map the new function
rs6000_linux_dwarf2_reg_to_regnum for the architecture.  Similarly,
dwarf2_frame_set_adjust_regnum is called to map
rs6000_linux_adjust_frame_regnum into the architecture.

Additional detail on the signal handling fix.

The specific sequence of events for handling a signal on most
architectures is as follows:

  1) Some code is running when a signal arrives.
  2) The kernel handles the signal and dispatches to the handler.
    ...

However on PowerPC the sequence of events is:

  1) Some code is running when a signal arrives.
  2) The kernel handles the signal and dispatches to the trampoline.
  3) The trampoline performs a normal function call to the handler.
      ...

We want the "nexti" to step into, not over, signal handlers invoked by
the kernel.  This is the case for most platforms as the kernel puts a
signal trampoline frame onto the stack to handle proper return after the
handler.  However, on some platforms such as PowerPC, the kernel actually
uses a trampoline to handle *invocation* of the handler.  We do not
want GDB to stop in the SIGTRAMP_FRAME.  The issue is fixed in function
process_event_stop_test by adding a check that the frame is not a
SIGTRAMP_FRAME to the if statement to stop in a subroutine call.  This
prevents GDB from erroneously detecting the trampoline invocation as a
subroutine call.

This patch fixes two regression test failures in gdb.base/store.exp.

The patch then fixes an exposed, dormant, signal handling issue that
is exposed in the signal handling test gdb.base/sigstep.exp.

The patch has been tested on Power 8 LE/BE, Power 9 LE/BE, Power 10 with
no new regressions.  Note, only two of the five failures in store.exp
are fixed.  The remaining three failures are fixed in a following
patch.
gdb/infrun.c
gdb/ppc-linux-tdep.c