forked from google/pigweed
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pw_build_info: Add GNU build ID support
Introduces the pw_build_info module, and adds support for reading GNU build IDs from python and from inside the context of a C++ application. Change-Id: I105627cffff28f5a6a2dbdf396be34143b0637d9 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/53760 Reviewed-by: Wyatt Hepler <[email protected]> Reviewed-by: Ewout van Bekkum <[email protected]> Commit-Queue: Armando Montanez <[email protected]>
- Loading branch information
1 parent
81017fe
commit 6954a8d
Showing
16 changed files
with
605 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# 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 | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# 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. | ||
|
||
load( | ||
"//pw_build:pigweed.bzl", | ||
"pw_cc_library", | ||
) | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
licenses(["notice"]) | ||
|
||
pw_cc_library( | ||
name = "build_id", | ||
srcs = [ | ||
"build_id.cc", | ||
], | ||
hdrs = [ | ||
"public/pw_build_info/build_id.h", | ||
], | ||
includes = ["public"], | ||
deps = [ | ||
"//pw_preprocessor", | ||
], | ||
) | ||
|
||
|
||
# This is only used for the python tests. | ||
filegroup( | ||
name = "build_id_print_test", | ||
srcs = [ | ||
"py/print_build_id.cc", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# 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 | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# 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. | ||
|
||
import("//build_overrides/pigweed.gni") | ||
|
||
import("$dir_pw_build/target_types.gni") | ||
import("$dir_pw_docgen/docs.gni") | ||
|
||
config("linker_script") { | ||
inputs = [ "build_id_linker_snippet.ld" ] | ||
|
||
# Automatically add the gnu build ID linker sections when building for Linux. | ||
# macOS and Windows executables are not supported, and embedded targets must | ||
# manually add the snippet to their linker script in a read-only section. | ||
if (current_os == "linux") { | ||
# When building for Linux, the linker provides a default linker script. | ||
# The add_build_id_to_default_script.ld wrapper includes the | ||
# build_id_linker_snippet.ld script in a way that appends to the the | ||
# default linker script instead of overriding it. | ||
ldflags = [ | ||
"-T", | ||
rebase_path("add_build_id_to_default_script.ld", root_build_dir), | ||
] | ||
lib_dirs = [ "." ] | ||
|
||
inputs += [ "add_build_id_to_default_script.ld" ] | ||
} | ||
visibility = [ ":*" ] | ||
} | ||
|
||
config("gnu_build_id") { | ||
ldflags = [ "-Wl,--build-id=sha1" ] | ||
} | ||
|
||
config("public_include_path") { | ||
include_dirs = [ "public" ] | ||
visibility = [ ":*" ] | ||
} | ||
|
||
# GNU build IDs aren't supported by Windows and macOS. | ||
if (current_os != "mac" && current_os != "win") { | ||
pw_source_set("build_id") { | ||
all_dependent_configs = [ | ||
":gnu_build_id", | ||
":linker_script", | ||
] | ||
public_configs = [ ":public_include_path" ] | ||
cflags = [ | ||
"-Wno-array-bounds", | ||
"-Wno-stringop-overflow", | ||
] | ||
public = [ "public/pw_build_info/build_id.h" ] | ||
sources = [ "build_id.cc" ] | ||
deps = [ dir_pw_preprocessor ] | ||
} | ||
} | ||
|
||
pw_doc_group("docs") { | ||
sources = [ "docs.rst" ] | ||
inputs = [ "build_id_linker_snippet.ld" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* 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 | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* 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. | ||
*/ | ||
|
||
SECTIONS | ||
{ | ||
.note.gnu.build-id : | ||
{ | ||
INCLUDE build_id_linker_snippet.ld | ||
} | ||
} | ||
|
||
/* | ||
* The INSERT directive instructs the linker to append the directives in this | ||
* script to the default linker script, rather than replace the default with | ||
* this script. The build ID is read only, so place it just after .rodata. | ||
*/ | ||
INSERT AFTER .rodata |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// 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 | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// 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 "pw_build_info/build_id.h" | ||
|
||
#include <cstdint> | ||
#include <cstring> | ||
#include <span> | ||
|
||
#include "pw_preprocessor/compiler.h" | ||
|
||
extern "C" const uint8_t gnu_build_id_begin; | ||
|
||
namespace pw::build_info { | ||
namespace { | ||
|
||
PW_PACKED(struct) ElfNoteInfo { | ||
uint32_t name_size; | ||
uint32_t descriptor_size; | ||
uint32_t type; | ||
}; | ||
|
||
} // namespace | ||
|
||
std::span<const std::byte> BuildId() { | ||
// Read the sizes at the beginning of the note section. | ||
ElfNoteInfo build_id_note_sizes; | ||
memcpy( | ||
&build_id_note_sizes, &gnu_build_id_begin, sizeof(build_id_note_sizes)); | ||
// Skip the "name" entry of the note section, and return a span to the | ||
// descriptor. | ||
return std::as_bytes(std::span(&gnu_build_id_begin + | ||
sizeof(build_id_note_sizes) + | ||
build_id_note_sizes.name_size, | ||
build_id_note_sizes.descriptor_size)); | ||
} | ||
|
||
} // namespace pw::build_info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* 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 | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* 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 = .; | ||
*(.note.gnu.build-id); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
.. _module-pw_build_info: | ||
|
||
------------- | ||
pw_build_info | ||
------------- | ||
|
||
.. warning:: | ||
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): | ||
|
||
.. literalinclude:: build_id_linker_snippet.ld | ||
|
||
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 ``.note.gnu.build-id`` 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 tooling | ||
-------------- | ||
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. | ||
|
||
.. code-block:: sh | ||
$ python -m pw_build_info.build_id my_device_image.elf | ||
d43cce74f18522052f77a1fa3fb7a25fe33f40dd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// 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 | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// 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. | ||
#pragma once | ||
|
||
#include <cstddef> | ||
#include <span> | ||
|
||
namespace pw::build_info { | ||
|
||
// Build IDs may be generated with several different algorithms. The largest of | ||
// these (aside from user-provided build IDs) are a fixed size of 20 bytes. | ||
inline constexpr size_t kMaxBuildIdSizeBytes = 20; | ||
|
||
// Reads a GNU build ID from the address starting at the address of the | ||
// `gnu_build_id_begin` symbol. This must be manually explicitly provided as | ||
// part of a linker script. See build_id_linker_snippet.ld for an example. | ||
std::span<const std::byte> BuildId(); | ||
|
||
} // namespace pw::build_info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# 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 | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# 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. | ||
|
||
import("//build_overrides/pigweed.gni") | ||
|
||
import("$dir_pw_build/python.gni") | ||
|
||
pw_python_package("py") { | ||
generate_setup = { | ||
name = "pw_build_info" | ||
version = "0.0.1" | ||
install_requires = [ "pyelftools" ] | ||
} | ||
inputs = [ "print_build_id.cc" ] | ||
sources = [ | ||
"pw_build_info/__init__.py", | ||
"pw_build_info/build_id.py", | ||
] | ||
|
||
# This test will only ever work on Linux as it requires the ability to compile | ||
# AND run an ELF file. | ||
if (host_os == "linux") { | ||
tests = [ "build_id_test.py" ] | ||
python_test_deps = [ "$dir_pw_cli/py" ] | ||
} | ||
|
||
pylintrc = "$dir_pigweed/.pylintrc" | ||
} |
Oops, something went wrong.