ctor_bare

Crates.ioctor_bare
lib.rsctor_bare
version
sourcesrc
created_at2024-11-20 15:13:10.150125
updated_at2024-11-20 16:11:32.498943
descriptionRegister constructor functions for Rust at complie time under no_std.
homepagehttps://github.com/arceos-org/arceos
repositoryhttps://github.com/arceos-org/ctor_bare
max_upload_size
id1454871
Cargo.toml error:TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
Firefly (Azure-stars)

documentation

https://docs.rs/ctor_bare

README

ctor_bare

Crates.io Docs.rs CI

Module initialization functions for Rust (like attribute((constructor)) in C/C++) under no_std.

After registering a constructor function, a function pointer pointing to it will be stored in the .init_array section.

It can support Linux, MacOS and other systems, and can be also used in no_std environments when developing your own kernel.

In Linux, Windows, MacOS and other systems, the .init_array section is a default section to store initialization functions. When the program starts, the system will call all functions in the .init_array section in order.

When you are running your own operating system, you can call ctor_bare::call_ctors to invoke all registered constructor functions.

Usage

use ctor_bare::register_ctor;
#[register_ctor]
fn hello_world() {
    println!("Hello, world!");
}

static MAX_NUM: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);

#[register_ctor]
fn set_max_num() {
    MAX_NUM.store(20, std::sync::atomic::Ordering::Relaxed);
}

fn main() {
    assert_eq!(MAX_NUM.load(std::sync::atomic::Ordering::Relaxed), 20);
}

Because the .init_array section is a default section to store initialization functions in Linux and some other systems, it will be included in the linker script of compilers like GCC and Clang.

However, if you are using a custom linker script, you need to add the .init_array section and map them in the page table manually, so that these functions can be executed correctly. You can add the following line to your linker script as a reference:

.init_array : ALIGN(4K) {
    PROVIDE_HIDDEN (__init_array_start = .);
    *(.init_array .init_array.*)
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4K);
}

Notes

To avoid section-related symbols being optimized by the compiler, you need to add "-z nostart-stop-gc" to the compile flags (see https://lld.llvm.org/ELF/start-stop-gc).

For example, in .cargo/config.toml:

[build]
rustflags = ["-C", "link-arg=-z", "link-arg=nostart-stop-gc"]
rustdocflags = ["-C", "link-arg=-z", "-C", "link-arg=nostart-stop-gc"]
Commit count: 8

cargo fmt