1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2014-12-03     Bernard      Add copyright header.
9  * 2014-12-29     Bernard      Add cplusplus initialization for ARMCC.
10  * 2016-06-28     Bernard      Add _init/_fini routines for GCC.
11  * 2016-10-02     Bernard      Add WEAK for cplusplus_system_init routine.
12  */
13 
14 #include <rtthread.h>
15 
16 #if defined(__ARMCC_VERSION)
17 extern void $Super$$__cpp_initialize__aeabi_(void);
18 /* we need to change the cpp_initialize order */
$Sub$$__cpp_initialize__aeabi_(void)19 rt_weak void $Sub$$__cpp_initialize__aeabi_(void)
20 {
21     /* empty */
22 }
23 #elif defined(__GNUC__) && !defined(__CS_SOURCERYGXX_MAJ__)
24 /* The _init()/_fini() routines has been defined in codesourcery g++ lite */
_init()25 rt_weak void _init()
26 {
27 }
28 
_fini()29 rt_weak void _fini()
30 {
31 }
32 
33 rt_weak void *__dso_handle = 0;
34 
35 #endif
36 
37 /**
38  * @brief   This function initializes the C++ runtime environment for ARM and GCC compilers.
39  *
40  * @note    If there is no SHT$$INIT_ARRAY section, calling $Super$$__cpp_initialize__aeabi_() will cause an error
41  *          in ARMCC compiler. Therefore, this function manually iterates through the base addresses of the
42  *          SHT$$INIT_ARRAY section to call the constructor functions of each object. In GCC compiler, this function
43  *          uses the __ctors_start__ and __ctors_end__ global variables to determine the range of constructor function
44  *          pointers and calls each constructor function of every object in that range.
45  *
46  * @return  Returns 0 if the initialization of the C++ runtime environment is successful. Otherwise, it returns
47  *          an error code indicating the failure of the operation.
48  */
cplusplus_system_init(void)49 rt_weak int cplusplus_system_init(void)
50 {
51 #if defined(__ARMCC_VERSION)
52     /* If there is no SHT$$INIT_ARRAY, calling
53      * $Super$$__cpp_initialize__aeabi_() will cause fault. At least until Keil5.12
54      * the problem still exists. So we have to initialize the C++ runtime by ourself.
55      */
56     typedef void PROC();
57     extern const unsigned long SHT$$INIT_ARRAY$$Base[];
58     extern const unsigned long SHT$$INIT_ARRAY$$Limit[];
59 
60     const unsigned long *base = SHT$$INIT_ARRAY$$Base;
61     const unsigned long *lim  = SHT$$INIT_ARRAY$$Limit;
62 
63     for (; base != lim; base++)
64     {
65         PROC *proc = (PROC *)((const char *)base + *base);
66         (*proc)();
67     }
68 #elif defined(__GNUC__)
69     typedef void(*pfunc)();
70     extern pfunc __ctors_start__[];
71     extern pfunc __ctors_end__[];
72     pfunc *p;
73 
74     for (p = __ctors_start__; p < __ctors_end__; p++)
75         (*p)();
76 #endif
77 
78     return 0;
79 }
80 INIT_COMPONENT_EXPORT(cplusplus_system_init);
81