1---
2title: Package Metadata for Core Files
3category: Interfaces
4layout: default
5SPDX-License-Identifier: LGPL-2.1-or-later
6---
7
8# Package Metadata for Core Files
9
10*Intended audience: hackers working on userspace subsystems that create ELF binaries
11or parse ELF core files.*
12
13## Motivation
14
15ELF binaries get stamped with a unique, build-time generated hex string identifier called
16`build-id`, [which gets embedded as an ELF note called `.note.gnu.build-id`](https://fedoraproject.org/wiki/Releases/FeatureBuildId).
17In most cases, this allows to associate a stripped binary with its debugging information.
18It is used, for example, to dynamically fetch DWARF symbols from a debuginfo server, or
19to query the local package manager and find out the package metadata or, again, the DWARF
20symbols or program sources.
21
22However, this usage of the `build-id` requires either local metadata, usually set up by
23the package manager, or access to a remote server over the network. Both of those might
24be unavailable or forbidden.
25
26Thus it becomes desirable to add additional metadata to a binary at build time, so that
27`systemd-coredump` and other services analyzing core files are able to extract said
28metadata simply from the core file itself, without external dependencies.
29
30## Implementation
31
32This document will attempt to define a common metadata format specification, so that
33multiple implementers might use it when building packages, or core file analyzers, and
34so on.
35
36The metadata will be embedded in a single, new, 4-bytes-aligned, allocated, 0-padded,
37read-only ELF header section, in a name-value JSON object format. Implementers working on parsing
38core files should not assume a specific list of names, but parse anything that is included
39in the section, and should look for the note using the `note type`. Implementers working on
40build tools should strive to use the same names, for consistency. The most common will be
41listed here. When corresponding to the content of os-release, the values should match, again for consistency.
42
43If available, the metadata should also include the debuginfod server URL that can provide
44the original executable, debuginfo and sources, to further facilitate debugging.
45
46* Section header
47
48```
49SECTION: `.note.package`
50note type: `0xcafe1a7e`
51Owner: `FDO` (FreeDesktop.org)
52Value: a single JSON object encoded as a zero-terminated UTF-8 string
53```
54
55* JSON payload
56
57```json
58{
59     "type":"rpm",          # this provides a namespace for the package+package-version fields
60     "os":"fedora",
61     "osVersion":"33",
62     "name":"coreutils",
63     "version":"4711.0815.fc13",
64     "architecture":"arm32",
65     "osCpe": "cpe:/o:fedoraproject:fedora:33",          # A CPE name for the operating system, `CPE_NAME` from os-release is a good default
66     "debugInfoUrl": "https://debuginfod.fedoraproject.org/"
67}
68```
69
70The format is a single JSON object, encoded as a zero-terminated `UTF-8` string.
71Each name in the object shall be unique as per recommendations of
72[RFC8259](https://datatracker.ietf.org/doc/html/rfc8259#section-4). Strings shall
73not contain any control character, nor use `\uXXX` escaping.
74
75When it comes to JSON numbers, this specification assumes that JSON parsers
76processing this information are capable of reproducing the full signed 53bit
77integer range (i.e. -2⁵³+1…+2⁵³-1) as well as the full 64bit IEEE floating
78point number range losslessly (with the exception of NaN/-inf/+inf, since JSON
79cannot encode that), as per recommendations of
80[RFC8259](https://datatracker.ietf.org/doc/html/rfc8259#page-8). Fields in
81these JSON objects are thus permitted to encode numeric values from these
82ranges as JSON numbers, and should not use numeric values not covered by these
83types and ranges.
84
85A reference implementations of a [build-time tool is provided](https://github.com/systemd/package-notes)
86and can be used to generate a linker script, which can then be used at build time via
87```LDFLAGS="-Wl,-T,/path/to/generated/script"``` to include the note in the binary.
88
89Generator:
90```console
91$ ./generate-package-notes.py --rpm systemd-248~rc2-1.fc33.arm32 --cpe cpe:/o:fedoraproject:fedora:33
92SECTIONS
93{
94    .note.package (READONLY) : ALIGN(4) {
95        LONG(0x0004)                                /* Length of Owner including NUL */
96        LONG(0x007b)                                /* Length of Value including NUL */
97        LONG(0xcafe1a7e)                            /* Note ID */
98        BYTE(0x46) BYTE(0x44) BYTE(0x4f) BYTE(0x00) /* Owner: 'FDO\x00' */
99        BYTE(0x7b) BYTE(0x22) BYTE(0x74) BYTE(0x79) /* Value: '{"type":"rpm","name":"systemd","version":"248~rc2-1.fc33","architecture":"arm32","osCpe":"cpe:/o:fedoraproject:fedora:33"}\x00\x00' */
100        BYTE(0x70) BYTE(0x65) BYTE(0x22) BYTE(0x3a)
101        BYTE(0x22) BYTE(0x72) BYTE(0x70) BYTE(0x6d)
102        BYTE(0x22) BYTE(0x2c) BYTE(0x22) BYTE(0x6e)
103        BYTE(0x61) BYTE(0x6d) BYTE(0x65) BYTE(0x22)
104        BYTE(0x3a) BYTE(0x22) BYTE(0x73) BYTE(0x79)
105        BYTE(0x73) BYTE(0x74) BYTE(0x65) BYTE(0x6d)
106        BYTE(0x64) BYTE(0x22) BYTE(0x2c) BYTE(0x22)
107        BYTE(0x76) BYTE(0x65) BYTE(0x72) BYTE(0x73)
108        BYTE(0x69) BYTE(0x6f) BYTE(0x6e) BYTE(0x22)
109        BYTE(0x3a) BYTE(0x22) BYTE(0x32) BYTE(0x34)
110        BYTE(0x38) BYTE(0x7e) BYTE(0x72) BYTE(0x63)
111        BYTE(0x32) BYTE(0x2d) BYTE(0x31) BYTE(0x2e)
112        BYTE(0x66) BYTE(0x63) BYTE(0x33) BYTE(0x33)
113        BYTE(0x22) BYTE(0x2c) BYTE(0x22) BYTE(0x61)
114        BYTE(0x72) BYTE(0x63) BYTE(0x68) BYTE(0x69)
115        BYTE(0x74) BYTE(0x65) BYTE(0x63) BYTE(0x74)
116        BYTE(0x75) BYTE(0x72) BYTE(0x65) BYTE(0x22)
117        BYTE(0x3a) BYTE(0x22) BYTE(0x61) BYTE(0x72)
118        BYTE(0x6d) BYTE(0x33) BYTE(0x32) BYTE(0x22)
119        BYTE(0x2c) BYTE(0x22) BYTE(0x6f) BYTE(0x73)
120        BYTE(0x43) BYTE(0x70) BYTE(0x65) BYTE(0x22)
121        BYTE(0x3a) BYTE(0x22) BYTE(0x63) BYTE(0x70)
122        BYTE(0x65) BYTE(0x3a) BYTE(0x2f) BYTE(0x6f)
123        BYTE(0x3a) BYTE(0x66) BYTE(0x65) BYTE(0x64)
124        BYTE(0x6f) BYTE(0x72) BYTE(0x61) BYTE(0x70)
125        BYTE(0x72) BYTE(0x6f) BYTE(0x6a) BYTE(0x65)
126        BYTE(0x63) BYTE(0x74) BYTE(0x3a) BYTE(0x66)
127        BYTE(0x65) BYTE(0x64) BYTE(0x6f) BYTE(0x72)
128        BYTE(0x61) BYTE(0x3a) BYTE(0x33) BYTE(0x33)
129        BYTE(0x22) BYTE(0x7d) BYTE(0x00) BYTE(0x00)
130    }
131}
132INSERT AFTER .note.gnu.build-id;
133```
134
135## Well-known keys
136
137The metadata format is intentionally left open, so that vendors can add their own information.
138A set of well-known keys is defined here, and hopefully shared among all vendors.
139
140| Key name     | Key description                                                          | Example value                         |
141|--------------|--------------------------------------------------------------------------|---------------------------------------|
142| type         | The packaging type                                                       | rpm                                   |
143| os           | The OS name, typically corresponding to ID in os-release                 | fedora                                |
144| osVersion    | The OS version, typically corresponding to VERSION_ID in os-release      | 33                                    |
145| name         | The source package name                                                  | coreutils                             |
146| version      | The source package version                                               | 4711.0815.fc13                        |
147| architecture | The binary package architecture                                          | arm32                                 |
148| osCpe        | A CPE name for the OS, typically corresponding to CPE_NAME in os-release | cpe:/o:fedoraproject:fedora:33        |
149| debugInfoUrl | The debuginfod server url, if available                                  | https://debuginfod.fedoraproject.org/ |
150