diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2012-01-09 09:50:19 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-01-09 09:50:19 +0000 |
commit | bf4db96c93ce31bbad0984724f9ab2d6695ca9ee (patch) | |
tree | 631f523670cea7578486ca6c077bf976188a3b09 | |
parent | b492b6862ef38c3a8c7a67f4c410dcf69434507d (diff) | |
download | gcc-bf4db96c93ce31bbad0984724f9ab2d6695ca9ee.zip gcc-bf4db96c93ce31bbad0984724f9ab2d6695ca9ee.tar.gz gcc-bf4db96c93ce31bbad0984724f9ab2d6695ca9ee.tar.bz2 |
re PR ada/41929 (64-bit null_pointer_deref1 gnat.dg test consumes all available memory)
PR ada/41929
* config/sparc/sol2-unwind.h (sparc64_is_sighandler): Remove SAVPC and
add CFA. Revert back to old code for Solaris 8+ multi-threaded.
(sparc_is_sighandler): Likewise.
(MD_FALLBACK_FRAME_STATE_FOR): Adjust call to IS_SIGHANDLER.
From-SVN: r183005
-rw-r--r-- | libgcc/ChangeLog | 8 | ||||
-rw-r--r-- | libgcc/config/sparc/sol2-unwind.h | 129 |
2 files changed, 96 insertions, 41 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 90cc782d..3f23e72 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2012-01-09 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/41929 + * config/sparc/sol2-unwind.h (sparc64_is_sighandler): Remove SAVPC and + add CFA. Revert back to old code for Solaris 8+ multi-threaded. + (sparc_is_sighandler): Likewise. + (MD_FALLBACK_FRAME_STATE_FOR): Adjust call to IS_SIGHANDLER. + 2012-01-06 Tristan Gingold <gingold@adacore.com> * config/ia64/t-ia64 (LIB1ASMFUNCS): Move backward diff --git a/libgcc/config/sparc/sol2-unwind.h b/libgcc/config/sparc/sol2-unwind.h index 54a97b0..ea4c541 100644 --- a/libgcc/config/sparc/sol2-unwind.h +++ b/libgcc/config/sparc/sol2-unwind.h @@ -1,5 +1,5 @@ /* DWARF2 EH unwinding support for SPARC Solaris. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -34,7 +34,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define IS_SIGHANDLER sparc64_is_sighandler static int -sparc64_is_sighandler (unsigned int *pc, unsigned int *savpc, int *nframes) +sparc64_is_sighandler (unsigned int *pc, void *cfa, int *nframes) { if (/* Solaris 8 - single-threaded ---------------------------- @@ -110,38 +110,59 @@ sparc64_is_sighandler (unsigned int *pc, unsigned int *savpc, int *nframes) && pc[ 0] == 0x81c7e008 && pc[ 1] == 0x81e80000) { - if (/* Solaris 8 /usr/lib/sparcv9/libthread.so.1 - ------------------------------------------ - Before patch 108827-08: - <sigacthandler+1760>: st %g4, [ %i1 + 0x1c ] - - Since patch 108827-08: - <sigacthandler+1816>: st %l0, [ %i4 + 0x10 ] */ - savpc[-1] == 0xc826601c - || savpc[-1] == 0xe0272010) + /* We have observed different calling frames among different + versions of the operating system, so that we need to + discriminate using the upper frame. We look for the return + address of the caller frame (there is an offset of 15 double + words between the frame address and the place where this return + address is stored) in order to do some more pattern matching. */ + unsigned int cuh_pattern + = *(unsigned int *)(*(unsigned long *)(cfa + 15*8) - 4); + + if (cuh_pattern == 0xd25fa7ef) { - /* We need to move up three frames: + /* This matches the call_user_handler pattern for Solaris 10. + There are 2 cases so we look for the return address of the + caller's caller frame in order to do more pattern matching. */ + unsigned int sah_pattern + = *(unsigned int *)(*(unsigned long *)(cfa + 176 + 15*8) - 4); + + if (sah_pattern == 0x92100019) + /* This is the same setup as for Solaris 9, see below. */ + *nframes = 3; + else + /* The sigacthandler frame isn't present in the chain. + We need to move up two frames: <signal handler> <-- context->cfa __sighndlr - sigacthandler + call_user_handler frame <kernel> - */ - *nframes = 2; + */ + *nframes = 2; } - else /* Solaris 8 /usr/lib/lwp/sparcv9/libthread.so.1, Solaris 9+ - ---------------------------------------------------------- */ - { - /* We need to move up three frames: + else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x94100013) + /* This matches the call_user_handler pattern for Solaris 9 and + for Solaris 8 running inside Solaris Containers respectively + We need to move up three frames: <signal handler> <-- context->cfa __sighndlr call_user_handler sigacthandler <kernel> - */ - *nframes = 3; - } + */ + *nframes = 3; + else + /* This is the default Solaris 8 case. + We need to move up two frames: + + <signal handler> <-- context->cfa + __sighndlr + sigacthandler + <kernel> + */ + *nframes = 2; return 1; } @@ -181,7 +202,7 @@ sparc64_frob_update_context (struct _Unwind_Context *context, #define IS_SIGHANDLER sparc_is_sighandler static int -sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes) +sparc_is_sighandler (unsigned int *pc, void *cfa, int *nframes) { if (/* Solaris 8, 9 - single-threaded ------------------------------- @@ -209,7 +230,7 @@ sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes) && pc[-1] == 0x9410001a && pc[ 0] == 0x80a62008) { - /* Need to move up one frame: + /* We need to move up one frame: <signal handler> <-- context->cfa sigacthandler @@ -240,7 +261,7 @@ sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes) && pc[ 1] == 0x81e80000 && pc[ 2] == 0x80a26000) { - /* Need to move up one frame: + /* We need to move up one frame: <signal handler> <-- context->cfa __libthread_segvhdlr @@ -267,33 +288,59 @@ sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes) && pc[ 0] == 0x81c7e008 && pc[ 1] == 0x81e80000) { - if (/* Solaris 8 /usr/lib/libthread.so.1 - ---------------------------------- - <sigacthandler+1796>: mov %i0, %o0 */ - savpc[-1] == 0x90100018) + /* We have observed different calling frames among different + versions of the operating system, so that we need to + discriminate using the upper frame. We look for the return + address of the caller frame (there is an offset of 15 words + between the frame address and the place where this return + address is stored) in order to do some more pattern matching. */ + unsigned int cuh_pattern + = *(unsigned int *)(*(unsigned int *)(cfa + 15*4) - 4); + + if (cuh_pattern == 0xd407a04c) { - /* We need to move up two frames: + /* This matches the call_user_handler pattern for Solaris 10. + There are 2 cases so we look for the return address of the + caller's caller frame in order to do more pattern matching. */ + unsigned int sah_pattern + = *(unsigned int *)(*(unsigned int *)(cfa + 96 + 15*4) - 4); + + if (sah_pattern == 0x92100019) + /* This is the same setup as for Solaris 9, see below. */ + *nframes = 3; + else + /* The sigacthandler frame isn't present in the chain. + We need to move up two frames: <signal handler> <-- context->cfa __sighndlr - sigacthandler + call_user_handler frame <kernel> - */ - *nframes = 2; + */ + *nframes = 2; } - else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+ - -------------------------------------------------- */ - { - /* We need to move up three frames: + else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x9410001b) + /* This matches the call_user_handler pattern for Solaris 9 and + for Solaris 8 running inside Solaris Containers respectively. + We need to move up three frames: <signal handler> <-- context->cfa __sighndlr call_user_handler sigacthandler <kernel> - */ - *nframes = 3; - } + */ + *nframes = 3; + else + /* This is the default Solaris 8 case. + We need to move up two frames: + + <signal handler> <-- context->cfa + __sighndlr + sigacthandler + <kernel> + */ + *nframes = 2; return 1; } @@ -331,7 +378,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, return _URC_NO_REASON; } - if (IS_SIGHANDLER (pc, (unsigned int *)fp->fr_savpc, &nframes)) + if (IS_SIGHANDLER (pc, this_cfa, &nframes)) { struct handler_args { struct frame frwin; |