| Crates.io | portable_link_section |
| lib.rs | portable_link_section |
| version | 0.1.0 |
| created_at | 2025-10-10 19:05:53.883075+00 |
| updated_at | 2025-10-10 19:05:53.883075+00 |
| description | A portable version of the #[link_section] macro. |
| homepage | |
| repository | https://github.com/robbepop/portable_link_section |
| max_upload_size | |
| id | 1877406 |
| size | 59,339 |
#[link_section] for RustA macro to provide support for portable #[link_section] annotations in Rust.
This respects the following binary file formats:
In essence the #[portable_link_section] macro is a restricted version of #[link_section].
The #[portable_link_section] macro accepts one of the following segment identifiers:
text: codedata: writable datarodata: read-only databss: zero-initialized dataWhen given text or data the macro expects another group identifier that has to follow some strict rules to provide portability.
Interpreters might have a use for portable #[link_section] in order to have more control where certain operator handler functions are placed in memory in order to improve I-cache efficiency by grouping hot and cold code.
text on fn items.#[portable_link_section(text(hot))]
fn func_0() {}
#[portable_link_section(text(cold_i32))]
fn func_1(lhs: i32, rhs: i32) -> i32 {
lhs.wrapping_add(rhs)
}
data, rodata or bss on static items.#[portable_link_section(data(my_group))]
static DATA_0: i32 = 42;
#[portable_link_section(rodata)]
static DATA_1: i32 = 42;
#[portable_link_section(bss)]
static DATA_2: i32 = 0;
Certain group identifiers have special meaning on some platforms,
therefore their usage is forbidden as to not end up with non-conformant
semantics across platforms.
#[portable_link_section(text(const))] // ~ERROR: const is reserved for `text` in MACH-O and therefore forbidden
fn func_0() {}
#[portable_link_section(data(common))] // ~ERROR: common is reserved for `data` in MACH-O and therefore forbidden
static DATA_0: i32 = 42;
The MACH-O file format has a strict limit on the structure of link section identifiers
as their length is capped to 16 bytes. Since they are represented as zero-terminated strings
we allow a maximum of 15 bytes per group identifier.
#[portable_link_section(text(this_group_identifier_is_too_long))] // ~ERROR: MACH-O has a limit of 15 bytes per identifier
fn func_0() {}
The following Rust code that uses the #[portable_link_section]:
#[portable_link_section(text(hot))]
fn func_0() {}
Gets expanded into the following Rust code:
#[cfg_attr(
all(target_family = "unix", not(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))),
unsafe(link_section = ".text.hot"),
)]
#[cfg_attr(
any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"),
unsafe(link_section = "__TEXT,__hot"),
)]
#[cfg_attr(
target_os = "windows",
unsafe(link_section = ".text$hot"),
)]
fn func_0() {}
Licensed under either of
at your option.