for gdb/ChangeLog from Alexandre Oliva * 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 * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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 + +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 +