microsoft/module-info
Rust
Captured source
source ↗microsoft/module-info
Description: Rust crate that embeds build metadata into ELF .note.package sections so module version, package version, and other provenance info survives in core dumps.
Language: Rust
License: NOASSERTION
Stars: 1
Forks: 0
Open issues: 5
Created: 2026-04-29T22:36:31Z
Pushed: 2026-06-04T01:07:06Z
Default branch: main
Fork: no
Archived: no
README:
Module Info
Embed build-time metadata (version, git commit, maintainer, OS) into your Rust binary so it survives crashes. The data lives in an ELF .note.package section, so when your process dies and dumps core, the metadata travels with it. Tools like coredumpctl, readelf -n, and GDB see exactly which build crashed, even if the binary has been redeployed or deleted.

Why module-info?
When a deployed binary crashes, the hardest question is often "which build was this?" Symbol files get lost, tags drift, and the binary on disk may already be gone. module-info answers it from the core dump alone:
- Survives the crash. The metadata is an ELF note baked into the image, so
it is captured in the core dump even if the binary has been redeployed or deleted.
- Standard, tool-ready format. Follows the [systemd package-metadata
spec](https://uapi-group.org/specifications/specs/package_metadata_for_executable_files/), so coredumpctl, readelf -n, GDB, and existing crash-analysis tooling read it with no changes.
- Auto-detected. Version, git branch/commit/repo, OS, and package details
are collected at build time from Cargo.toml, git, and the OS. A typical setup needs three lines.
- Build-time only. The note is written during the build, so carrying it
costs nothing at runtime. Reading the metadata back from inside the running process is optional and lives behind the embed-module-info feature.
- Executables and shared libraries. Both carry their own
.note.package. - Cross-platform safe. Compiles everywhere; it is a no-op on non-Linux
targets, so the same source builds on Windows and macOS.
What gets embedded
A small JSON record in the binary's .note.package section, one key/value pair per line and ASCII-only (see [Limitations](#limitations)):
{
"binary":"sample_crashing_process",
"moduleVersion":"0.1.0.0",
"version":"0.1.0",
"maintainer":"team@contoso.com",
"name":"sample_crashing_process",
"type":"tool",
"repo":"module-info",
"branch":"main",
"hash":"9fbf13be41d9c29f056588f6ef97509e534a51f5",
"copyright":"Contoso, Ltd.",
"os":"ubuntu",
"osVersion":"20.04"
}Reading it back needs no special tooling. On binutils 2.39+, readelf -n decodes the note directly:
$ readelf -n ./sample_crashing_process
...
Displaying notes found in: .note.package
Owner Data size Description
FDO 0x00000144 FDO_PACKAGING_METADATA
Packaging Metadata: {"binary":"sample_crashing_process","moduleVersion":"0.1.0.0", ... }(The exact Data size depends on your field values.)
Quick start
1. Add the dependency.
cargo add module-info --features embed-module-info cargo add --build module-info
Requires Rust 1.74 or newer.
2. Add a `build.rs` at your project root:
fn main() -> Result> {
module_info::generate_project_metadata_and_linker_script()?;
Ok(())
}3. Embed the note by adding one macro at your crate root (src/main.rs or src/lib.rs):
module_info::embed!();
That's it. Your binary now carries its metadata. Most fields are detected automatically from Cargo.toml, git, and the OS. To set the maintainer and a few extras, add this to Cargo.toml:
[package.metadata.module_info] maintainer = "team@contoso.com" # contact email or team UUID type = "agent" # optional copyright = "Contoso, Ltd." # optional
How the three pieces fit. The [build-dependencies] entry runs the build script, which collects the metadata and tells the linker to add the .note.package section. The [dependencies] entry plus the embed-module-info feature anchor that section in the final binary and provide the runtime read-back API. module_info::embed!() is that anchor; it expands to nothing on non-Linux targets, so the same source builds everywhere. In a workspace, each binary or shared library that should carry metadata needs its own build.rs and embed!() call.
Read it back at runtime (optional)
use module_info::get_module_info;
if let Ok(version) = get_module_info!(ModuleInfoField::Version) {
println!("Version: {version}");
}
// Or grab everything as a HashMap:
if let Ok(all) = get_module_info!() {
for (key, value) in all {
println!("{key}: {value}");
}
}ModuleInfoField does not need importing: the get_module_info! macro matches the variant name (e.g. ModuleInfoField::Version) as a token.
Runtime read-back is a convenience; the main feature is that the metadata is recoverable from a crash dump without it.
Platform support
- Linux: full functionality. Emits the
.note.packagesection at build
time; runtime accessors read it back.
- Windows / macOS / other: no-op. Nothing is embedded, build-script entry
points compile to empty stubs (so the same source builds everywhere), and the runtime accessors return ModuleInfoError::NotAvailable, so handle that in cross-platform code.
Verify it worked
$ readelf -n ./your_binary # binutils >= 2.39 prints the JSON directly $ objcopy --dump-section .note.package=/dev/stdout ./your_binary
.note.package is an allocated section, so it survives strip.
Reading metadata from a core dump
This is the payoff: because the note sits in the first read-only page, it is captured in the core dump even when the binary is gone. A core has no section headers, so pull a field straight out of the dumped bytes with strings:
$ strings core | grep -oE '"moduleVersion":"[^"]+"' "moduleVersion":"0.1.0.0"
Or use coredumpctl on systemd hosts. The [full guide](docs/GUIDE.md#reading-from-a-core-dump) has the full commands, and the sample_crashing_process example exercises it end to end.
Limitations
- Linux/ELF only. On other targets embedding is a no-op (the build still
compiles) and the runtime accessors return ModuleInfoError::NotAvailable.
- GNU ld / gold linker. The note is placed with an
INSERT AFTERlinker
script. Alternative linkers (lld, mold) may not honor it; if you use one, confirm the section is…
Excerpt shown — open the source for the full document.
Notability
notability 2.0/10Low traction, trivial repo