[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libunwind-devel] [patch] Fix ia64 _Unwind_GetIPInfo (GCC PR target/2788
From: |
Jan Kratochvil |
Subject: |
[Libunwind-devel] [patch] Fix ia64 _Unwind_GetIPInfo (GCC PR target/27880) |
Date: |
Fri, 17 Apr 2009 23:15:40 +0200 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
On Wed, 01 Apr 2009 17:24:08 +0200, David Mosberger-Tang wrote:
> On Wed, Apr 1, 2009 at 7:02 AM, Jakub Jelinek <address@hidden> wrote:
> > But I think on ia64 the unwinder never subtracts anything when looking up
> > FDEs
>
> That's correct. The code/unwind-info is constructed such that the IP
> never needs to be adjusted to locate the right unwind-info.
This rule may be correct for locating the right FDE.
Unfortunately the same adjusted/unadjusted return address is being used also by
__gxx_personality_v0() to locate the right call-site (the try {} block) for
unwinding. And this case is already sensitive for off-by-one PC values.
Unlike the FDE location where the function prologue + epilogue make it immune
against off-by-one PC calculations.
One can also see this __gxx_personality_v0() function operation and the
generated LSDA tables are arch-independent. Therefore even the calculation of
the return address should be done arch-independently.
Function f() from the attachment crashes with current libunwind. Compiled as:
---snip---
[.LEHB4:]
br.call.sptk.many b0 = __cxa_throw#
[.LEHE4:]
;;
.L25:
---snip---
.uleb128 .LEHB4-.LFB1412 /* cs_start */
.uleb128 .LEHE4-.LEHB4 /* cs_len */
.uleb128 .L25-.LFB1412 /* cs_ip */
.uleb128 0x1 /* cs_action */
---snip---
The current libunwind will return .LEHE4 as the return address from
__cxa_throw which will not pass the personality check for exactly only the
inner range .LEHB4 ... .LEHE4. The condition ther is:
gcc/libstdc++-v3/libsupc++/eh_personality.cc
else if (ip < info.Start + cs_start + cs_len)
Therefore suggesting to unify it with non-ia64 case which already uses:
*ip_before_insn = unw_is_signal_frame (&context->cursor);
Thanks,
Jan
diff --git a/src/Makefile.am b/src/Makefile.am
index c08fb4a..e6e3b33 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,13 +69,8 @@ libunwind_la_SOURCES_local_unwind =
\
unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c \
unwind/GetRegionStart.c unwind/GetTextRelBase.c \
unwind/RaiseException.c unwind/Resume.c \
- unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c
-
-if ARCH_IA64
-libunwind_la_SOURCES_local_unwind += ia64/unwind_GetIPInfo.c
-else
-libunwind_la_SOURCES_local_unwind += unwind/GetIPInfo.c
-endif # ARCH_IA64
+ unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c \
+ unwind/GetIPInfo.c
# _ReadULEB()/_ReadSLEB() are needed for Intel C++ 8.0 compatibility
libunwind_la_SOURCES_os_linux_local = mi/_ReadULEB.c mi/_ReadSLEB.c
diff --git a/src/ia64/unwind_GetIPInfo.c b/src/ia64/unwind_GetIPInfo.c
deleted file mode 100644
index dfdf5e8..0000000
--- a/src/ia64/unwind_GetIPInfo.c
+++ b/src/ia64/unwind_GetIPInfo.c
@@ -1,43 +0,0 @@
-/* libunwind - a platform-independent unwind library
- Copyright (C) 2009 Red Hat
- Contributed by Jan Kratochvil <address@hidden>
-
-This file is part of libunwind.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#include "../unwind/unwind-internal.h"
-
-/* gcc/unwind-dw2.c: Retrieve the return address and flag whether that IP is
- before or after first not yet fully executed instruction.
- IP_BEFORE_INSN ensures leaving IP intact as was designed for ia64. */
-
-PROTECTED unsigned long
-_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
-{
- unw_word_t val;
-
- unw_get_reg (&context->cursor, UNW_REG_IP, &val);
- *ip_before_insn = 1;
- return val;
-}
-
-unsigned long __libunwind_Unwind_GetIPInfo (struct _Unwind_Context *, int *)
- ALIAS (_Unwind_GetIPInfo);
#include <iostream>
using namespace std;
class E {
public:
const char* error;
E(const char* arg) : error(arg) { }
};
class A {
public:
int i;
// A function try block with a member
// initializer
A() try : i(0) {
throw E("Exception thrown in A()");
}
catch (E& e) {
cout << e.error << endl;
}
};
// A function try block
void f() try {
throw E("Exception thrown in f()");
}
catch (E& e) {
cout << e.error << endl;
}
void g() {
int i;
for (;;) {
printf ("In function g ()\n");
throw E("Exception thrown in g()");
}
}
int main() {
f();
// A try block
try {
for (;;) {
g();
}
}
catch (E& e ) {
// cout << e.error << endl;
}
try {
A x;
}
catch(...) { }
}