Knowledge · SBOM
SBOMs without source code: what the binary tells you about a C project
Ben Plannet, co-founder and CTO of LegacyMind GmbH · As of 5 October 2026
The short answer
An SBOM can be created without source code, straight from the shipped firmware. Even a plain C project without a package manager leaves traces of its libraries in the binary: function names, version records, source paths and version strings. Far more of that can be read from an ELF or AXF than from a BIN.
Why C projects are hard to inventory
With Node, Python or Java, a lock file states which packages in which versions are built in, and an SBOM tool reads that file. A C project rarely has one: libraries sit in the project as copied source, come from a vendor SDK or as a precompiled library. Tools that only read manifests then find little or nothing.
The linker puts everything into one binary. That is exactly where the libraries can be found again.
What the binary reveals
| Trace in the binary | What it evidences |
|---|---|
| Function names (symbol table) | Which library is linked, for example mbedtls_, lwip_, xTask |
| Source paths (debug information) | Origin, often with the version in a folder name |
| Version records | A version the library stores itself, for example RTX5 |
| Version strings as text | A version, where the library compiles one in |
| Section .comment | Compiler and version |
| Package databases (Linux) | Packages with versions from dpkg, opkg, apk or rpm |
What stays open without source code
A binary evidences what was linked. It does not always evidence the version: libraries without a version string and without a source path can be named but not dated. Checksums of individual source files cannot be recomputed from the finished binary either. An honest SBOM from the binary then leaves the version blank instead of guessing it, and says where every version it does name comes from.
BSI TR-03183-2 requires every component used by the linker to be listed in the SBOM, statically and dynamically linked alike. Data lost in the assembly, such as the hash or file name of a single library, is omitted under the guideline. Tools that only read manifests miss these components.
What LegacyMind does automatically
Microcontroller builds from Keil MDK, IAR or GNU Arm. Read: CMSIS packs, versioned from the pack vendor's own description, version records in the binary (for example RTX5) and versions from source paths (FreeRTOS, lwIP, mbedTLS, STM32Cube). Plus hardening (stack canary, MPU, privilege separation) and embedded keys.
A BIN without a file system is read byte by byte. Components are named where the bytes evidence them, for example through the version strings of TLS libraries.
The image as you ship it: archives, raw images, file systems (SquashFS, JFFS2, CramFS, UBI, YAFFS2, ext), kernel and boot images including ARM zImage, update containers and VM disks. The analysis unpacks down to the root file system and reads package databases (dpkg, opkg, apk, rpm), binaries and the kernel.
You make the conformity statement. This page and our reports provide technical findings as its basis.
Questions
- Can an SBOM be generated from a Keil or IAR build?
- Yes. Keil's AXF and IAR's .out are ELF files. Symbols, source paths and version records identify the libraries and many of their versions.
- Is an SBOM from the binary more accurate than one from the source?
- It describes something else: what is actually shipped. An SBOM from the source can name libraries the linker never took in, and one from the binary cannot evidence versions that are compiled in nowhere.
- What format is the SBOM in?
- CycloneDX and SPDX are common. LegacyMind exports CycloneDX 1.6 JSON, stating where each component was read.
Sources
Read on
Check your own image
The app and the reports are in German. Questions in English are welcome.