This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Reading signal handler frame in AIX


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cdcda965ea4c70c80b9f8c294597e991417ff9d5

commit cdcda965ea4c70c80b9f8c294597e991417ff9d5
Author: Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
Date:   Thu Nov 1 06:23:59 2018 -0400

    Reading signal handler frame in AIX
    
    In AIX if gdb is debugging an application which has a signal handler
    and reaches the signal handler frame, then we need to read the back
    chain address from sigcontext saved on the stack, similarly the LR.
    
    As backchain at an offset 0 will be 0, because we will have a
    sigconext saved after the minimum stack size. So the correct
    backchain will be at an offset after minimum stack and the LR at
    an offset 8 will be of the signal millicode address.
    If the back chain pointer is NULL and the LR field is in the kernel
    segment(ex. 0x00004a14) then we can probably assume we are in a
    signal  handler.
    
    sample output
    
    (gdb) bt
    0  sig_handle_aix (signo=11) at aix-sighandle.c:7
    1  0x0000000000004a94 in ?? ()
    (gdb)
    
    expected output
    
    (gdb) bt
    0  sig_handle_aix (signo=11) at aix-sighandle.c:7
    1  <signal handler called>
    2  0x0000000100000748 in foo () at aix-sighandle.c:14
    3  0x000000010000079c in main () at aix-sighandle.c:19
    
    gdb/ChangeLog:
    
    2018-11-01  Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
    
    	* rs6000-aix-tdep.c: Include "trad-frame.h" and "frame-unwind.h".
    	(SIG_FRAME_LR_OFFSET64): New define.
    	(SIG_FRAME_FP_OFFSET64): New define.
    	(aix_sighandle_frame_cache): New Function.
    	(aix_sighandle_frame_this_id): New Function.
    	(aix_sighandle_frame_prev_register): New Function.
    	(aix_sighandle_frame_sniffer): New Function.
    	(aix_sighandle_frame_unwind): New global variable.
    	(rs6000_aix_init_osabi): Install new frame unwinder.
    
    gdb/testsuite/ChangeLog:
    
    2018-11-01  Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
    
    	* gdb.arch/aix-sighandle.c: New file.
    	* gdb.arch/aix-sighandle.exp: New file.

Diff:
---
 gdb/ChangeLog                            |  12 ++++
 gdb/rs6000-aix-tdep.c                    | 116 ++++++++++++++++++++++++++++++-
 gdb/testsuite/ChangeLog                  |   5 ++
 gdb/testsuite/gdb.arch/aix-sighandle.c   |  35 ++++++++++
 gdb/testsuite/gdb.arch/aix-sighandle.exp |  43 ++++++++++++
 5 files changed, 210 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6d9816e..e33fe9d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,15 @@
+2018-11-01  Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
+
+	* rs6000-aix-tdep.c: Include "trad-frame.h" and "frame-unwind.h".
+	(SIG_FRAME_LR_OFFSET64): New define.
+	(SIG_FRAME_FP_OFFSET64): New define.
+	(aix_sighandle_frame_cache): New Function.
+	(aix_sighandle_frame_this_id): New Function.
+	(aix_sighandle_frame_prev_register): New Function.
+	(aix_sighandle_frame_sniffer): New Function.
+	(aix_sighandle_frame_unwind): New global variable.
+	(rs6000_aix_init_osabi): Install new frame unwinder.
+
 2018-10-31  Sergio Durigan Junior  <sergiodj@redhat.com>
 
 	PR gdb/23835
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index 50a146a..4528cb2 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -38,6 +38,8 @@
 #include "solib-aix.h"
 #include "target-float.h"
 #include "xml-utils.h"
+#include "trad-frame.h"
+#include "frame-unwind.h"
 
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
@@ -45,11 +47,122 @@
    the signal handler doesn't save this register, so we have to
    access the sigcontext structure via an offset from the signal handler
    frame.
-   The following constants were determined by experimentation on AIX 3.2.  */
+   The following constants were determined by experimentation on AIX 3.2.
+
+   sigcontext structure have the mstsave saved under the
+   sc_jmpbuf.jmp_context. STKMIN(minimum stack size) is 56 for 32-bit
+   processes, and iar offset under sc_jmpbuf.jmp_context is 40.
+   ie offsetof(struct sigcontext, sc_jmpbuf.jmp_context.iar).
+   so PC offset in this case is STKMIN+iar offset, which is 96. */
+
 #define SIG_FRAME_PC_OFFSET 96
 #define SIG_FRAME_LR_OFFSET 108
+/* STKMIN+grp1 offset, which is 56+228=284 */
 #define SIG_FRAME_FP_OFFSET 284
 
