This is the mail archive of the gdb-patches@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]

add support for `S´ augmentation in dwarf2 debug info


Jakub Jelinek has recently introduced support in GCC for unwinding
frames with the `S´ augmentation, used to denote signal stack frames.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208

Although GDB already does a lot of grunt work in recognizing signal
stack frames to avoid the same kind of unwinding problem, it could
take advantage of this to (a) remove machine-specific code that does
so, when the augmentation is widely available, and (b) speed up
recognizing such frames when it is only partially available.

This patch introduces code to recognize and take advantage of the "S"
augmentation, but makes no effort to remove existing machine-specific
code.  The testcase probably already worked without the change, but
it's good to have it there to avoid regressions when someone decides
to experiment with taking code out.

Ok to install?  Tested on amd64-linux-gnu.

for gdb/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2-frame.c (struct dwarf2_cie): Add signal_frame field.
	(dwarf2_frame_sniffer): Use it.
	(decode_frame_entry_1): Set it according to augmentation "S".

for gdb/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gdb.dwarf2/signal-augm.exp: New test.
	* gdb.dwarf2/signal-augm.c, gdb.dwarf2/signal-augm.S: Its sources.

Index: gdb/dwarf2-frame.c
===================================================================
--- gdb/dwarf2-frame.c.orig	2006-03-03 11:51:41.000000000 -0300
+++ gdb/dwarf2-frame.c	2006-03-03 11:57:45.000000000 -0300
@@ -69,6 +69,9 @@ struct dwarf2_cie
   /* True if a 'z' augmentation existed.  */
   unsigned char saw_z_augmentation;
 
+  /* True if an 'S' augmentation existed.  */
+  unsigned char signal_frame;
+
   struct dwarf2_cie *next;
 };
 
@@ -1032,15 +1035,17 @@ dwarf2_frame_sniffer (struct frame_info 
      function.  frame_pc_unwind(), for a no-return next function, can
      end up returning something past the end of this function's body.  */
   CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame);
-  if (!dwarf2_frame_find_fde (&block_addr))
+  struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr);
+  if (!fde)
     return NULL;
 
   /* On some targets, signal trampolines may have unwind information.
      We need to recognize them so that we set the frame type
      correctly.  */
 
-  if (dwarf2_frame_signal_frame_p (get_frame_arch (next_frame),
-				   next_frame))
+  if (fde->cie->signal_frame
+      || dwarf2_frame_signal_frame_p (get_frame_arch (next_frame),
+				      next_frame))
     return &dwarf2_signal_frame_unwind;
 
   return &dwarf2_frame_unwind;
