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]

Re: add support for `S´ augmentation in dwarf2 debug info


> From: Alexandre Oliva <aoliva@redhat.com>
> Date: Fri, 03 Mar 2006 12:18:43 -0300
> 
> --=-=-=
> Content-Type: text/plain; charset=iso-8859-1
> Content-Transfer-Encoding: quoted-printable
> 
> Jakub Jelinek has recently introduced support in GCC for unwinding
> frames with the `S=B4 augmentation, used to denote signal stack frames.
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D26208
> 
> 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.

Hmm, removing the machine-specific code won't be possible for quite a
long time I think, but it certainly isolates us from changes made to
the signal trampolines in glibc.

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

Hmm, I'm wondering whether we should give saw_z_augmentation a more
meaningful name too (not sure if there is one though).

Here it the testcases are really Linux-specific (and yuck, that i386
sigaction hack is ugly).  Hopefully they're not too fragile.  Could
you please change bug-gdb@prep.ai.mit.edu into bug-gdb@gnu.org before
checking this in?

Thanks,

Mark

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


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