public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Adding support for reding signal handler frame in AIX
@ 2018-08-29  5:54 Sangamesh Mallayya
  2018-09-04 23:18 ` Kevin Buettner
  0 siblings, 1 reply; 10+ messages in thread
From: Sangamesh Mallayya @ 2018-08-29  5:54 UTC (permalink / raw)
  To: gdb-patches, Ulrich Weigand

[-- 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 "
}

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-10-31 10:37 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-29  5:54 [PATCH] Adding support for reding signal handler frame in AIX Sangamesh Mallayya
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

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).