@@ -1500,6 +1505,10 @@ decode_frame_entry_1 (struct comp_unit *
          depends on the target address size.  */
       cie->encoding = DW_EH_PE_absptr;
 
+      /* We'll determine the final value later, but we need to
+	 initialize it conservatively.  */
+      cie->signal_frame = 0;
+
       /* Check version number.  */
       cie_version = read_1_byte (unit->abfd, buf);
       if (cie_version != 1 && cie_version != 3)
@@ -1578,6 +1587,17 @@ decode_frame_entry_1 (struct comp_unit *
 	      augmentation++;
 	    }
 
+	  /* "S" indicates a signal frame, such that the return
+	     address must not be decremented to locate the call frame
+	     info for the previous frame; it might even be the first
+	     instruction of a function, so decrementing it would take
+	     us to a different function.  */
+	  else if (*augmentation == 'S')
+	    {
+	      cie->signal_frame = 1;
+	      augmentation++;
+	    }
+
 	  /* Otherwise we have an unknown augmentation.
 	     Bail out unless we saw a 'z' prefix.  */
 	  else
Index: gdb/testsuite/gdb.dwarf2/signal-augm.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/signal-augm.S	2006-03-03 11:57:45.000000000 -0300
@@ -0,0 +1,207 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2006  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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Jakub Jelinek, as testcase for GCC PR 26208.  */
+
+	.globl fn3
+	.type	fn3, @function
+#ifdef __powerpc64__
+	.section ".opd","aw"
+	.align	3
+fn3:
+	.quad   .L.fn3,.TOC.@tocbase,0
+	.text
+.L.fn3:
+#else
+	.text
+	.p2align 4,,15
+fn3:
+#endif
+	.cfi_startproc
+#if defined __x86_64__
+	movl	$10, %eax
+	movl	$11, %ecx
+1:	pushq	%rax
+	.cfi_adjust_cfa_offset 8
+	pushq	%rcx
+	.cfi_adjust_cfa_offset 8
+	popq	%rax
+	.cfi_adjust_cfa_offset -8
+	popq	%rcx
+	.cfi_adjust_cfa_offset -8
+	pushq	%rax
+	.cfi_adjust_cfa_offset 8
+	pushq	%rcx
+	.cfi_adjust_cfa_offset 8
+	popq	%rax
+	.cfi_adjust_cfa_offset -8
+	popq	%rcx
+	.cfi_adjust_cfa_offset -8
+	pushq	%rax
+	.cfi_adjust_cfa_offset 8
+	pushq	%rcx
+	.cfi_adjust_cfa_offset 8
+	popq	%rax
+	.cfi_adjust_cfa_offset -8
+	popq	%rcx
+	.cfi_adjust_cfa_offset -8
+	pushq	%rax
+	.cfi_adjust_cfa_offset 8
+	pushq	%rcx
+	.cfi_adjust_cfa_offset 8
+	popq	%rax
+	.cfi_adjust_cfa_offset -8
+	popq	%rcx
+	.cfi_adjust_cfa_offset -8
+	jmp	1b
+#elif defined __i386__
+	movl	$10, %eax
+	movl	$11, %ecx
+1:	pushl	%eax
+	.cfi_adjust_cfa_offset 4
+	pushl	%ecx
+	.cfi_adjust_cfa_offset 4
+	popl	%eax
+	.cfi_adjust_cfa_offset -4
+	popl	%ecx
+	.cfi_adjust_cfa_offset -4
+	pushl	%eax
+	.cfi_adjust_cfa_offset 4
+	pushl	%ecx
+	.cfi_adjust_cfa_offset 4
+	popl	%eax
+	.cfi_adjust_cfa_offset -4
+	popl	%ecx
+	.cfi_adjust_cfa_offset -4
+	pushl	%eax
+	.cfi_adjust_cfa_offset 4
+	pushl	%ecx
+	.cfi_adjust_cfa_offset 4
+	popl	%eax
+	.cfi_adjust_cfa_offset -4
+	popl	%ecx
+	.cfi_adjust_cfa_offset -4
+	pushl	%eax
+	.cfi_adjust_cfa_offset 4
+	pushl	%ecx
+	.cfi_adjust_cfa_offset 4
+	popl	%eax
+	.cfi_adjust_cfa_offset -4
+	popl	%ecx
+	.cfi_adjust_cfa_offset -4
+	jmp	1b
+#elif defined __powerpc64__
+	mflr	0
+	mr	9,1
+	std	0,16(1)
+	.cfi_offset lr, 8
+	bl	1f
+1:	stdu	1,-64(1)
+	.cfi_adjust_cfa_offset 64
+	stdu	9,-64(1)
+	.cfi_adjust_cfa_offset 64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	stdu	1,-64(1)
+	.cfi_adjust_cfa_offset 64
+	stdu	9,-64(1)
+	.cfi_adjust_cfa_offset 64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	b	1b
+#elif defined __powerpc__
+	mflr	0
+	mr	9,1
+	stwu	1,-16(1)
+	.cfi_adjust_cfa_offset 16
+	stw	0,20(1)
+	.cfi_offset lr, 4
+	bl	1f
+1:	stwu	9,-64(1)
+	.cfi_adjust_cfa_offset 64
+	stwu	9,-64(1)
+	.cfi_adjust_cfa_offset 64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	stwu	9,-64(1)
+	.cfi_adjust_cfa_offset 64
+	stwu	9,-64(1)
+	.cfi_adjust_cfa_offset 64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	addi	1,1,64
+	.cfi_adjust_cfa_offset -64
+	b	1b
+#elif defined __s390x__
+	stmg	%r14,%r15,112(%r15)
+	.cfi_offset %r14, -48
+	.cfi_offset %r15, -40
+	lghi	%r14,6
+1:	aghi	%r15,-160
+	.cfi_adjust_cfa_offset	160
+	aghi	%r15,-160
+	.cfi_adjust_cfa_offset	160
+	aghi	%r15,160
+	.cfi_adjust_cfa_offset	-160
+	aghi	%r15,160
+	.cfi_adjust_cfa_offset	-160
+	aghi	%r15,-160
+	.cfi_adjust_cfa_offset	160
+	aghi	%r15,-160
+	.cfi_adjust_cfa_offset	160
+	aghi	%r15,160
+	.cfi_adjust_cfa_offset	-160
+	aghi	%r15,160
+	.cfi_adjust_cfa_offset	-160
+	j	1b
+#elif defined __s390__
+	stm	%r14,%r15,56(%r15)
+	.cfi_offset %r14, -40
+	.cfi_offset %r15, -36
+	lgi	%r14,6
+1:	ahi	%r15,-96
+	.cfi_adjust_cfa_offset	96
+	ahi	%r15,-96
+	.cfi_adjust_cfa_offset	96
+	ahi	%r15,96
+	.cfi_adjust_cfa_offset	-96
+	ahi	%r15,96
+	.cfi_adjust_cfa_offset	-96
+	ahi	%r15,-96
+	.cfi_adjust_cfa_offset	96
+	ahi	%r15,-96
+	.cfi_adjust_cfa_offset	96
+	ahi	%r15,96
+	.cfi_adjust_cfa_offset	-96
+	ahi	%r15,96
+	.cfi_adjust_cfa_offset	-96
+	j	1b
+#endif
+	.cfi_endproc
+#ifdef __powerpc64__
+	.size	fn3, . - .L.fn3
+#else
+	.size	fn3, .-fn3
+#endif
+	.section	.note.GNU-stack,"",@progbits
Index: gdb/testsuite/gdb.dwarf2/signal-augm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/signal-augm.c	2006-03-03 11:57:45.000000000 -0300
@@ -0,0 +1,198 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2006  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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Written by Jakub Jelinek, as testcase for GCC PR 26208.  GDB does
+   not need all of it, since all we do is to try to recognize signal
+   stack frames.  If the compiler does not support the S augmentation
+   used to denote stack frames, and GDB does not otherwise recognize
+   stack frames, the test fails.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+                   _Unwind_Exception_Class exc_class,
+                   struct _Unwind_Exception *exc_obj,
+                   struct _Unwind_Context *context,
+                   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void
+force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+  exc->exception_cleanup = 0;
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+
+  abort ();
+}
+
+int count;
+
+static void
+counter (void *p __attribute__((unused)))
+{
+  ++count;
+}
+
+static void
+handler (void *p __attribute__((unused)))
+{
+  if (count != 2)
+    abort ();
+  _exit (0);
+}
+
+static int __attribute__((noinline))
+fn5 (void)
+{
+  char dummy __attribute__((cleanup (counter)));
+  force_unwind ();
+  return 0;
+}
+
+static void
+fn4 (int sig, siginfo_t *info, void *ctx)
+{
+  char dummy __attribute__((cleanup (counter)));
+  fn5 ();
+}
+
+extern void fn3 (long a, long b, long c, long d, long e, long f, long g);
+
+static int __attribute__((noinline))
+fn2 (void)
+{
+  fn3 (1, 2, 3, 4, 5, 6, 7);
+  return 0;
+}
+
+static int __attribute__((noinline))
+fn1 (void)
+{
+#if defined __i386__ && defined SIGACTION_DIRECT_SYSCALL
+  struct i386_kernel_sigaction
+    {
+      void (*k_sa_handler) (int, siginfo_t *, void *);
+      unsigned long k_sa_flags;
+      void (*sa_restorer) (void);
+      unsigned long long k_sa_mask;
+    } s;
+  extern void __cleanup12_rt_sigreturn (void);
+  s.k_sa_handler = fn4;
+  s.k_sa_mask = 0;
+  s.k_sa_flags = 0x4000000 | SA_RESETHAND | SA_SIGINFO;
+  s.sa_restorer = __cleanup12_rt_sigreturn;
+  asm volatile (".subsection 1; nop; __cleanup12_rt_sigreturn:"
+		"movl %0, %%eax; int $0x80; .previous"
+		: : "i" (__NR_rt_sigreturn));
+  syscall (SYS_rt_sigaction, SIGUSR1, &s, NULL, 8);
+#else
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_sigaction = fn4;
+  s.sa_flags = SA_RESETHAND | SA_SIGINFO;
+  sigaction (SIGUSR1, &s, NULL);
+#endif
+  fn2 ();
+  return 0;
+}
+
+static void *
+tf (void *arg)
+{
+  char dummy __attribute__((cleanup (handler)));
+  (void) arg;
+  fn1 ();
+  return 0;
+}
+
+void
+do_test (void)
+{
+  pthread_t th;
+  struct timespec ts;
+  if (pthread_create (&th, 0, tf, 0))
+    {
+      fputs ("pthread_create failed\n", stderr);
+      _exit (1);
+    }
+  ts.tv_sec = 1;
+  ts.tv_nsec = 0;
+  nanosleep (&ts, NULL);
+  if (pthread_kill (th, SIGUSR1))
+    {
+      fputs ("pthread_kill failed\n", stderr);
+      _exit (1);
+    }
+  ts.tv_sec = 3;
+  ts.tv_nsec = 0;
+  nanosleep (&ts, NULL);
+  _exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+  int i, failures = 0, status;
+  if (argc == 2 && strcmp (argv[1], "-d") == 0)
+    do_test ();
+  else
+    for (i = 0; i < 50; i++)
+      {
+	pid_t pid = fork ();
+	if (pid < 0)
+	  {
+	    perror ("fork");
+	    failures++;
+	  }
+	else if (pid == 0)
+	  do_test ();
+	else if (waitpid (pid, &status, 0) < 0)
+	  {
+	    perror ("waitpid");
+	    failures++;
+	  }
+	else if (! WIFEXITED (status) || WEXITSTATUS (status))
+	  {
+	    fprintf (stderr, "Failure in round %d\n", i);
+	    failures++;
+	  }
+      }
+  if (failures)
+    abort ();
+  return 0;
+}
Index: gdb/testsuite/gdb.dwarf2/signal-augm.exp
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.dwarf2/signal-augm.exp	2006-03-03 12:08:40.000000000 -0300
@@ -0,0 +1,77 @@
+# Copyright 2006 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Alexandre Oliva <aoliva@redhat.com>
+
+if $tracelevel then {
+	strace $tracelevel
+	}
+
+set prms_id 0
+set bug_id 0
+
+# signal-augm.S needs hand-coded assembly
+if {![istarget i*86-*-linux*]
+    && ![istarget x86_64-*-linux*]
+    && ![istarget powerpc*-*-linux*]
+    && ![istarget s390*-*-linux*]} {
+    return -1;
+}
+
+if [get_compiler_info "ignored"] {
+    return -1
+}
+
+if {$gcc_compiled == 0} {
+    return -1
+}
+
+set testfile "signal-augm"
+
+set srcbasename ${srcdir}/${subdir}/${testfile}
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcbasename}.c ${srcbasename}.S" "${binfile}" executable [list debug "additional_flags=-pthread -fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2"]] != ""} {
+    return -1;
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if [target_info exists gdb_stub] {
+    gdb_step_for_stub;
+}
+
+gdb_test "break fn5" "Breakpoint.*at.*" "breakpoint fn5"
+
+set test "stop at fn5"
+gdb_test_multiple "run -d" "$test" {
+    -re "received signal" {
+	send_gdb "continue\n"
+    }
+    -re "Breakpoint 1" {
+	pass "$test"
+    }
+}
+
+gdb_test "backtrace" ".*\#0 .* fn5 .*\#1 .* fn4 .*\#2 .*signal handler.*\#3 .* fn3 .*\#4 .* fn2 .*\#5 .* fn1 .*\#6 .* tf.*" "$test"
+
+return 0
+
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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