Skip to content

Commit

Permalink
pw_build: Add pw_elf_to_bin rule
Browse files Browse the repository at this point in the history
This rule calls objcopy from the toolchain to remove all ELF headers
from a binary executable target. This can be used to produce baremetal
bootable images.

Change-Id: Ic0018e2f8d4913a4f7510273ef240101aebce180
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/212671
Lint: Lint 🤖 <[email protected]>
Presubmit-Verified: CQ Bot Account <[email protected]>
Commit-Queue: Austin Foxley <[email protected]>
Reviewed-by: Ted Pudlik <[email protected]>
  • Loading branch information
afoxley authored and CQ Bot Account committed May 31, 2024
1 parent fc373c8 commit 201c503
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
16 changes: 16 additions & 0 deletions pw_build/bazel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,22 @@ This should result in a ``test.map`` file generated next to the ``test`` binary.
Note that it's only partially compatible with the ``cc_binary`` interface and
certain things are not implemented like make variable substitution.

pw_elf_to_bin
-------------
The ``pw_elf_to_bin`` rule takes in a binary executable target and produces a
file with all ELF headers removed. It uses the toolchains ``objcopy``
tool. This output is commonly used to boot images on baremetal.

.. code-block::
load("@pigweed//pw_build:binary_tools.bzl", "pw_elf_to_bin")
pw_elf_to_bin(
name = "bin",
elf_input = ":main",
bin_out = "main.bin",
)
Miscellaneous utilities
-----------------------

Expand Down
7 changes: 7 additions & 0 deletions pw_build/bazel_internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations under
# the License.

load("//pw_build:binary_tools.bzl", "pw_elf_to_bin")
load("//pw_build:pigweed.bzl", "pw_linker_script")

cc_library(
Expand Down Expand Up @@ -97,3 +98,9 @@ cc_binary(
"//conditions:default": [],
}),
)

pw_elf_to_bin(
name = "test_bin",
bin_out = "test.bin",
elf_input = ":test_linker_script",
)
71 changes: 71 additions & 0 deletions pw_build/binary_tools.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright 2024 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.
"""Rules for processing binary executables."""

load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
load("@pw_toolchain//actions:providers.bzl", "ActionNameInfo")

def _pw_elf_to_bin_impl(ctx):
cc_toolchain = find_cpp_toolchain(ctx)

feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features,
unsupported_features = ctx.disabled_features,
)
objcopy_path = cc_common.get_tool_for_action(
feature_configuration = feature_configuration,
action_name = ctx.attr._objcopy[ActionNameInfo].name,
)

ctx.actions.run_shell(
inputs = depset(
direct = [ctx.executable.elf_input],
transitive = [
cc_toolchain.all_files,
],
),
outputs = [ctx.outputs.bin_out],
command = "{objcopy} {args} {input} {output}".format(
objcopy = objcopy_path,
args = "-Obinary",
input = ctx.executable.elf_input.path,
output = ctx.outputs.bin_out.path,
),
)

return DefaultInfo(
files = depset([ctx.outputs.bin_out] + ctx.files.elf_input),
executable = ctx.outputs.bin_out,
)

pw_elf_to_bin = rule(
implementation = _pw_elf_to_bin_impl,
doc = """Takes in an ELF executable and uses the toolchain objcopy tool to
create a binary file, not containing any ELF headers. This can be used to
create a bare-metal bootable image.
""",
attrs = {
"bin_out": attr.output(mandatory = True),
"elf_input": attr.label(mandatory = True, executable = True, cfg = "target"),
"_objcopy": attr.label(
default = "@pw_toolchain//actions:objcopy_embed_data",
providers = [ActionNameInfo],
),
},
executable = True,
toolchains = use_cpp_toolchain(),
fragments = ["cpp"],
)

0 comments on commit 201c503

Please sign in to comment.