This module is under construction and may not be ready for use.

pw_build_info provides tooling, build integration, and libraries for generating, embedding, and parsing build-related information that is embedded into binaries. Simple numeric version numbering doesn’t typically express things like where the binary originated, what devices it’s compatible with, whether local changes were present when the binary was built, and more. pw_build_info simplifies the process of integrating rich version metadata to answer more complex questions about compiled binaries.

GNU Build IDs

This module provides C++ and python libraries for reading GNU build IDs generated by the link step of a C++ executable. These build IDs are essentially hashes of the final linked binary, meaning two identical binaries will have identical build IDs. This can be used to accurately identify matching binaries.

Linux executables that depend on the build_id GN target will automatically generate GNU build IDs. Windows and macOS binaries cannot use this target as the implementation of GNU build IDs depends on the ELF file format.

Embedded targets must first explicitly place the GNU build ID section into a non-info section of their linker script that is readable by the firmware. The following linker snippet may be copied into a read-only section (just like the .rodata or .text sections):

 * Copyright 2021 The Pigweed Authors
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.

/* Include this linker snippet in a section of your linker script that specifies
 * where .rodata or .text will live in flash.
. = ALIGN(4);
gnu_build_id_begin = .;

This snippet may be placed directly into an existing section, as it is not required to live in its own dedicated section. When opting to create a dedicated section for the build ID to reside in, Pigweed recommends naming the section as it makes it slightly easier for tools to parse the build ID out of a binary. After the linker script has been properly set up, the build_id GN target may be used to read the build ID at runtime.

Python API reference

read_build_id_from_section(elf_file: BinaryIO) Optional[bytes]

Reads a GNU build ID from an ELF binary by searching for a section.

read_build_id_from_symbol(elf_file: BinaryIO) Optional[bytes]

Reads a GNU build ID from an ELF binary by searching for a gnu_build_id_begin symbol. This can be a rather slow operation.

read_build_id(elf_file: BinaryIO) Optional[bytes]

Reads a GNU build ID from an ELF binary, first checking for a GNU build ID section and then falling back to search for a gnu_build_id_begin symbol.

find_matching_elf(uuid: bytes, search_dir: Path) Optional[Path]

Recursively searches a directory for an ELF file with a matching UUID.

Warning: This can take on the order of several seconds.

Python utility

GNU build IDs can be parsed out of ELF files using the build_id python tool. Simply point the tool to a binary with a GNU build ID and the build ID will be printed out if it is found.

$ python -m pw_build_info.build_id my_device_image.elf