Fix backtrace across signals on amd64

The 'Apply the retpoline transformation to indirect jumps in the
raw ASM' commit in 6.4 added an instruction to the sigcode.
This fixes the offset to look for sigreturn and mantains
backward compat till 5.0.

okay?

Index: Makefile
===================================================================
RCS file: /cvs/ports/devel/gdb/Makefile,v
retrieving revision 1.65
diff -u -p -u -r1.65 Makefile
--- Makefile    29 Mar 2020 17:23:30 -0000      1.65
+++ Makefile    18 May 2020 21:44:42 -0000
@@ -4,7 +4,7 @@ COMMENT=        GNU debugger
 CATEGORIES=    devel
 
 DISTNAME=      gdb-7.12.1
-REVISION=      10
+REVISION=      11
 
 HOMEPAGE=      https://www.gnu.org/software/gdb/
 
Index: patches/patch-gdb_amd64obsd-tdep_c
===================================================================
RCS file: patches/patch-gdb_amd64obsd-tdep_c
diff -N patches/patch-gdb_amd64obsd-tdep_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-gdb_amd64obsd-tdep_c  18 May 2020 21:44:42 -0000
@@ -0,0 +1,107 @@
+$OpenBSD$
+
+Index: gdb/amd64obsd-tdep.c
+--- gdb/amd64obsd-tdep.c.orig
++++ gdb/amd64obsd-tdep.c
+@@ -76,8 +76,40 @@ amd64obsd_iterate_over_regset_sections (struct gdbarch
+ /* Support for signal handlers.  */
+ 
+ /* Default page size.  */
+-static const int amd64obsd_page_size = 4096;
++static const CORE_ADDR amd64obsd_page_size = 4096;
+ 
++/* Offset & instructions for sigreturn(2).  */
++
++#define SIGRETURN_INSN_LEN 9
++
++struct amd64obsd_sigreturn_info_t {
++  int offset;
++  gdb_byte sigreturn[SIGRETURN_INSN_LEN];
++}; 
++
++static const amd64obsd_sigreturn_info_t
++  amd64obsd_sigreturn_info[] = {
++  /* OpenBSD 6.4 */
++  { 9, { 0x48, 0xc7, 0xc0,
++         0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
++         0x0f, 0x05 } },         /* syscall */
++  /* OpenBSD 5.1 */
++  { 6, { 0x48, 0xc7, 0xc0,
++         0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
++         0x0f, 0x05 } },         /* syscall */
++  { 7, { 0x48, 0xc7, 0xc0,
++         0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
++         0x0f, 0x05 } },         /* syscall */
++  /* OpenBSD 5.0 */
++  { 6, { 0x48, 0xc7, 0xc0,
++         0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
++         0xcd, 0x80 } },         /* int $0x80 */
++  { 7, { 0x48, 0xc7, 0xc0,
++         0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
++         0xcd, 0x80 } },         /* int $0x80 */
++  { -1, {} }
++};
++
+ /* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp
+    routine.  */
+ 
+@@ -86,20 +118,8 @@ amd64obsd_sigtramp_p (struct frame_info *this_frame)
+ {
+   CORE_ADDR pc = get_frame_pc (this_frame);
+   CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
+-  const gdb_byte osigreturn[] =
+-  {
+-    0x48, 0xc7, 0xc0,
+-    0x67, 0x00, 0x00, 0x00,   /* movq $SYS_sigreturn, %rax */
+-    0xcd, 0x80                        /* int $0x80 */
+-  };
+-  const gdb_byte sigreturn[] =
+-  {
+-    0x48, 0xc7, 0xc0,
+-    0x67, 0x00, 0x00, 0x00,   /* movq $SYS_sigreturn, %rax */
+-    0x0f, 0x05                        /* syscall */
+-  };
+-  size_t buflen = (sizeof sigreturn) + 1;
+-  gdb_byte *buf;
++  const amd64obsd_sigreturn_info_t *info;
++  gdb_byte buf[SIGRETURN_INSN_LEN];
+   const char *name;
+ 
+   /* If the function has a valid symbol name, it isn't a
+@@ -113,22 +133,22 @@ amd64obsd_sigtramp_p (struct frame_info *this_frame)
+   if (find_pc_section (pc) != NULL)
+     return 0;
+ 
+-  /* If we can't read the instructions at START_PC, return zero.  */
+-  buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1);
+-  if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen))
+-    return 0;
++  for (info = amd64obsd_sigreturn_info; info->offset != -1; info++)
++    {
+ 
+-  /* Check for sigreturn(2).  Depending on how the assembler encoded
+-     the `movq %rsp, %rdi' instruction, the code starts at offset 6 or
+-     7.  OpenBSD 5.0 and later use the `syscall' instruction.  Older
+-     versions use `int $0x80'.  Check for both.  */
+-  if (memcmp (buf, sigreturn, sizeof sigreturn)
+-      && memcmp (buf + 1, sigreturn, sizeof sigreturn)
+-      && memcmp (buf, osigreturn, sizeof osigreturn)
+-      && memcmp (buf + 1, osigreturn, sizeof osigreturn))
+-    return 0;
++      /* If we can't read the instructions at return zero.  */
++      if (!safe_frame_unwind_memory (this_frame,
++        start_pc + info->offset, buf, sizeof buf))
++        continue;
+ 
+-  return 1;
++      /* Check for sigreturn(2).  */
++      if (memcmp (buf, info->sigreturn, sizeof buf))
++        continue;
++
++      return 1;
++    }
++
++  return 0;
+ }
+ 
+ /* Assuming THIS_FRAME is for a BSD sigtramp routine, return the

Reply via email to