diff options
author | John David Anglin <danglin@gcc.gnu.org> | 2014-10-26 14:46:14 +0000 |
---|---|---|
committer | John David Anglin <danglin@gcc.gnu.org> | 2014-10-26 14:46:14 +0000 |
commit | ef2810c14536560e0e929c58e80719b399176afd (patch) | |
tree | 60e477c920c2141bd940ae8fe0d6188c2b545b27 /libgcc | |
parent | d44f6d93470c7a689fe0836b18f0aa01cca99cb8 (diff) | |
download | gcc-ef2810c14536560e0e929c58e80719b399176afd.zip gcc-ef2810c14536560e0e929c58e80719b399176afd.tar.gz gcc-ef2810c14536560e0e929c58e80719b399176afd.tar.bz2 |
linux-unwind.h (pa32_read_access_ok): New function.
* config/pa/linux-unwind.h (pa32_read_access_ok): New function.
(pa32_fallback_frame_state): Use pa32_read_access_ok to check if
memory read accesses are ok.
From-SVN: r216716
Diffstat (limited to 'libgcc')
-rw-r--r-- | libgcc/ChangeLog | 6 | ||||
-rw-r--r-- | libgcc/config/pa/linux-unwind.h | 34 |
2 files changed, 34 insertions, 6 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index d1a3b73..36a63bc 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,9 @@ +2014-10-26 John David Anglin <danglin@gcc.gnu.org> + + * config/pa/linux-unwind.h (pa32_read_access_ok): New function. + (pa32_fallback_frame_state): Use pa32_read_access_ok to check if + memory read accesses are ok. + 2014-10-25 Joseph Myers <joseph@codesourcery.com> * configure.ac (ppc_fp_type): Set variable on powerpc*-*-linux*. diff --git a/libgcc/config/pa/linux-unwind.h b/libgcc/config/pa/linux-unwind.h index 9939f61..98289a7 100644 --- a/libgcc/config/pa/linux-unwind.h +++ b/libgcc/config/pa/linux-unwind.h @@ -32,6 +32,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include <signal.h> #include <sys/ucontext.h> +/* Return TRUE if read access to *P is allowed. */ + +static inline long +pa32_read_access_ok (void *p) +{ + long ret; + + __asm__ ("proberi (%1),3,%0" : "=r" (ret) : "r" (p) :); + return ret; +} + /* Unfortunately, because of various bugs and changes to the kernel, we have several cases to deal with. @@ -48,7 +59,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see tell us how to locate the sigcontext structure. Note that with a 2.4 64-bit kernel, the signal context is not properly - passed back to userspace so the unwind will not work correctly. */ + passed back to userspace so the unwind will not work correctly. + + There is also a bug in various glibc versions. The (CONTEXT)->ra + for the outermost frame is not marked as undefined, so we need to + check whether read access is allowed for all the accesses used in + searching for the signal trampoline. */ #define MD_FALLBACK_FRAME_STATE_FOR pa32_fallback_frame_state @@ -73,14 +89,17 @@ pa32_fallback_frame_state (struct _Unwind_Context *context, e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 08000240 nop */ - if (pc[0] == 0x34190000 || pc[0] == 0x34190002) + if (pa32_read_access_ok (pc) + && (pc[0] == 0x34190000 || pc[0] == 0x34190002)) off = 4*4; - else if (pc[4] == 0x34190000 || pc[4] == 0x34190002) + else if (pa32_read_access_ok (&pc[4]) + && (pc[4] == 0x34190000 || pc[4] == 0x34190002)) { pc += 4; off = 10 * 4; } - else if (pc[5] == 0x34190000 || pc[5] == 0x34190002) + else if (pa32_read_access_ok (&pc[5]) + && (pc[5] == 0x34190000 || pc[5] == 0x34190002)) { pc += 5; off = 10 * 4; @@ -96,13 +115,16 @@ pa32_fallback_frame_state (struct _Unwind_Context *context, word boundary and we can then determine the frame offset. */ sp = (unsigned long)context->ra; pc = (unsigned int *)sp; - if ((pc[0] == 0x34190000 || pc[0] == 0x34190002) && (sp & 4)) + if ((sp & 4) + && pa32_read_access_ok (pc) + && (pc[0] == 0x34190000 || pc[0] == 0x34190002)) off = 5 * 4; else return _URC_END_OF_STACK; } - if (pc[1] != 0x3414015a + if (!pa32_read_access_ok (&pc[3]) + || pc[1] != 0x3414015a || pc[2] != 0xe4008200 || pc[3] != 0x08000240) return _URC_END_OF_STACK; |