libunwind-devel
[Top][All Lists]
Advanced

[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(...) { }
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]