sel4_ctors_dtors/
lib.rs

1//
2// Copyright 2024, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7// See:
8// - https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
9// - https://maskray.me/blog/2021-11-07-init-ctors-init-array
10
11#![no_std]
12#![feature(linkage)]
13
14use core::mem;
15use core::ptr;
16use core::slice;
17
18type ArrayEntry = unsafe extern "C" fn();
19
20extern "C" {
21    static __preinit_array_start: ArrayEntry;
22    static __preinit_array_end: ArrayEntry;
23    static __init_array_start: ArrayEntry;
24    static __init_array_end: ArrayEntry;
25    static __fini_array_start: ArrayEntry;
26    static __fini_array_end: ArrayEntry;
27
28    fn _init();
29    fn _fini();
30}
31
32mod _weak {
33    #[linkage = "weak"]
34    #[no_mangle]
35    extern "C" fn _init() {}
36
37    #[linkage = "weak"]
38    #[no_mangle]
39    extern "C" fn _fini() {}
40}
41
42#[derive(Debug, Copy, Clone, Eq, PartialEq)]
43pub enum Error {
44    Misaligned { section_name: &'static str },
45}
46
47unsafe fn run_array(
48    start_addr: usize,
49    end_addr: usize,
50    section_name: &'static str,
51) -> Result<(), Error> {
52    if start_addr != end_addr {
53        if start_addr % mem::size_of::<ArrayEntry>() != 0
54            || end_addr % mem::size_of::<ArrayEntry>() != 0
55        {
56            return Err(Error::Misaligned { section_name });
57        }
58
59        let len = (end_addr - start_addr) / mem::size_of::<ArrayEntry>();
60        let array = slice::from_raw_parts(start_addr as *const ArrayEntry, len);
61        for entry in array {
62            (entry)();
63        }
64    }
65    Ok(())
66}
67
68fn run_preinit_array() -> Result<(), Error> {
69    unsafe {
70        run_array(
71            ptr::addr_of!(__preinit_array_start) as usize,
72            ptr::addr_of!(__preinit_array_end) as usize,
73            ".preinit_array",
74        )
75    }
76}
77
78fn run_init_array() -> Result<(), Error> {
79    unsafe {
80        run_array(
81            ptr::addr_of!(__init_array_start) as usize,
82            ptr::addr_of!(__init_array_end) as usize,
83            ".init_array",
84        )
85    }
86}
87
88fn run_fini_array() -> Result<(), Error> {
89    unsafe {
90        run_array(
91            ptr::addr_of!(__fini_array_start) as usize,
92            ptr::addr_of!(__fini_array_end) as usize,
93            ".fini_array",
94        )
95    }
96}
97
98fn run_init() {
99    unsafe { _init() }
100}
101
102fn run_fini() {
103    unsafe { _fini() }
104}
105
106pub fn run_ctors() -> Result<(), Error> {
107    run_preinit_array()?;
108    run_init();
109    run_init_array()?;
110    Ok(())
111}
112
113pub fn run_dtors() -> Result<(), Error> {
114    run_fini_array()?;
115    run_fini();
116    Ok(())
117}