| // Copyright (C) 2012 The Android Open Source Project |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // 1. Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // 2. Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution. |
| // 3. Neither the name of the project nor the names of its contributors |
| // may be used to endorse or promote products derived from this software |
| // without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
| // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| // ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| // SUCH DAMAGE. |
| |
| #include <cstdlib> |
| #include <cxxabi.h> |
| #include <exception> |
| |
| namespace std { |
| |
| // The default std::terminate() implementation will crash the process. |
| // This is done to help debugging, i.e.: |
| // - When running the program in a debugger, it's trivial to get |
| // a complete stack trace explaining the failure. |
| // |
| // - Otherwise, the default SIGSEGV handler will generate a stack |
| // trace in the log, that can later be processed with ndk-stack |
| // and other tools. |
| // |
| // - Finally, this also works when a custom SIGSEGV handler has been |
| // installed. E.g. when using Google Breakpad, the termination will |
| // be recorded in a Minidump, which contains a stack trace to be |
| // later analyzed. |
| // |
| // The C++ specification states that the default std::terminate() |
| // handler is library-specific, even though most implementation simply |
| // choose to call abort() in this case. |
| // |
| static void default_terminate(void) { |
| // The crash address is just a "magic" constant that can be used to |
| // identify stack traces (like 0xdeadbaad is used when heap corruption |
| // is detected in the C library). 'cab1' stands for "C++ ABI" :-) |
| *(reinterpret_cast<char*>(0xdeadcab1)) = 0; |
| |
| // should not be here, but just in case. |
| abort(); |
| } |
| |
| terminate_handler default_terminate_fn = default_terminate; |
| terminate_handler current_terminate_fn = default_terminate_fn; |
| |
| unexpected_handler default_unexpected_fn = terminate; |
| unexpected_handler current_unexpected_fn = default_unexpected_fn; |
| |
| |
| exception::exception() throw() { |
| } |
| |
| exception::~exception() throw() { |
| } |
| |
| const char* exception::what() const throw() { |
| return "std::exception"; |
| } |
| |
| bad_exception::bad_exception() throw() { |
| } |
| |
| bad_exception::~bad_exception() throw() { |
| } |
| |
| const char* bad_exception::what() const throw() { |
| return "std::bad_exception"; |
| } |
| |
| bad_cast::bad_cast() throw() { |
| } |
| |
| bad_cast::~bad_cast() throw() { |
| } |
| |
| const char* bad_cast::what() const throw() { |
| return "std::bad_cast"; |
| } |
| |
| bad_typeid::bad_typeid() throw() { |
| } |
| |
| bad_typeid::~bad_typeid() throw() { |
| } |
| |
| const char* bad_typeid::what() const throw() { |
| return "std::bad_typeid"; |
| } |
| |
| terminate_handler get_terminate() { |
| return current_terminate_fn; |
| } |
| |
| terminate_handler set_terminate(terminate_handler f) { |
| terminate_handler tmp = current_terminate_fn; |
| current_terminate_fn = f; |
| return tmp; |
| } |
| |
| void terminate() { |
| try { |
| current_terminate_fn(); |
| abort(); |
| } catch (...) { |
| abort(); |
| } |
| } |
| |
| unexpected_handler get_unexpected() { |
| return current_unexpected_fn; |
| } |
| |
| unexpected_handler set_unexpected(unexpected_handler f) { |
| unexpected_handler tmp = current_unexpected_fn; |
| current_unexpected_fn = f; |
| return tmp; |
| } |
| |
| void unexpected() { |
| current_unexpected_fn(); |
| terminate(); |
| } |
| |
| void __terminate(terminate_handler t_handler) { |
| try { |
| t_handler(); |
| abort(); |
| } catch (...) { |
| abort(); |
| } |
| } |
| |
| void __unexpected(unexpected_handler u_handler) { |
| u_handler(); |
| terminate(); |
| } |
| |
| bool uncaught_exception() throw() { |
| using namespace __cxxabiv1; |
| |
| __cxa_eh_globals* globals = __cxa_get_globals(); |
| return globals->uncaughtExceptions != 0; |
| } |
| |
| } // namespace std |