xref: /aosp_15_r20/external/pigweed/pw_build/binary_tools.bzl (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2024 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Rules for processing binary executables."""
15
16load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
17load("@pw_toolchain//actions:providers.bzl", "ActionNameInfo")
18
19def _run_action_on_executable(
20        ctx,
21        action_name,
22        action_args,
23        input,
24        output,
25        additional_outputs,
26        output_executable = False):
27    """Macro to be used in rule implementation to run an action on input executable.
28
29    Looks up the current toolchain to find the path to the specified action."""
30    cc_toolchain = find_cpp_toolchain(ctx)
31
32    feature_configuration = cc_common.configure_features(
33        ctx = ctx,
34        cc_toolchain = cc_toolchain,
35        requested_features = ctx.features,
36        unsupported_features = ctx.disabled_features,
37    )
38    tool_path = cc_common.get_tool_for_action(
39        feature_configuration = feature_configuration,
40        action_name = action_name,
41    )
42
43    ctx.actions.run_shell(
44        inputs = depset(
45            direct = [input],
46            transitive = [
47                cc_toolchain.all_files,
48            ],
49        ),
50        outputs = [output],
51        command = "{tool} {args}".format(
52            tool = tool_path,
53            args = action_args,
54        ),
55    )
56
57    return DefaultInfo(
58        files = depset([output] + additional_outputs),
59        executable = output if output_executable else None,
60    )
61
62def _pw_elf_to_bin_impl(ctx):
63    return _run_action_on_executable(
64        ctx = ctx,
65        action_name = ctx.attr._objcopy[ActionNameInfo].name,
66        action_args = "{args} {input} {output}".format(
67            args = "-Obinary",
68            input = ctx.executable.elf_input.path,
69            output = ctx.outputs.bin_out.path,
70        ),
71        input = ctx.executable.elf_input,
72        output = ctx.outputs.bin_out,
73        additional_outputs = ctx.files.elf_input,
74        output_executable = True,
75    )
76
77pw_elf_to_bin = rule(
78    implementation = _pw_elf_to_bin_impl,
79    doc = """Takes in an ELF executable and uses the toolchain objcopy tool to
80    create a binary file, not containing any ELF headers. This can be used to
81    create a bare-metal bootable image.
82    """,
83    attrs = {
84        "bin_out": attr.output(mandatory = True),
85        "elf_input": attr.label(mandatory = True, executable = True, cfg = "target"),
86        "_objcopy": attr.label(
87            default = "@pw_toolchain//actions:objcopy_embed_data",
88            providers = [ActionNameInfo],
89        ),
90    },
91    executable = True,
92    toolchains = use_cpp_toolchain(),
93    fragments = ["cpp"],
94)
95
96def _pw_elf_to_dump_impl(ctx):
97    return _run_action_on_executable(
98        ctx = ctx,
99        action_name = ctx.attr._objdump[ActionNameInfo].name,
100        action_args = "{args} {input} > {output}".format(
101            args = "-dx",
102            input = ctx.executable.elf_input.path,
103            output = ctx.outputs.dump_out.path,
104        ),
105        input = ctx.executable.elf_input,
106        output = ctx.outputs.dump_out,
107        additional_outputs = ctx.files.elf_input,
108    )
109
110pw_elf_to_dump = rule(
111    implementation = _pw_elf_to_dump_impl,
112    doc = """Takes in an ELF executable and uses the toolchain objdump tool to
113    create a text file dump of the contents.
114    """,
115    attrs = {
116        "dump_out": attr.output(mandatory = True),
117        "elf_input": attr.label(mandatory = True, executable = True, cfg = "target"),
118        "_objdump": attr.label(
119            default = "@pw_toolchain//actions:objdump_embed_data",
120            providers = [ActionNameInfo],
121        ),
122    },
123    toolchains = use_cpp_toolchain(),
124    fragments = ["cpp"],
125)
126