+/* 64 bit process.
+   STKMIN64  is 112 and iar offset is 312. So 112+312=424 */
+#define SIG_FRAME_LR_OFFSET64 424
+/* STKMIN64+grp1 offset. 112+56=168 */
+#define SIG_FRAME_FP_OFFSET64 168
+
+static struct trad_frame_cache *
+aix_sighandle_frame_cache (struct frame_info *this_frame,
+			   void **this_cache)
+{
+  LONGEST backchain;
+  CORE_ADDR base, base_orig, func;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct trad_frame_cache *this_trad_cache;
+
+  if ((*this_cache) != NULL)
+    return (struct trad_frame_cache *) (*this_cache);
+
+  this_trad_cache = trad_frame_cache_zalloc (this_frame);
+  (*this_cache) = this_trad_cache;
+
+  base = get_frame_register_unsigned (this_frame,
+                                      gdbarch_sp_regnum (gdbarch));
+  base_orig = base;
+
+  if (tdep->wordsize == 4)
+    {
+      func = read_memory_unsigned_integer (base_orig +
+					   SIG_FRAME_PC_OFFSET + 8,
+					   tdep->wordsize, byte_order);
+      safe_read_memory_integer (base_orig + SIG_FRAME_FP_OFFSET + 8,
+				tdep->wordsize, byte_order, &backchain);
+      base = (CORE_ADDR)backchain;
+    }
+  else
+    {
+      func = read_memory_unsigned_integer (base_orig +
+					   SIG_FRAME_LR_OFFSET64,
+					   tdep->wordsize, byte_order);
+      safe_read_memory_integer (base_orig + SIG_FRAME_FP_OFFSET64,
+				tdep->wordsize, byte_order, &backchain);
+      base = (CORE_ADDR)backchain;
+    }
+
+  trad_frame_set_reg_value (this_trad_cache, gdbarch_pc_regnum (gdbarch), func);
+  trad_frame_set_reg_value (this_trad_cache, gdbarch_sp_regnum (gdbarch), base);
+
+  if (tdep->wordsize == 4)
+    trad_frame_set_reg_addr (this_trad_cache, tdep->ppc_lr_regnum,
+                             base_orig + 0x38 + 52 + 8);
+  else
+    trad_frame_set_reg_addr (this_trad_cache, tdep->ppc_lr_regnum,
+                             base_orig + 0x70 + 320);
+
+  trad_frame_set_id (this_trad_cache, frame_id_build (base, func));
+  trad_frame_set_this_base (this_trad_cache, base);
+
+  return this_trad_cache;
+}
+
+static void
+aix_sighandle_frame_this_id (struct frame_info *this_frame,
+			     void **this_prologue_cache,
+			     struct frame_id *this_id)
+{
+  struct trad_frame_cache *this_trad_cache
+    = aix_sighandle_frame_cache (this_frame, this_prologue_cache);
+  trad_frame_get_id (this_trad_cache, this_id);
+}
+
+static struct value *
+aix_sighandle_frame_prev_register (struct frame_info *this_frame,
+				   void **this_prologue_cache, int regnum)
+{
+  struct trad_frame_cache *this_trad_cache
+    = aix_sighandle_frame_cache (this_frame, this_prologue_cache);
+  return trad_frame_get_register (this_trad_cache, this_frame, regnum);
+}
+
+int
+aix_sighandle_frame_sniffer (const struct frame_unwind *self,
+			     struct frame_info *this_frame,
+			     void **this_prologue_cache)
+{
+  CORE_ADDR pc = get_frame_pc (this_frame);
+  if (pc && pc < AIX_TEXT_SEGMENT_BASE)
+    return 1;
+
+  return 0;
+}
+
+/* AIX signal handler frame unwinder */
+
+static const struct frame_unwind aix_sighandle_frame_unwind = {
+  SIGTRAMP_FRAME,
+  default_frame_unwind_stop_reason,
+  aix_sighandle_frame_this_id,
+  aix_sighandle_frame_prev_register,
+  NULL,
+  aix_sighandle_frame_sniffer
+};
 
 /* Core file support.  */
 
@@ -1061,6 +1174,7 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_auto_wide_charset (gdbarch, rs6000_aix_auto_wide_charset);
 
   set_solib_ops (gdbarch, &solib_aix_so_ops);
+  frame_unwind_append_unwinder (gdbarch, &aix_sighandle_frame_unwind);
 }
 
 void
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 575364f..241bf80 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-11-01  Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
+
+	* gdb.arch/aix-sighandle.c: New file.
+	* gdb.arch/aix-sighandle.exp: New file.
+
 2018-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* gdb.arch/riscv-reg-aliases.exp: Rewrite to take account of float
diff --git a/gdb/testsuite/gdb.arch/aix-sighandle.c b/gdb/testsuite/gdb.arch/aix-sighandle.c
new file mode 100644
index 0000000..a889e7e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aix-sighandle.c
@@ -0,0 +1,35 @@
+/* Copyright 2018 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+
+void sig_handle_aix (int signo)
+{
+  printf ("signal is: %d\n", signo);
+}
+
+void foo()
+{
+  char *ptr;
+  signal (SIGSEGV, sig_handle_aix);
+  strcpy (ptr, "signal");
+}
+
+int main()
+{
+  foo ();
+}
diff --git a/gdb/testsuite/gdb.arch/aix-sighandle.exp b/gdb/testsuite/gdb.arch/aix-sighandle.exp
new file mode 100644
index 0000000..a401ff7
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aix-sighandle.exp
@@ -0,0 +1,43 @@
+# Copyright 2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if {![istarget "powerpc*-*-aix*"]} {
+    return
+}
+
+if { [prepare_for_testing "failed to prepare" aix-sighandle aix-sighandle.c] } {
+    return -1
+}
+
+set srcfile aix-sighandle.c
+set binfile aix-sighandle
+
+gdb_test "break sig_handle_aix" \
+     "Breakpoint.1.at.*:.file.*$srcfile,.line.22." \
+     "breakpoint sig_handle_aix"
+gdb_test "run" \
+  "Starting.program:.*$binfile.*\r\nProgram.received.signal.SIGSEGV,.*\r\n.*.in.foo.*.at.*$srcfile:29.*" \
+  "run to breakpoint sig_handle_aix"
+
+gdb_test "continue" \
+  "Continuing.*Breakpoint.1,.sig_handle_aix..signo=11..at.*$srcfile:22.*" \
+  "continue to breakpoint sig_handle_aix"
+
+gdb_test_sequence "backtrace" "backtrace for sighandle" {
+  "\[\r\n\]+#0 .* sig_handle_aix \\(signo=11\\) at "
+  "\[\r\n\]+#1 .* .signal.handler.called."
+  "\[\r\n\]+#2 .* foo \\(\\) at "
+  "\[\r\n\]+#3 .* main \\(\\) at "
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]