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