RepoMicrosoftMicrosoftpublished Apr 29, 2026seen 5d

microsoft/module-info

Rust

Open original ↗

Captured source

source ↗
published Apr 29, 2026seen 5dcaptured 14hhttp 200method plain

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.

![Documentation](https://docs.rs/module-info)

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.package section 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 AFTER linker

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/10

Low traction, trivial repo