link-section 0.19.3

Link-time initialized slices for Rust, with full support for Linux, macOS, Windows, WASM and many more platforms.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
The crate is part of the [`linktime`](https://crates.io/crates/linktime) project.

[![GitHub](https://img.shields.io/badge/repo-github-blue)](https://github.com/mmastrac/linktime) [![Crates.io License](https://img.shields.io/crates/l/link-section)](https://crates.io/crates/link-section) [![Build Status](https://github.com/mmastrac/linktime/actions/workflows/rust.yml/badge.svg)](https://github.com/mmastrac/linktime/actions/workflows/rust.yml) 


| crate | |
| --- | --- |
| `linktime`<br>[![docs.rs]https://docs.rs/linktime/badge.svg]https://docs.rs/linktime [![crates.io]https://img.shields.io/crates/v/linktime.svg]https://crates.io/crates/linktime | Convenience crate for `ctor`, `dtor` and `link-section` |
| `ctor`<br>[![docs.rs]https://docs.rs/ctor/badge.svg]https://docs.rs/ctor [![crates.io]https://img.shields.io/crates/v/ctor.svg]https://crates.io/crates/ctor | Module initialization functions before main |
| `dtor`<br>[![docs.rs]https://docs.rs/dtor/badge.svg]https://docs.rs/dtor [![crates.io]https://img.shields.io/crates/v/dtor.svg]https://crates.io/crates/dtor | Module shutdown functions before main |
| `link-section`<br>[![docs.rs]https://docs.rs/link-section/badge.svg]https://docs.rs/link-section [![crates.io]https://img.shields.io/crates/v/link-section.svg]https://crates.io/crates/link-section | Linker-managed typed (slices) and untyped sections |
| `scattered-collect`<br>[![docs.rs]https://docs.rs/scattered-collect/badge.svg]https://docs.rs/scattered-collect [![crates.io]https://img.shields.io/crates/v/scattered-collect.svg]https://crates.io/crates/scattered-collect | Linker-managed collections: slices, sorted slices, maps |
# link-section
A crate for defining linker-backed sections in Rust.

`link-section` provides two attributes:

- `#[section(...)]` defines a section handle. The handle is a `static` item used
  to inspect the section at runtime, usually as a slice. The handle's visibility
  determines where items may be submitted: public handles can be submitted from
  any module, while private handles can only be submitted from the module that
  defines them.
- `#[in_section(path::to::SECTION)]` submits an item to that section. A
  submitted item is an item annotated with `#[in_section(...)]`; depending on
  the section kind, it may also remain usable directly at the submission site.
  The `path::to::SECTION` must be visible to the submission site.

Together, these attributes let separately-declared items be collected into one
linker section and accessed through a single section handle.

## Visibility

Importantly, even though the linker is used to collect items, the visibility of
the section handle determines where items may be submitted: public handles can
be submitted from any crate (assuming the submitting crate references the one
with the collection handle), while private handles can only be submitted from
the crate that defines them.

The section name is generated from the name of the item and a location of the
item within the source tree. This means that you may have more than one
independent section with the item name in a project, and they will not conflict.

Note that if you are generating sections from a macro, you _must_ include at
least one token from the top-level macro call in the section definition to avoid
conflicts with tokens that are provided purely from the macro itself.

To allow for submission of items without visibility constraints, the crate
provides an `unsafe` option for the submission macro where the section's
name and attributes may be specified manually:

```rust
pub struct MyType(u8);

mod my_private_section {
    // Specify a section name so it can be used without a direct reference.
    #[section(typed, unsafe, name = my_crate::SECTION_NAME)]
    static MY_SECTION: link_section::TypedSection<MyType>;
}

mod elsewhere {
    // This must match the definition site!
    #[in_section(unsafe, name = my_crate::SECTION_NAME, type = typed)] // optionally: aux(main = MAIN_SECTION)
    static ITEM: MyType = MyType(42);
}
```

### Syntax

Section definition:

 - `#[section(<kind>)]`
 - `#[section(<kind>, aux(main = <path::to::MAIN_SECTION>))]`
 - `#[section(unsafe, type = <kind>)]`
 - `#[section(unsafe, type = <kind>, name = <name>)]`

Section submission:

 - `#[in_section(path::to::SECTION)]`
 - `#[in_section(unsafe, type = <kind>, name = <name>)]`

## Section Kinds

There are five section kinds:

- `untyped`: Collects related code or data in one linker section without
  exposing a typed slice. This is useful for co-location, phase-specific code,
  or platform-specific section placement.
- `typed`: Stores values of one type and exposes them as an immutable slice.
- `mutable`: Stores values of one type and exposes them as a mutable slice.
- `reference`: Stores values of one type, exposes them as an immutable slice,
  and also lets each submitted item be used as a reference at its submission
  site.
- `movable`: Stores values of one type and exposes them as a mutable slice, and
  also lets each submitted item be used as a reference at its submission site.
  The entire section is available as a mutable slice, and items may be reordered
  during startup initialization (see [`TypedMovableSection`] for more details).

| Section Kind | Immutable Slice | Mutable Slice | `const` Items | `static` / Reference Items |
| ------------ | --------------- | ------------- | ------------- | -------------------------- |
| `untyped`    |||||
| `typed`      |||| ⚠️                         |
| `mutable`    |||||
| `reference`  |||||
| `movable`    |||||

⚠️ Native targets support `static` submissions for `typed` sections; WASM uses
`const` submissions only.

## Submitting Items

Items are submitted with `#[in_section(SECTION)]`.

A `const` submission copies the value into the section. The original constant
remains usable as a normal Rust constant, and the section receives its own
stored copy.

```rust
#[in_section(MY_SECTION)]
pub const ITEM: MyType = MyType::new();
```

A `static` submission stores the `static` directly in the section. References to
the `static` and references obtained from the section slice point at the same
underlying object. `static` submissions are supported for typed sections on
native targets and for reference sections.

```rust
#[in_section(MY_SECTION)]
pub static ITEM: MyType = MyType::new();
```

A `fn` submitted to a typed section is stored as a function pointer. The
function body itself is not placed into the typed data section.

```rust
#[section(typed)]
pub static FUNCTIONS: link_section::TypedSection<fn()>;

#[in_section(FUNCTIONS)]
pub fn callback() {
    // ...
}
```

## 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, via emulation (§2)          |
| AIX                      | ✅ Supported (§3) (§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) AIX requires `-C link-arg=-bdbg:namedsects:ss` which enables functionality
similar to LLVM/GCC's orphan section handling.

(§4) Empty sections are not currently supported: ensure every section has at least
one item, or pass the `-C link-arg=-berok` linker flag to ignore errors.

## 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](https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155)
and
[this blog post](https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165)
for more details about the alphabetical sorting rule.

### WASM

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

On WASM platforms there are no linker-provided start/end symbols and no linker
ordering. Normally, WASM does not support placing arbitrary data in link
sections - only non-pointer data is supported. To work around this, the WASM
support uses `const` items and pre-`main` construction functions to gather each
entry into a contiguous section allocated at startup.

Each submitted item emits a plain (linear-memory) static "list node" plus an
`.init_array.0` constructor that threads the node onto an intrusive linked list
rooted in the section. Because these nodes are interior-mutable and have their
address taken, LLVM cannot merge them even under fat LTO, so the item
count is always exact.

The list is materialised into one contiguous allocation by an eager,
ordered constructor. Item submissions run at `.init_array.0` (priority 0), and
each section emits a finalization constructor at `.init_array.1` (priority 1).
Because wasm-ld orders `.init_array.*` by the integer value of the suffix, the
finalizer is guaranteed to run after every submission and before any
`#[ctor(priority >= 2)]` and before `main` — a well-defined pre-`main` time
rather than "whenever the section is first read".

[`Ref`] / [`MovableRef`] handles carry a pointer to their owning section and also
flatten it on first dereference. That lazy path is an idempotent backstop for the
one remaining tie: an explicit `#[ctor(priority = 1)]` that runs before the
finalizer. As a result the `#[ctor]` priority requirement is the same as
elsewhere: to read a link section or dereference a [`Ref`] / [`MovableRef`]
handle from a `#[ctor]`, use at least `#[ctor(priority = 1)]`. Reads from `main`
(or any later constructor) are always safe.

A `#[ctor(priority = 0)]` that reads section *bounds* (not a [`Ref`]) is the one
corner that breaks: it interleaves with `.init_array.0` submissions, triggers an
early lazy flatten, and then any later submission panics (the section is already
materialised). The contract — use at least priority 1 — is unchanged, but the
panic now names the section and the likely cause.

### AIX

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

AIX maps Rust's `#[link_section]` to `csect`s (Control Sections), which act like
subsections of the larger `.text` and `.data` sections
<sup>[↳](https://www.ibm.com/docs/kk/aix/7.2.0?topic=program-understanding-programming-toc)</sup>.
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
<sup>[↳](https://reviews.llvm.org/D124857?id=427067)</sup>.

This flag can be set with `-C link-arg=-bdbg:namedsects:ss` (or by upgrading to
a recent Rust version that sets this automatically
<sup>[↳](https://rust.googlesource.com/rust/+/ad582a586550bf2c72e963939f61a71df1af7c0c%5E%21/#F0)</sup>
to support link sections.

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

```text
= 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.
```

In addition, the linker may report the same errors if a section is empty. It is
recommended that you either (1) provide a sentinel item for AIX that can be skipped
in the slice, or (2) pass the `-C link-arg=-berok` linker flag to ignore the error.

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 `csect`s and exports. A future version of `link-section` may add
support for loading `csect` bounds from the binary's symbol table.

```toml
[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 materialised 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.

## Exclusive Access

Mutable sections (ie: [`TypedMutableSection`] and [`TypedMovableSection`])
require exclusive access to the section's memory while calling
[`TypedMutableSection::as_mut_slice`] or [`TypedMovableSection::as_mut_slice`].

This is normally satisfied only during pre-`main` initialization (for example
inside a `#[ctor]`). After `main`, the caller must guarantee no concurrent reads
or writes from other threads and no active Rust references into the section.

It is highly recommended not to access the mutable references after `main` has
started.

## Usage

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

```rust
use link_section::{in_section, section};

#[section(untyped)]
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:

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

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

    #[section(typed)]
    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` would have been far more challenging to implement without dtolnay's great `linkme` project paving the way.
# Re-exporting from another crate

The macros assume this crate is available as a direct dependency, resolving their
support paths through the crate's own name. If you re-export this crate's items as
part of your own crate (so that downstream users don't need to depend on it
directly), you have two options:

- (preferred) use the declarative macro form. It resolves its support paths
  relative to your re-export, so no extra configuration is required.
- Alternatively, pass the `crate_path` attribute to redirect the macro's
  generated output to the path where this crate has been re-exported.

See the `crate_path` entry in the *Macro Attributes* section below for the exact
syntax for this crate.
# Crate Features

| Cargo feature | Description |
| --- | --- |
| `proc_macro` |  Crate feature `proc_macro` (enables the `#[section]` attribute shim). |

# Macro Attributes

<table><tr><th>Attribute</th><th>Description</th></tr>
<tr><td><code>aux(main = path::to::MAIN_SECTION)</code></td><td>

 Auxiliary sections are stored in a section near the main section. The
 aux path must be a valid reference to the main section.


</td></tr>
<tr><td><code>crate_path = ::path::to::link_section</code></td><td>

 The path to the `link-section` crate containing the support macros. If
 you re-export `link-section` items as part of your crate, you can use
 this to redirect the macro's output to the correct crate.

 Using the declarative [`section!`][s] form is
 preferred over this parameter.

 [s]: crate::declarative::section!


</td></tr>
<tr><td><code>name = my_crate::SECTION_NAME</code></td><td>

 Specify a custom section name to allow the section to be used without a
 direct reference. If not specified, the section name will be generated
 using the item name and a path to the section.

 It is valid to specify multiple sections with the same name, and the linker
 will ensure that both sections contain the same items. The multiple sections
 must contain the same type, otherwise the section will `panic!` at runtime.

 While `name` accepts a path, this path does not refer to a specific Rust
 item path.


</td></tr>
<tr><td><code>untyped | typed | mutable | movable | reference</code></td><td>

 The type of the section.


</td></tr>
<tr><td><code>unsafe</code></td><td>

 Allow the section to be used without a direct reference.


</td></tr>
</table>

# Defaults