Blame SOURCES/gdb-rhbz1086894-incomplete-bt-coredump-signal-handler.patch

2c2fa1
commit f2205de0080d999c9b67872c9db471c31b53e378
2c2fa1
Author: Hui Zhu <teawater@gmail.com>
2c2fa1
Date:   Tue May 20 13:19:06 2014 +0800
2c2fa1
2c2fa1
    Fix issue #15778: GDB Aarch64 signal frame unwinder issue
2c2fa1
    
2c2fa1
    The root cause of this issue is unwinder of "#3  <signal handler called>"
2c2fa1
    doesn't supply right values of registers.
2c2fa1
    When GDB want to get the previous frame of "#3  <signal handler called>",
2c2fa1
    it will call cache init function of unwinder "aarch64_linux_sigframe_init".
2c2fa1
    The address or the value of the registers is get from this function.
2c2fa1
    So the bug is inside thie function.
2c2fa1
    
2c2fa1
    I check the asm code of "#3  <signal handler called>":
2c2fa1
    (gdb) frame 3
2c2fa1
    (gdb) p $pc
2c2fa1
    $1 = (void (*)()) 0x7f931fa4d0
2c2fa1
    (gdb) disassemble $pc, +10
2c2fa1
    Dump of assembler code from 0x7f931fa4d0 to 0x7f931fa4da:
2c2fa1
    => 0x0000007f931fa4d0:	mov	x8, #0x8b                  	// #139
2c2fa1
       0x0000007f931fa4d4:	svc	#0x0
2c2fa1
       0x0000007f931fa4d8:	nop
2c2fa1
    
2c2fa1
    This is the syscall sys_rt_sigreturn, Linux kernel function "restore_sigframe"
2c2fa1
    will set the frame:
2c2fa1
    	for (i = 0; i < 31; i++)
2c2fa1
    		__get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
2c2fa1
    				 err);
2c2fa1
    	__get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
2c2fa1
    	__get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
2c2fa1
    The struct of uc_mcontext is:
2c2fa1
    struct sigcontext {
2c2fa1
    	__u64 fault_address;
2c2fa1
    	/* AArch64 registers */
2c2fa1
    	__u64 regs[31];
2c2fa1
    	__u64 sp;
2c2fa1
    	__u64 pc;
2c2fa1
    	__u64 pstate;
2c2fa1
    	/* 4K reserved for FP/SIMD state and future expansion */
2c2fa1
    	__u8 __reserved[4096] __attribute__((__aligned__(16)));
2c2fa1
    };
2c2fa1
    
2c2fa1
    But in GDB function "aarch64_linux_sigframe_init", the code the get address
2c2fa1
    of registers is:
2c2fa1
      for (i = 0; i < 31; i++)
2c2fa1
        {
2c2fa1
          trad_frame_set_reg_addr (this_cache,
2c2fa1
    			       AARCH64_X0_REGNUM + i,
2c2fa1
    			       sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
2c2fa1
    			       + i * AARCH64_SIGCONTEXT_REG_SIZE);
2c2fa1
        }
2c2fa1
    
2c2fa1
      trad_frame_set_reg_addr (this_cache, AARCH64_FP_REGNUM, fp);
2c2fa1
      trad_frame_set_reg_addr (this_cache, AARCH64_LR_REGNUM, fp + 8);
2c2fa1
      trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, fp + 8);
2c2fa1
    
2c2fa1
    The code that get pc and sp is not right, so I change the code according
2c2fa1
    to Linux kernel code:
2c2fa1
      trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM,
2c2fa1
    			   sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
2c2fa1
    			     + 31 * AARCH64_SIGCONTEXT_REG_SIZE);
2c2fa1
      trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM,
2c2fa1
    			   sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
2c2fa1
    			     + 32 * AARCH64_SIGCONTEXT_REG_SIZE);
2c2fa1
    
2c2fa1
    The issue was fixed by this change, and I did the regression test.  It
2c2fa1
    also fixed a lot of other XFAIL and FAIL.
2c2fa1
    
2c2fa1
    2014-05-20  Hui Zhu  <hui@codesourcery.com>
2c2fa1
    	    Yao Qi  <yao@codesourcery.com>
2c2fa1
    
2c2fa1
    	PR backtrace/16558
2c2fa1
    	* aarch64-linux-tdep.c (aarch64_linux_sigframe_init): Update comments
