#section #no-alloc #link-time

no-std build link-section

Link-time initialized slices for Rust, with full support for Linux, macOS, Windows, WASM and many more platforms

20 releases (7 breaking)

new 0.16.1 May 11, 2026
0.15.0 May 6, 2026
0.0.1 Mar 27, 2026

#242 in Procedural macros

Download history 28267/week @ 2026-04-06 79186/week @ 2026-04-13 78219/week @ 2026-04-20 83311/week @ 2026-04-27 103353/week @ 2026-05-04

353,456 downloads per month
Used in 2 crates

Apache-2.0 OR MIT

59KB
1K SLoC

Build Status

The crate is part of the linktime project.

crate docs version
linktime docs.rs crates.io
ctor docs.rs crates.io
dtor docs.rs crates.io
link-section docs.rs crates.io

link-section

A crate for defining link sections in Rust.

Sections are defined using the #[section] macro. This creates an associated data and text section, and items decorated with the #[in_section] macro are placed into the associated section.

Platform Support

Platform Support
Linux ✅ Supported, uses orphan section handling (§1)
*BSD ✅ Supported, uses orphan section handling (§1)
macOS ✅ Fully supported
Windows ✅ Fully supported
WASM ✅ Fully supported (§2) (§3)
AIX ✅ Supported (§4)
Other LLVM/GCC platforms ✅ Supported, uses orphan section handling (§1)

(§1) Orphan section handling is a feature of the linker that allows sections to be defined without a pre-defined name.

(§2) WASM requires const items, and uses ctor-like initialization to copy data to a contiguous section. To access link-section slices in WASM in #[ctor] functions, make sure to use at least #[ctor(priority = 1)].

(§3) Host environment support (by calling the exported register_link_section function) is required to register each section with the runtime.

(§4) AIX requires -C link-arg=-bdbg:namedsects:ss which enables functionality similar to LLVM/GCC's orphan section handling.

Platform Details

Each platform has a slightly different implementation of section control.

Linux and other LLVM/GCC platforms

  • Has start/end symbols: ✅ (C-compatible names only)
  • Supports linker sorting: ❌

On Linux and other LLVM/GCC platforms, the linker supports orphan sections, which allow sections to be defined without a pre-defined name. These sections are emitted as if they were r/w .data. For sections with C-compatible names, the linker will emit start/end symbols for the section.

Orphan sections are not sorted via numeric suffix (e.g.: SECTION.1, SECTION.2, etc.) with the default linker script.

macOS

  • Has start/end symbols: ✅
  • Supports linker sorting: ❌

On macOS, sections are configured via __DATA or __TEXT prefix and option suffixes (regular, no_dead_strip, etc.). The linker emits start and stop symbols, but Rust requires a (somewhat-stable) \x01 prefix to avoid mangling the section name. macOS does not support ordering in the linker.

Windows

  • Has start/end symbols: ❌
  • Supports linker sorting: ✅

On Windows, the linker does not emit start/end symbols, but all sections with a common prefix are automatically sorted by suffix, allowing us to use suffixes to control placement of start/stop symbols that we emit.

See this blog post and this blog post for more details about the alphabetical sorting rule.

WASM

  • Has start/end symbols: ❌
  • Supports linker sorting: ❌

On WASM platforms, Rust emits data into custom sections which do not support ordering, and are stored out-of-band. The host environment is responsible for registering this out-of-band section with this library as this data is not accessible by the WASM runtime.

Normally, WASM does not support placing arbitrary data in link sections - only non-pointer data is supported. However, the WASM support uses const items and pre-main construction functions to copy each entry into a contiguous section allocated at startup. The number of items in a link-section is computed by generating a custom data section containing one byte per item.

The WASM support expects a function in the module's environment with the following signature and functionality. The wasm import only passes the four usize / pointer parameters; the embedder should close over WebAssembly.Module and WebAssembly.Memory from compile/instantiate when installing the import.

/**
 * Support function for `link-section` crate.
 */
export function readCustomSection(
  wasmModule: WebAssembly.Module,
  wasmInstance: WebAssembly.Instance,
  namePtr: number,
  nameLength: number,
  targetPtr: number,
  targetLength: number,
): number {
    const memory = wasmInstance.exports.memory as WebAssembly.Memory;
    const nameBytes = new Uint8Array(memory.buffer, namePtr, nameLength);
    const sectionName = new TextDecoder().decode(nameBytes);

    const sections = WebAssembly.Module.customSections(wasmModule, sectionName);
    if (sections.length === 0) {
        return 0;
    }

    const section = sections[0];
    const need = section.byteLength;
    if (targetLength < need) {
        return need;
    }

    new Uint8Array(memory.buffer, targetPtr, need).set(new Uint8Array(section));
    return need;
}

AIX

  • Has start/end symbols: ✅
  • Supports linker sorting: ❌

AIX maps Rust's #[link_section] to csects (Control Sections), which act like subsections of the larger .text and .data sections . A csect is the smallest, indivisible unit of code or data.

By default, AIX does not have section start/stop symbols, but the most recent versions of the linker added a new -bdbg:namedsects:ss flag which enables section start/stop symbols .

This flag can be set with -C link-arg=-bdbg:namedsects:ss (or by upgrading to a recent Rust version that sets this automatically to support link sections.

The linker will report an error like this if the start/stop symbols are not found:

  = note: ld: 0711-317 ERROR: Undefined symbol: __start__data_link_section_DATABASES
          ld: 0711-317 ERROR: Undefined symbol: __stop__data_link_section_DATABASES
          ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.

For debugging AIX link-section issues, -C link-arg=-bmap:[path]/linker.out and -C link-arg=-bnoquiet may also be useful.

AIX supports a special mode to strip (strip -r) that preserves structural symbols like csects and exports. A future version of link-section may add support for loading csect bounds from the binary's symbol table.

[target.powerpc64-ibm-aix]
rustflags = [
    "-C", "link-arg=-bdbg:namedsects:ss",   # required
    "-C", "link-arg=-bmap:linker.out",      # for debugging
    "-C", "link-arg=-bnoquiet",             # for debugging
]

Typed Sections

Typed sections provide a section where all items are of a specific, sized type. The typed section may be accessed as a slice of the type at zero cost if desired.

A typed section can be created from either static or const items.

For const items: a copy of the const is materialized at link time, while the constant itself remains available for use as a constant in const contexts.

For static items: the static is stored directly in the link section.

fn items are special-cased and stored as function pointers in the typed section.

Usage

Create an untyped section using the #[section] macro that keeps related items in close proximity:

use link_section::{in_section, section};

#[section]
pub static CODE_SECTION: link_section::Section;

#[in_section(CODE_SECTION)]
pub fn link_section_function() {
    println!("link_section_function");
}

Create a typed section using the #[section] macro that stores items of a specific, sized type from static or const items:

mod my_registry {
    use link_section::{in_section, section};

    pub struct MyStruct {
        name: &'static str,
    }

    #[section]
    pub static MY_REGISTRY: link_section::TypedSection<MyStruct>;

    // Registers a `const` item.
    mod register_a_constant {
        use super::*;

        // A copy of this constant is registered in the link section.
        #[in_section(MY_REGISTRY)]
        pub const LINKED_MY_STRUCT: MyStruct = MyStruct { name: "my_struct" };
    }

    // Registers a `static` item.
    mod register_a_static {
        use super::*;

        // This static lives directly in the link section.
        #[in_section(MY_REGISTRY)]
        pub static LINKED_MY_STRUCT: MyStruct = MyStruct { name: "my_struct_2" };
    }
}

Inspiration

link-section was originally inspired by the linkme project.

Dependencies