blob: 031b64ce54c4af4057cd7ae78d72574e689383ad [file] [log] [blame]
// 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