public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Sangamesh Mallayya" <sangamesh.swamy@in.ibm.com>
To: gdb-patches@sourceware.org, "Ulrich Weigand" <Ulrich.Weigand@de.ibm.com>
Subject: [PATCH] Adding support for reding signal handler frame in AIX
Date: Wed, 29 Aug 2018 05:54:00 -0000	[thread overview]
Message-ID: <OF4A567E9C.67455645-ON652582F8.001F64A7-652582F8.00207854@notes.na.collabserv.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 3617 bytes --]

Hi All,

Attaching the patch for adding signal handler support 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 
sigconext saved on the 
stack, similarly the LR.

As backchain at an offset 0 will be 0, because we will have sigconext 
saved after the minimum stack size. 
So, 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.

This can be demonstrated using the below sample program.

# cat aix-sighandle.c
#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();
}


without patch
-----------------

Reading symbols from ./aix-sighandle...done.
(gdb) br sig_handle_aix
Breakpoint 1 at 0x100006bc: file aix-sighandle.c, line 7.
(gdb) r
Starting program: aix-sighandle 

Program received signal SIGSEGV, Segmentation fault.
0x0000000100000748 in foo () at /home/binutils-gdb/gdb/aix-sighandle.c:14
14        strcpy(ptr, "signal");
(gdb) c
Continuing.

Breakpoint 1, sig_handle_aix (signo=11) at 
/home/binutils-gdb/gdb/aix-sighandle.c:7
7         printf("signal is: %d\n", signo);
(gdb) bt
#0  sig_handle_aix (signo=11) at /home/binutils-gdb/gdb/aix-sighandle.c:7
#1  0x0000000000004a94 in ?? ()
(gdb) 

with patch
-------------

Reading symbols from ./aix-sighandle...done.
(gdb) br sig_handle_aix
Breakpoint 1 at 0x100006bc: file /home/binutils-gdb/gdb/aix-sighandle.c, 
line 7.
(gdb) r
Starting program: /home/binutils-gdb/gdb/aix-sighandle 

Program received signal SIGSEGV, Segmentation fault.
0x0000000100000748 in foo () at /home/binutils-gdb/gdb/aix-sighandle.c:14
14        strcpy(ptr, "signal");
(gdb) c
Continuing.

Breakpoint 1, sig_handle_aix (signo=11) at 
/home/binutils-gdb/gdb/aix-sighandle.c:7
7         printf("signal is: %d\n", signo);
(gdb) bt
#0  sig_handle_aix (signo=11) at/home/binutils-gdb/gdb/aix-sighandle.c:7
#1  <signal handler called>
#2  0x0000000100000748 in foo () at 
/home/binutils-gdb/gdb/aix-sighandle.c:14
#3  0x000000010000079c in main () at 
/home/binutils-gdb/gdb/aix-sighandle.c:19
warning: (Internal error: pc 0x1000004f3 in read in psymtab, but not in 
symtab.)

warning: (Internal error: pc 0x1000004f4 in read in psymtab, but not in 
symtab.)

(gdb) 


Summary of the gdb.base testsuites.
I saw assertion failure not related to the fix while running the testcases 
which i will be fixing it soon.

Wrote a small testcase to run it on only AIX to test the signal handler.

Without patch
-----------------
# of expected passes            16372
# of unexpected failures        2279
# of expected failures          14
# of unresolved testcases       30
# of untested testcases         68
# of unsupported tests          37

with patch
-------------
# of expected passes            16395
# of unexpected failures        2256
# of expected failures          14
# of unresolved testcases       30
# of untested testcases         68
# of unsupported tests          37


We already had some discussion on this before and here is the link.
https://sourceware.org/ml/gdb-patches/2018-01/msg00255.html


 

Thanks,
Sangamesh

[-- Attachment #2: aix-sighandle.patch --]
[-- Type: application/octet-stream, Size: 5567 bytes --]

--- ./gdb/rs6000-aix-tdep.c_orig	2018-03-13 08:59:25 +0000
+++ ./gdb/rs6000-aix-tdep.c	2018-08-27 03:24:23 +0000
@@ -38,6 +38,8 @@
 #include "solib-aix.h"
 #include "target-float.h"
 #include "xml-utils.h"
+#include "tramp-frame.h"
+#include "trad-frame.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,24 @@
    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.
+
+   sigconext 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
 
 /* Core file support.  */
 
@@ -103,6 +118,104 @@
   -1 /* vrsave_offset */
 };
 
