Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*- Helpers for calling unextected and terminate
  2. // Copyright (C) 2001-2015 Free Software Foundation, Inc.
  3. //
  4. // This file is part of GCC.
  5. //
  6. // GCC is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10. //
  11. // GCC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. #include <bits/c++config.h>
  26. #include <cstdlib>
  27. #include <bits/exception_defines.h>
  28. #include "unwind-cxx.h"
  29.  
  30. using namespace __cxxabiv1;
  31.  
  32. #include "unwind-pe.h"
  33.  
  34.  
  35. // Helper routine for when the exception handling code needs to call
  36. // terminate.
  37.  
  38. extern "C" void
  39. __cxa_call_terminate(_Unwind_Exception* ue_header) throw ()
  40. {
  41.  
  42.   if (ue_header)
  43.     {
  44.       // terminate is classed as a catch handler.
  45.       __cxa_begin_catch(ue_header);
  46.  
  47.       // Call the terminate handler that was in effect when we threw this
  48.       // exception.  */
  49.       if (__is_gxx_exception_class(ue_header->exception_class))
  50.         {
  51.           __cxa_exception* xh;
  52.  
  53.           xh = __get_exception_header_from_ue(ue_header);
  54.           __terminate(xh->terminateHandler);
  55.         }
  56.     }
  57.   /* Call the global routine if we don't have anything better.  */
  58.   std::terminate();
  59. }
  60.  
  61.  
  62. #ifdef __ARM_EABI_UNWINDER__
  63. // The ARM EABI __cxa_call_unexpected has the same semantics as the generic
  64. // routine, but the exception specification has a different format.
  65. extern "C" void
  66. __cxa_call_unexpected(void* exc_obj_in)
  67. {
  68.   _Unwind_Exception* exc_obj
  69.     = reinterpret_cast<_Unwind_Exception*>(exc_obj_in);
  70.  
  71.   int rtti_count = 0;
  72.   _Unwind_Word rtti_stride = 0;
  73.   _Unwind_Word* rtti_list = NULL;
  74.   _Unwind_Ptr rtti_base = 0;
  75.   bool foreign_exception;
  76.   std::unexpected_handler unexpectedHandler = NULL;
  77.   std::terminate_handler terminateHandler = NULL;
  78.   __cxa_exception* xh;
  79.   if (__is_gxx_exception_class(exc_obj->exception_class))
  80.     {
  81.       // Save data from the EO, which may be clobbered by _cxa_begin_catch.
  82.       xh = __get_exception_header_from_ue(exc_obj);
  83.       unexpectedHandler = xh->unexpectedHandler;
  84.       terminateHandler = xh->terminateHandler;
  85.       rtti_count = exc_obj->barrier_cache.bitpattern[1];
  86.       rtti_base = (_Unwind_Ptr) exc_obj->barrier_cache.bitpattern[2];
  87.       rtti_stride = exc_obj->barrier_cache.bitpattern[3];
  88.       rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4];
  89.       foreign_exception = false;
  90.     }
  91.   else
  92.     foreign_exception = true;
  93.  
  94.   /* This must be called after extracting data from the EO, but before
  95.      calling unexpected().   */
  96.   __cxa_begin_catch(exc_obj);
  97.  
  98.   // This function is a handler for our exception argument.  If we exit
  99.   // by throwing a different exception, we'll need the original cleaned up.
  100.   struct end_catch_protect
  101.   {
  102.     end_catch_protect() { }
  103.     ~end_catch_protect() { __cxa_end_catch(); }
  104.   } end_catch_protect_obj;
  105.  
  106.  
  107.   __try
  108.     {
  109.       if (foreign_exception)
  110.         std::unexpected();
  111.       else
  112.         __unexpected(unexpectedHandler);
  113.     }
  114.   __catch(...)
  115.     {
  116.       /* See if the new exception matches the rtti list.  */
  117.       if (foreign_exception)
  118.         std::terminate();
  119.  
  120.       // Get the exception thrown from unexpected.
  121.  
  122.       __cxa_eh_globals* globals = __cxa_get_globals_fast();
  123.       __cxa_exception* new_xh = globals->caughtExceptions;
  124.       void* new_ptr = __get_object_from_ambiguous_exception (new_xh);
  125.       const std::type_info* catch_type;
  126.       int n;
  127.       bool bad_exception_allowed = false;
  128.       const std::type_info& bad_exc = typeid(std::bad_exception);
  129.  
  130.       // Check the new exception against the rtti list
  131.       for (n = 0; n < rtti_count; n++)
  132.         {
  133.           _Unwind_Word offset;
  134.  
  135.           offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)];
  136.           offset = _Unwind_decode_typeinfo_ptr(rtti_base, offset);
  137.           catch_type = (const std::type_info*) (offset);
  138.  
  139.           if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false,
  140.                                &new_ptr) != ctm_failed)
  141.             __throw_exception_again;
  142.  
  143.           // If the exception spec allows std::bad_exception, throw that.
  144.           // We don't have a thrown object to compare against, but since
  145.           // bad_exception doesn't have virtual bases, that's OK; just pass NULL.
  146.           void* obj = NULL;
  147.           if (catch_type->__do_catch(&bad_exc, &obj, 1))
  148.             bad_exception_allowed = true;
  149.         }
  150.  
  151.       // If the exception spec allows std::bad_exception, throw that.
  152. #if __cpp_exceptions
  153.       if (bad_exception_allowed)
  154.         throw std::bad_exception();
  155. #endif  
  156.  
  157.       // Otherwise, die.
  158.       __terminate(terminateHandler);
  159.     }
  160. }
  161. #endif // __ARM_EABI_UNWINDER__
  162.