Skip to main content

Crate module_info

Crate module_info 

Source
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_info rlib to be linked into the consuming binary so the .note.package section is emitted with ELF type SHT_NOTE.
get_module_info
Read the embedded metadata at runtime.
note
Emit a styled Info: line on cargo’s build-script output channel.

Structs§

EmbedArtifacts
Artifacts written by embed_package_metadata.
EmbedOptions
Options controlling how embed_package_metadata writes artifacts and whether it emits cargo link-arg directives.
Info
Convenience struct-literal view over PackageMetadata with field names shaped like the JSON keys rather than the internal Rust snake_case names.
PackageMetadata
Package metadata for embedding in the ELF .note.package section.

Enums§

ModuleInfoError
Errors returned from module_info APIs.
ModuleInfoField
Represents the available module info fields

Functions§

embed_package_metadata
Embed a PackageMetadata value 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 moduleVersion field (a 4-part identifier typically produced by the build pipeline; see module_version_env_var_name in Cargo.toml’s [package.metadata.module_info]).
get_version
Returns the embedded version field (from Cargo.toml’s package.version or version_env_var_name) as a String.
new
One-call entry point: convert InfoPackageMetadata and embed via embed_package_metadata with EmbedOptions::default().
print_module_info
Prints all available module info to stdout and returns a result indicating success or failure

Type Aliases§

ModuleInfoResult
A type alias for Results that use ModuleInfoError