Expand description
Embed metadata into ELF binaries as .note.package sections so it
survives crashes, visible to coredumpctl, readelf -n, and any
other consumer of the systemd package-metadata
format.
The crate’s main feature is crash-dump preservation: when your process dies,
the version of code that crashed is recoverable from the core dump without external
symbol files or build-system context.
Runtime read-back via the get_module_info! macro is a convenience
accessor, useful while the process is still alive but not the reason
the crate exists.
Consumers call generate_project_metadata_and_linker_script from
build.rs to generate the linker script and Cargo directives. At
runtime, metadata fields can be read via get_module_info! (returns
ModuleInfoResult<String> for a single field, or a HashMap of all
readable fields when called with no arguments). On non-Linux platforms
the crate exposes no-op stubs so cross-platform builds still compile;
runtime accessors return ModuleInfoError::NotAvailable.
See the README and the examples/ directory for an end-to-end integration.
§Limitations
rlib consumers read the host binary’s metadata, not their own.
When a downstream library’s build.rs calls
generate_project_metadata_and_linker_script, the resulting
cargo:rustc-link-arg=-T<linker_script>.ld directive is attached to that
library’s own build and does not propagate to the final executable’s link
command, so the library’s linker script never runs at the link step that
produces the binary. Meanwhile, every get_module_info! call inside
the library expands to an extern "C" { static module_info_*: u8; }
declaration. At the final link those undefined references resolve
against the executable’s linker script, which defines a single set of
module_info_* symbols pointing at the executable’s .note.package
payload, so library code reading them gets the executable’s values. The
same applies to anything statically linked into a Rust executable:
rlib, staticlib linked via #[link(kind = "static")], or in-tree
workspace libraries.
staticlib consumed by an outer (non-cargo) build can embed its own
metadata. Set EmbedOptions::emit_cargo_link_arg to false; the
crate then writes linker_script.ld to out_dir without emitting the
cargo:rustc-link-arg directive. The outer build (Make, CMake, MSBuild,
…) passes that script to its own linker, at which point the
module_info_* symbols are defined by the staticlib’s linker script and
the staticlib reads its own metadata. See “Option B” in the README for
the full flow.
cdylib shared libraries loaded via dlopen are not affected. A
cdylib runs its own link step and applies its own linker script, so
the module_info_* symbols inside the resulting .so are local to it
(not exported in the dynamic symbol table). Code inside the library
reads its own metadata correctly, even when the host process’s main
executable also embeds .note.package. To consume a cdylib’s metadata
at runtime, expose an extern "C" accessor and call it via dlopen;
see examples/sample_elf_bin_with_lib for the full pattern. Reading a
library file’s metadata without loading it (e.g. for crash triage) is
always possible by parsing the ELF note section from the .so on disk.
Little-endian targets only. The ELF note header is serialized with
u32::to_le_bytes at build.rs time. Supported targets today are
x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, and
i686-unknown-linux-gnu (all little-endian). Cross-compiling for a
big-endian Linux target (s390x, powerpc-be, mips-be) will silently emit
a byte-swapped note section that readelf -n and systemd-coredump
cannot parse. Adding big-endian support would mean selecting to_le_bytes
vs to_be_bytes from CARGO_CFG_TARGET_ENDIAN.
Macros§
- embed
- Force the
module_inforlib to be linked into the consuming binary so the.note.packagesection is emitted with ELF typeSHT_NOTE. - get_
module_ info - Read the embedded metadata at runtime.
- note
- Emit a styled
Info:line on cargo’s build-script output channel.
Structs§
- Embed
Artifacts - Artifacts written by
embed_package_metadata. - Embed
Options - Options controlling how
embed_package_metadatawrites artifacts and whether it emits cargo link-arg directives. - Info
- Convenience struct-literal view over
PackageMetadatawith field names shaped like the JSON keys rather than the internal Rust snake_case names. - Package
Metadata - Package metadata for embedding in the ELF
.note.packagesection.
Enums§
- Module
Info Error - Errors returned from
module_infoAPIs. - Module
Info Field - Represents the available module info fields
Functions§
- embed_
package_ metadata - Embed a
PackageMetadatavalue into ELF note artifacts on disk. - extract_
module_ ⚠info - Extract a single module-info field from a linker-script-placed symbol.
- generate_
project_ metadata_ and_ linker_ script - Zero-configuration build-script entry point.
- get_
module_ version - Returns the embedded
moduleVersionfield (a 4-part identifier typically produced by the build pipeline; seemodule_version_env_var_nameinCargo.toml’s[package.metadata.module_info]). - get_
version - Returns the embedded
versionfield (fromCargo.toml’spackage.versionorversion_env_var_name) as aString. - new
- One-call entry point: convert
Info→PackageMetadataand embed viaembed_package_metadatawithEmbedOptions::default(). - print_
module_ info - Prints all available module info to stdout and returns a result indicating success or failure
Type Aliases§
- Module
Info Result - A type alias for Results that use ModuleInfoError