• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/build_defs/cc:action_names.bzl", "ACTION_NAMES")
17load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
18load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
19load("//pw_toolchain/action:action_names.bzl", "PW_ACTION_NAMES")
20
21def run_action_on_executable(
22        ctx,
23        action_name,
24        action_args,
25        inputs,
26        output,
27        additional_outputs,
28        output_executable = False):
29    """Macro to be used in rule implementation to run an action on input executable.
30
31    Looks up the current toolchain to find the path to the specified action.
32
33    Args:
34      ctx: Rule context
35      action_name: The name of the action
36      action_args: Arguments to pass to the action
37      inputs: Input files to use in the action
38      output: The output generated by the action
39      additional_outputs: Extra output objects that should be bundled into the result
40      output_executable: True if the output is an executable
41    Returns:
42      DefaultInfo with the output and additional_outputs.
43    """
44    cc_toolchain = find_cpp_toolchain(ctx)
45
46    feature_configuration = cc_common.configure_features(
47        ctx = ctx,
48        cc_toolchain = cc_toolchain,
49        requested_features = ctx.features,
50        unsupported_features = ctx.disabled_features,
51    )
52    tool_path = cc_common.get_tool_for_action(
53        feature_configuration = feature_configuration,
54        action_name = action_name,
55    )
56
57    ctx.actions.run_shell(
58        inputs = depset(
59            direct = inputs,
60            transitive = [
61                cc_toolchain.all_files,
62            ],
63        ),
64        outputs = [output],
65        command = "{tool} {args}".format(
66            tool = tool_path,
67            args = action_args,
68        ),
69    )
70
71    return DefaultInfo(
72        files = depset([output] + additional_outputs),
73        executable = output if output_executable else None,
74    )
75
76def _pw_elf_to_bin_impl(ctx):
77    return run_action_on_executable(
78        ctx = ctx,
79        # TODO: https://github.com/bazelbuild/rules_cc/issues/292 - Add a helper
80        # to rules cc to make it possible to get this from ctx.attr._objcopy.
81        action_name = ACTION_NAMES.objcopy_embed_data,
82        action_args = "{args} {input} {output}".format(
83            args = "-Obinary",
84            input = ctx.executable.elf_input.path,
85            output = ctx.outputs.bin_out.path,
86        ),
87        inputs = [ctx.executable.elf_input],
88        output = ctx.outputs.bin_out,
89        additional_outputs = ctx.files.elf_input,
90        output_executable = True,
91    )
92
93pw_elf_to_bin = rule(
94    implementation = _pw_elf_to_bin_impl,
95    doc = """Takes in an ELF executable and uses the toolchain objcopy tool to
96    create a binary file, not containing any ELF headers. This can be used to
97    create a bare-metal bootable image.
98    """,
99    attrs = {
100        "bin_out": attr.output(mandatory = True),
101        "elf_input": attr.label(mandatory = True, executable = True, cfg = "target"),
102        "_objcopy": attr.label(
103            default = "@rules_cc//cc/toolchains/actions:objcopy_embed_data",
104        ),
105    },
106    executable = True,
107    toolchains = use_cpp_toolchain(),
108    fragments = ["cpp"],
109)
110
111def _pw_elf_to_dump_impl(ctx):
112    return run_action_on_executable(
113        ctx = ctx,
114        # TODO: https://github.com/bazelbuild/rules_cc/issues/292 - Add a helper
115        # to rules cc to make it possible to get this from ctx.attr._objdump.
116        action_name = PW_ACTION_NAMES.objdump_disassemble,
117        action_args = "{args} {input} > {output}".format(
118            args = "-dx",
119            input = ctx.executable.elf_input.path,
120            output = ctx.outputs.dump_out.path,
121        ),
122        inputs = [ctx.executable.elf_input],
123        output = ctx.outputs.dump_out,
124        additional_outputs = ctx.files.elf_input,
125    )
126
127pw_elf_to_dump = rule(
128    implementation = _pw_elf_to_dump_impl,
129    doc = """Takes in an ELF executable and uses the toolchain objdump tool to
130    create a text file dump of the contents.
131    """,
132    attrs = {
133        "dump_out": attr.output(mandatory = True),
134        "elf_input": attr.label(mandatory = True, executable = True, cfg = "target"),
135        "_objdump": attr.label(
136            default = "//pw_toolchain/action:objdump_disassemble",
137        ),
138    },
139    toolchains = use_cpp_toolchain(),
140    fragments = ["cpp"],
141)
142