| // Copyright Microsoft and CHERIoT Contributors. |
| // SPDX-License-Identifier: MIT |
| |
| #pragma once |
| #include <cheri.hh> |
| #include <riscvreg.h> |
| #include <stddef.h> |
| |
| /** |
| * Support for running global constructors. There is no global initialisation |
| * phase for all compartments, so this provides support for lazily running |
| * global constructors on demand. |
| */ |
| namespace GlobalConstructors |
| { |
| /** |
| * Helper that runs all global constructors in its constructor. |
| */ |
| struct ConstructHelper |
| { |
| /** |
| * Iterate over the global constructors array, calling each |
| * constructor. |
| */ |
| ConstructHelper() |
| { |
| using GlobalConstructor = void (*)(); |
| ptraddr_t initStart = LA_ABS(__init_array_start); |
| ptraddr_t initEnd = LA_ABS(__init_array_end); |
| CHERI::Capability<void (*)()> pcc{ |
| static_cast<void (**)()>(__builtin_cheri_program_counter_get())}; |
| for (ptraddr_t i = initStart; i < initEnd; |
| i += sizeof(GlobalConstructor)) |
| { |
| pcc.address() = i; |
| (*pcc)(); |
| } |
| } |
| }; |
| |
| /** |
| * Call all global constructors in this compartment, precisely once. |
| */ |
| void run() |
| { |
| // This will emit a guard variable and code that checks the guard |
| // variable and calls the constructor if it has not been called. |
| static ConstructHelper helper; |
| } |
| }; // namespace GlobalConstructors |