Xyris  0.5
gcc.cpp
Go to the documentation of this file.
1 /**
2  * @file cxx.cpp
3  * @author Keeton Feavel ([email protected])
4  * @brief local static variable guards
5  * @version 0.1
6  * @date 2021-07-24
7  *
8  * @copyright Copyright the Xyris Contributors (c) 2021
9  *
10  * References:
11  * https://wiki.osdev.org/C++#Local_Static_Variables_.28GCC_Only.29
12  * https://opensource.apple.com/source/libcppabi/libcppabi-14/src/cxa_guard.cxx
13  *
14  */
15 #include <Locking/Mutex.hpp>
16 #include <Arch/Arch.hpp>
17 #include <Panic.hpp>
18 #include <stddef.h>
19 #include <stdint.h>
20 
21 /**
22  * @brief This function is the global handler for all stack protection. GCC will automatically
23  * write the canary code and use this function as the handler for when a smashed stack is detected.
24  *
25  */
26 #if UINTPTR_MAX == UINT32_MAX
27 uintptr_t __stack_chk_guard = 0xDEADC0DE;
28 #elif UINTPTR_MAX == UINT64_MAX
29 uintptr_t __stack_chk_guard = 0xBADBADBADBADBAD1;
30 #endif
31 
32 extern "C"
33 {
34 
35 // Function prototypes (to make compiler happy)
36 void __stack_chk_fail(void);
37 void __cxa_pure_virtual();
38 
39 void __stack_chk_fail(void)
40 {
41  panic("Smashed stack detected.");
42 }
43 
45 {
46  panic("Pure virtual called!");
47 }
48 
49 }
50 
51 /**
52  * Special thanks to the LLVM maintainers and Apple for their fantastic comments explaining what these
53  * functions are supposed to do, as well as providing implementation inspiration. See the link at the
54  * top of this source file for details.
55  */
56 namespace __cxxabiv1 {
57 
58 /**
59  * All static object initializations are protected by the single, global, recursive mutex.
60  * The recursive mutex is apparently required to enable nested objects initialization
61  *
62  * FIXME: This needs to be a recursive lock when those are added
63  */
64 Mutex cxaGuard("cxaguard");
65 
66 struct cxaguard {
67  uint64_t initialized : 8;
68  uint64_t inuse : 8;
69  uint64_t guard : 48;
70 };
71 
72 // The ABI requires a 64-bit type.
73 __extension__ typedef struct cxaguard __guard;
74 
75 static void cxaGuardSetInitializeHasRun(__guard* g)
76 {
77  g->initialized = 1;
78 }
79 
80 static bool cxaGuardHasInitializerRun(__guard* g)
81 {
82  return g->initialized;
83 }
84 
85 static void cxaGuardSetInUse(__guard* g)
86 {
87  g->inuse = 1;
88 }
89 
90 static void cxaGuardSetNotInUse(__guard* g)
91 {
92  g->inuse = 0;
93 }
94 
95 static bool cxaGuardIsInUse(__guard* g)
96 {
97  return g->inuse;
98 }
99 
100 extern "C"
101 {
102 
103 // Function prototypes
106 void __cxa_guard_abort(__guard* g);
107 
109 {
110  if (cxaGuardHasInitializerRun(g)) {
111  return 0;
112  }
113 
114  cxaGuard.lock();
115  // Ensure another thread didn't beat us to the chase
116  if (cxaGuardHasInitializerRun(g)) {
117  cxaGuard.unlock();
118  return 0;
119  }
120 
121  if (cxaGuardIsInUse(g)) {
122  panicf("[%s] __guard in bad state", __func__);
123  }
124 
125  cxaGuardSetInUse(g);
126  return 1;
127 }
128 
130 {
131  cxaGuardSetInitializeHasRun(g);
132  cxaGuard.unlock();
133 }
134 
136 {
137  cxaGuard.unlock();
138  cxaGuardSetNotInUse(g);
139 }
140 
141 }
142 
143 } // !namespace __cxxabiv1
Mutex::unlock
bool unlock()
Release the mutex.
Definition: Mutex.cpp:38
__cxxabiv1::cxaguard::inuse
uint64_t inuse
Definition: gcc.cpp:68
__cxxabiv1
Definition: gcc.cpp:56
__cxxabiv1::cxaguard::initialized
uint64_t initialized
Definition: gcc.cpp:67
__cxxabiv1::__cxa_guard_release
void __cxa_guard_release(__guard *g)
Definition: gcc.cpp:129
__cxxabiv1::cxaguard
Definition: gcc.cpp:66
__cxxabiv1::__cxa_guard_abort
void __cxa_guard_abort(__guard *g)
Definition: gcc.cpp:135
__stack_chk_fail
void __stack_chk_fail(void)
Definition: gcc.cpp:39
Mutex
Definition: Mutex.hpp:16
Mutex::lock
bool lock()
Aquire the mutex.
Definition: Mutex.cpp:20
Arch.hpp
Architecture control and initialization.
Panic.hpp
Kernel panic management.
__cxxabiv1::cxaguard::guard
uint64_t guard
Definition: gcc.cpp:69
panicf
void panicf(const char *fmt,...)
Halt the system and print the provided message and arguments on the panic screen.
Definition: Panic.cpp:87
__stack_chk_guard
uintptr_t __stack_chk_guard
This function is the global handler for all stack protection. GCC will automatically write the canary...
Definition: gcc.cpp:27
__cxxabiv1::__cxa_guard_acquire
int __cxa_guard_acquire(__guard *g)
Definition: gcc.cpp:108
__cxxabiv1::cxaGuard
Mutex cxaGuard("cxaguard")
panic
void panic(const char *msg)
Halt the system and print the provided message on the panic screen.
Definition: Panic.cpp:82
__cxxabiv1::__guard
typedef__extension__ struct cxaguard __guard
Definition: gcc.cpp:73
Mutex.hpp
__cxa_pure_virtual
void __cxa_pure_virtual()
Definition: gcc.cpp:44