1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_CppException.cpp
4 
5   Copyright (C)2011 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 35648 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/os/CTR/os_CppException.h>
17 #include <nn/os/CTR/os_ThreadLocalRegion.h>
18 #include <exception>
19 #include <cstdlib>
20 
21 namespace nn { namespace os { namespace CTR {
22 
23     namespace
24     {
25         extern "C" NN_WEAK_SYMBOL void __ARM_exceptions_buffer_required(void);
26         extern "C" void* __ARM_exceptions_buffer_init(void);
27 
28         typedef void (*handler)(void);
29 
30 
31         struct __cxa_eh_globals
32         {
33             uint32_t                uncaughtExceptions;                     // counter
34             std::unexpected_handler unexpectedHandler;                      // per-thread handler
35             std::terminate_handler  terminateHandler;                       // per-thread handler
36             bool                    implementation_ever_called_terminate;   // true if it ever did
37             NN_PADDING3;
38             handler                 call_hook;                              // transient field to tell terminate/unexpected which hook to call
39             void*                   caughtExceptions;                       // chain of "caught" exceptions
40             void*                   propagatingExceptions;                  // chain of "propagating" (in cleanup) exceptions
41             void*                   emergency_buffer;                       // emergency buffer for when rest of heap full
42         };
43 
IsArmExceptionsBufferNotRequired()44         bool IsArmExceptionsBufferNotRequired()
45         {
46             return &__ARM_exceptions_buffer_required == NULL;
47         }
48 
DefaultTerminateHandler()49         void DefaultTerminateHandler()
50         {
51             std::abort();
52         }
DefaultUnexpectedHandler()53         void DefaultUnexpectedHandler()
54         {
55             std::terminate();
56         }
57     }
58 
59 
SetupThreadCppExceptionEnvironment()60     void SetupThreadCppExceptionEnvironment()
61     {
62         CTR::ThreadLocalRegion* pTlr = os::CTR::GetThreadLocalRegion();
63         NN_STATIC_ASSERT( sizeof(pTlr->ehGlobals) == sizeof(__cxa_eh_globals) );
64         pTlr->ehGlobalsAddr = pTlr->ehGlobals;
65 
66         __cxa_eh_globals& ceg = *reinterpret_cast<__cxa_eh_globals*>(pTlr->ehGlobals);
67         ceg.uncaughtExceptions      = 0;
68         ceg.unexpectedHandler       = DefaultUnexpectedHandler;
69         ceg.terminateHandler        = DefaultTerminateHandler;
70         ceg.implementation_ever_called_terminate = false;
71         ceg.call_hook               = NULL;
72         ceg.caughtExceptions        = NULL;
73         ceg.propagatingExceptions   = NULL;
74         ceg.emergency_buffer        =
75             IsArmExceptionsBufferNotRequired() ? NULL: __ARM_exceptions_buffer_init();
76     }
77 
78 }}}
79 
80