+static void 
+aix_sigtramp_cache (struct frame_info *this_frame,
+                    struct trad_frame_cache *this_cache,
+                    CORE_ADDR func, LONGEST offset,
+                    int bias)
+{
+  LONGEST backchain;
+  CORE_ADDR base, frame_base, base_orig;
+  CORE_ADDR regs;
+  CORE_ADDR gpregs;
+  CORE_ADDR fpregs;
+  int i;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int wordsize = tdep->wordsize;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  base = get_frame_register_unsigned (this_frame,
+                                      gdbarch_sp_regnum (gdbarch));
+  base_orig = base;
+  if (wordsize == 4) {
+    safe_read_memory_integer (base_orig + SIG_FRAME_FP_OFFSET + 8,
+                              wordsize, byte_order, &backchain);
+    base = (CORE_ADDR)backchain;
+  } else {
+      safe_read_memory_integer (base_orig + SIG_FRAME_FP_OFFSET64,
+				wordsize, byte_order, &backchain);
+      base = (CORE_ADDR)backchain;
+  }
+
+  trad_frame_set_reg_value (this_cache, gdbarch_pc_regnum (gdbarch), func);
+  trad_frame_set_reg_value (this_cache, gdbarch_sp_regnum (gdbarch), base);
+
+  if (wordsize == 4) {
+    trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum,
+                             base_orig + offset + 52 + 8);
+  } else {
+    trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum,
+                             base_orig + offset + 320);
+  } 
+  trad_frame_set_id (this_cache, frame_id_build (base, func));
+}
+
+static void
+aix_sigtramp_cache_init (const struct tramp_frame *self,
+			 struct frame_info *this_frame,
+			 struct trad_frame_cache *this_cache,
+			 CORE_ADDR func)
+{
+    struct gdbarch *gdbarch = get_frame_arch (this_frame);
+    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+    if (tdep->wordsize == 4)
+      aix_sigtramp_cache (this_frame, this_cache, func,
+       			  0x38 /* Minimum stack size  */,
+			  0);
+    else
+      aix_sigtramp_cache (this_frame, this_cache, func,
+     			  0x70 /* Minimum stack size.  */,
+			  0);
+}
+
+static int
+aix_validate_pc (const struct tramp_frame *self,
+		 struct frame_info *this_frame,
+		 CORE_ADDR *pc)
+{
+    struct gdbarch *gdbarch = get_frame_arch (this_frame);
+    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+    CORE_ADDR dest, frame_base;
+    frame_base = get_frame_register_unsigned (this_frame,
+				gdbarch_sp_regnum (gdbarch));
+    if (tdep->wordsize == 4)  {
+      if (*pc && *pc < AIX_TEXT_SEGMENT_BASE) {
+        *pc = read_memory_unsigned_integer
+              (frame_base + SIG_FRAME_PC_OFFSET + 8,
+              tdep->wordsize, byte_order);
+      }
+    } else {
+      if (*pc && *pc < AIX_TEXT_SEGMENT_BASE) {
+        *pc = read_memory_unsigned_integer
+	      (frame_base  + SIG_FRAME_LR_OFFSET64,
+	      tdep->wordsize, byte_order);
+      }
+    }
+    return 1;
+} 
+
+static struct tramp_frame aix_sighandler_tramp_frame = {
+  SIGTRAMP_FRAME,
+  4,
+  {
+    { TRAMP_SENTINEL_INSN },
+  },
+  aix_sigtramp_cache_init,
+  aix_validate_pc
+};
 
 /* Supply register REGNUM in the general-purpose register set REGSET
    from the buffer specified by GREGS and LEN to register cache
@@ -1083,6 +1196,7 @@
   set_gdbarch_auto_wide_charset (gdbarch, rs6000_aix_auto_wide_charset);
 
   set_solib_ops (gdbarch, &solib_aix_so_ops);
+  tramp_frame_prepend_unwinder (gdbarch, &aix_sighandler_tramp_frame);
 }
 
 void
--- ./gdb/tramp-frame.c_orig	2018-08-27 03:25:49 +0000
+++ ./gdb/tramp-frame.c	2018-08-27 03:26:24 +0000
@@ -132,6 +132,12 @@
      false on HPUX which has a signal trampoline that has a name; it can
      also be false when using an alternative signal stack.  */
   func = tramp_frame_start (tramp, this_frame, pc);
+  #if defined (_AIX)
+  if (pc <= 0x10000000) {
+      tramp->validate (tramp, this_frame, &pc);
+      func = pc;
+  }
+  #endif
   if (func == 0)
     return 0;
   tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);

[-- Attachment #3: aix-sighandle_test.c --]
[-- Type: application/octet-stream, Size: 246 bytes --]

#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();
}

[-- Attachment #4: aix-sighandle_test.exp --]
[-- Type: application/octet-stream, Size: 850 bytes --]

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.7." \
     "breakpoint sig_handle_aix"
gdb_test "run" \
  "Starting.program:.*$binfile.*\r\nProgram.received.signal.SIGSEGV,.*\r\n.*.in.foo.*.at.*$srcfile:14.*" \
  "run to breakpoint sig_handle_aix"

gdb_test "continue" \
  "Continuing.*Breakpoint.1,.sig_handle_aix..signo=11..at.*$srcfile:7.*" \
  "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 "
}

             reply	other threads:[~2018-08-29  5:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-29  5:54 Sangamesh Mallayya [this message]
2018-09-04 23:18 ` Kevin Buettner
2018-09-10  6:32   ` Sangamesh Mallayya
2018-09-10 17:34     ` Kevin Buettner
2018-09-12 13:53     ` Ulrich Weigand
2018-09-27  8:33       ` Sangamesh Mallayya
     [not found]       ` <OF4C5ED06A.3C846B3C-ON65258315.002EABF7-65258315.002F01D3@LocalDomain>
2018-10-30  7:16         ` Sangamesh Mallayya
2018-10-30 10:20           ` Ulrich Weigand
2018-10-31 10:18             ` Sangamesh Mallayya
2018-10-31 10:37               ` Ulrich Weigand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=OF4A567E9C.67455645-ON652582F8.001F64A7-652582F8.00207854@notes.na.collabserv.com \
    --to=sangamesh.swamy@in.ibm.com \
    --cc=Ulrich.Weigand@de.ibm.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).