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