#linker #elf #configuration #programming #set #declarative #array

linker-set

Declarative programming via linker-constructed arrays

8 releases

0.3.5 Aug 3, 2024
0.3.4 Aug 2, 2024
0.3.3 Jul 14, 2024
0.2.0 Apr 18, 2024
0.1.0 Apr 17, 2024

#541 in Data structures

BSD-3-Clause

16KB
213 lines

INTRO

A linker set allows you to program declaratively rather than imperatively by embedding configuration or behavior into a program as data.

Using a linker set, you can scatter instances of a certain type all over your program, and, with the proper annotations, the linker will gather them up into a special section of the ELF binary, forming an array, which can be iterated at runtime.

See the tests in src/lib.rs for usage, but general idea is:

    use linker_set::*;

    set_declare!(name, type);

    #[set_entry(name)]
    static VAR: type = ...;

    for i in set!(name) ...

The set_declare!() macro outputs a module definition. The module must be imported into the scope of calls to the set_entry attribute and the set!() macro.

If you make a linker set of an integer type, you should use typed literals, not generic integer literals. I.e.

    static FOO: u64 = 1000u64; // not 1000

Generic integer literals will defeat a typechecking mechanism that is output by the set_entry macro.

All items in a set should be of the same size, the size of the declared type. Otherwise, stuff won't work. The macros make an attempt to typecheck set entries, but they aren't foolproof. Caveat scriptor.

The index operator is kind of just for fun. Obviously you shouldn't depend on the linker to provide any specific ordering.

HISTORY

This idea comes from Clustrix, the best distributed relational database in the world, which no one knew about. Clustrix was written in a very unusual but very interesting style of C. Much of it was written in continuation passing style, and continuations and lightweight threads (fibers) ran on top of a scheduler very similar to the asynchronous runtimes like Tokio which later became popular. (But Clustrix was started in 2006, before that popularity.)

Linker sets were used extensively in the Clustrix code to do things such as specify initialization or other system processes via graphs (initgraphs), automatically create heaps for memory allocation, automatically allocate integers or flags for what would otherwise have to be centrally controlled constants, and automatically register structures or handlers with a subsystem.

This concept was present in the oldest version of the Clustrix code in Git. A prior Subversion repository seemed to have been lost. The inspiration appears to have come from FreeBSD, which has several macros whose names match exactly macros used in the Clustrix source code.

https://en.wikipedia.org/wiki/Clustrix https://github.com/freebsd/freebsd-src/blob/main/sys/sys/linker_set.h

SEE ALSO

The crate "linkme" does a similar thing, calling the concept "distributed slices."

Sidney Cammeresi sac@cheesecake.org

Dependencies

~245–700KB
~17K SLoC