Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Alexandre Oliva <aoliva@redhat.com>
To: gdb-patches@sources.redhat.com
Subject: add support for `S´ augmentation in dwarf2 debug  info
Date: Fri, 03 Mar 2006 17:41:00 -0000	[thread overview]
Message-ID: <orbqwnpne4.fsf@free.oliva.athome.lsd.ic.unicamp.br> (raw)

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

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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdb-augmS.patch --]
[-- Type: text/x-patch, Size: 15117 bytes --]

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
+

[-- Attachment #3: Type: text/plain, Size: 249 bytes --]


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

             reply	other threads:[~2006-03-03 15:19 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-03-03 17:41 Alexandre Oliva [this message]
2006-03-04 12:05 ` Mark Kettenis
2006-03-04 14:54   ` Alexandre Oliva
2006-03-04 18:01 ` Daniel Jacobowitz
2006-03-06 15:18   ` Daniel Jacobowitz
2006-03-07 14:21   ` Alexandre Oliva
2006-03-29  0:04     ` Daniel Jacobowitz
2006-05-28  6:42       ` Alexandre Oliva

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=orbqwnpne4.fsf@free.oliva.athome.lsd.ic.unicamp.br \
    --to=aoliva@redhat.com \
    --cc=gdb-patches@sources.redhat.com \
    /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