2c2fa1
    	and change address of sp and pc.
2c2fa1
2c2fa1
Index: gdb-7.6.1/gdb/aarch64-linux-tdep.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/aarch64-linux-tdep.c
2c2fa1
+++ gdb-7.6.1/gdb/aarch64-linux-tdep.c
2c2fa1
@@ -47,28 +47,30 @@
2c2fa1
 
2c2fa1
 /* Signal frame handling.
2c2fa1
 
2c2fa1
-      +----------+  ^
2c2fa1
-      | saved lr |  |
2c2fa1
-   +->| saved fp |--+
2c2fa1
-   |  |          |
2c2fa1
-   |  |          |
2c2fa1
-   |  +----------+
2c2fa1
-   |  | saved lr |
2c2fa1
-   +--| saved fp |
2c2fa1
-   ^  |          |
2c2fa1
-   |  |          |
2c2fa1
-   |  +----------+
2c2fa1
-   ^  |          |
2c2fa1
-   |  | signal   |
2c2fa1
-   |  |          |
2c2fa1
-   |  | saved lr |-->interrupted_function_pc
2c2fa1
-   +--| saved fp |
2c2fa1
-   |  +----------+
2c2fa1
-   |  | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
2c2fa1
-   +--| saved fp |<- FP
2c2fa1
-      |          |
2c2fa1
-      |          |<- SP
2c2fa1
-      +----------+
2c2fa1
+      +------------+  ^
2c2fa1
+      | saved lr   |  |
2c2fa1
+   +->| saved fp   |--+
2c2fa1
+   |  |            |
2c2fa1
+   |  |            |
2c2fa1
+   |  +------------+
2c2fa1
+   |  | saved lr   |
2c2fa1
+   +--| saved fp   |
2c2fa1
+   ^  |            |
2c2fa1
+   |  |            |
2c2fa1
+   |  +------------+
2c2fa1
+   ^  |            |
2c2fa1
+   |  | signal     |
2c2fa1
+   |  |            |        SIGTRAMP_FRAME (struct rt_sigframe)
2c2fa1
+   |  | saved regs |
2c2fa1
+   +--| saved sp   |--> interrupted_sp
2c2fa1
+   |  | saved pc   |--> interrupted_pc
2c2fa1
+   |  |            |
2c2fa1
+   |  +------------+
2c2fa1
+   |  | saved lr   |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
2c2fa1
+   +--| saved fp   |<- FP
2c2fa1
+      |            |         NORMAL_FRAME
2c2fa1
+      |            |<- SP
2c2fa1
+      +------------+
2c2fa1
 
2c2fa1
   On signal delivery, the kernel will create a signal handler stack
2c2fa1
   frame and setup the return address in LR to point at restorer stub.
2c2fa1
@@ -117,6 +119,8 @@
2c2fa1
   d28015a8        movz    x8, #0xad
2c2fa1
   d4000001        svc     #0x0
2c2fa1
 
2c2fa1
+  This is a system call sys_rt_sigreturn.
2c2fa1
+
2c2fa1
   We detect signal frames by snooping the return code for the restorer
2c2fa1
   instruction sequence.
2c2fa1
 
2c2fa1
@@ -140,7 +144,6 @@ aarch64_linux_sigframe_init (const struc
2c2fa1
 {
2c2fa1
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
2c2fa1
   CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
2c2fa1
-  CORE_ADDR fp = get_frame_register_unsigned (this_frame, AARCH64_FP_REGNUM);
2c2fa1
   CORE_ADDR sigcontext_addr =
2c2fa1
     sp
2c2fa1
     + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
2c2fa1
@@ -154,12 +157,14 @@ aarch64_linux_sigframe_init (const struc
2c2fa1
 			       sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
2c2fa1
 			       + i * AARCH64_SIGCONTEXT_REG_SIZE);
2c2fa1
     }
2c2fa1
+  trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM,
2c2fa1
+			   sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
2c2fa1
+			     + 31 * AARCH64_SIGCONTEXT_REG_SIZE);
2c2fa1
+  trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM,
2c2fa1
+			   sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
2c2fa1
+			     + 32 * AARCH64_SIGCONTEXT_REG_SIZE);
2c2fa1
 
2c2fa1
-  trad_frame_set_reg_addr (this_cache, AARCH64_FP_REGNUM, fp);
2c2fa1
-  trad_frame_set_reg_addr (this_cache, AARCH64_LR_REGNUM, fp + 8);
2c2fa1
-  trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, fp + 8);
2c2fa1
-
2c2fa1
-  trad_frame_set_id (this_cache, frame_id_build (fp, func));
2c2fa1
+  trad_frame_set_id (this_cache, frame_id_build (sp, func));
2c2fa1
 }
2c2fa1
 
2c2fa1
 static const struct tramp_frame aarch64_linux_rt_sigframe =
2c2fa1
Index: gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-rhbz1086894-bt-signal-handler.exp
2c2fa1
===================================================================
2c2fa1
--- /dev/null
2c2fa1
+++ gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-rhbz1086894-bt-signal-handler.exp
2c2fa1
@@ -0,0 +1,35 @@
2c2fa1
+# Copyright (C) 2014 Free Software Foundation, Inc.
2c2fa1
+#
2c2fa1
+# This program is free software; you can redistribute it and/or modify
2c2fa1
+# it under the terms of the GNU General Public License as published by
2c2fa1
+# the Free Software Foundation; either version 3 of the License, or
2c2fa1
+# (at your option) any later version.
2c2fa1
+#
2c2fa1
+# This program is distributed in the hope that it will be useful,
2c2fa1
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2c2fa1
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2c2fa1
+# GNU General Public License for more details.
2c2fa1
+#
2c2fa1
+# You should have received a copy of the GNU General Public License
2c2fa1
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
2c2fa1
+
2c2fa1
+# Internal testing for RHEL-7.1.
2c2fa1
+
2c2fa1
+standard_testfile
2c2fa1
+
2c2fa1
+if { ![istarget "aarch64*"] } {
2c2fa1
+        verbose "Skipping $testfile"
2c2fa1
+        return
2c2fa1
+}
2c2fa1
+
2c2fa1
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
2c2fa1
+        return -1
2c2fa1
+}
2c2fa1
+
2c2fa1
+if ![runto_main] {
2c2fa1
+        return -1
2c2fa1
+}
2c2fa1
+
2c2fa1
+gdb_test "continue" "Continuing.\r\n\r\nProgram received signal SIGSEGV.*" "run until SIGSEGV"
2c2fa1
+
2c2fa1
+gdb_test "backtrace" "#$decimal\\s+$hex in pause .*from.*" "backtrace on signal handler"
2c2fa1
Index: gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-rhbz1086894-bt-signal-handler.c
2c2fa1
===================================================================
2c2fa1
--- /dev/null
2c2fa1
+++ gdb-7.6.1/gdb/testsuite/gdb.arch/aarch64-rhbz1086894-bt-signal-handler.c
2c2fa1
@@ -0,0 +1,40 @@
2c2fa1
+/* Copyright 2014 Free Software Foundation, Inc.
2c2fa1
+
2c2fa1
+   This file is part of GDB.
2c2fa1
+
2c2fa1
+   This program is free software; you can redistribute it and/or modify
2c2fa1
+   it under the terms of the GNU General Public License as published by
2c2fa1
+   the Free Software Foundation; either version 3 of the License, or
2c2fa1
+   (at your option) any later version.
2c2fa1
+
2c2fa1
+   This program is distributed in the hope that it will be useful,
2c2fa1
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
2c2fa1
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2c2fa1
+   GNU General Public License for more details.
2c2fa1
+
2c2fa1
+   You should have received a copy of the GNU General Public License
2c2fa1
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
2c2fa1
+
2c2fa1
+/* Internal test for RHEL-7.1.  */
2c2fa1
+
2c2fa1
+#include <sys/types.h>
2c2fa1
+#include <signal.h>
2c2fa1
+#include <unistd.h>
2c2fa1
+#include <assert.h>
2c2fa1
+
2c2fa1
+static void
2c2fa1
+handle_alrm(int signo)
2c2fa1
+{
2c2fa1
+  kill (getpid (), SIGSEGV);
2c2fa1
+  assert (0);
2c2fa1
+}
2c2fa1
+
2c2fa1
+int
2c2fa1
+main (int argc, char *argv[])
2c2fa1
+{
2c2fa1
+  signal (SIGALRM, handle_alrm);
2c2fa1
+  alarm (1);
2c2fa1
+  pause ();
2c2fa1
+  assert (0);
2c2fa1
+  return 0;
2c2fa1
+}