blob: d932ab1f4eaf6a593c0e5854fda4b3d5a3df53b6 [file] [log] [blame]
# Copyright 2022 The Fuchsia Authors
#
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT
import("//build/zircon/c_utils.gni")
# Provide an ELF executable() or loadable_module() target with a PT_INTERP
# string based on the build ID of another linking target.
#
# This defines a link-input target (as in source_set() et al) that can
# be included in $deps of executable() and similar targets. Doing so
# gives that executable a PT_INTERP value of the build ID, in canonical
# hex textual form, of whatever executable-like target was reached by
# this target's $deps.
#
# Parameters
#
# * deps
# - Required: Must reach exactly one linking target (executable, etc.) as
# per link_output_rspfile(), which see. That executable's build ID
# rendered as hex text will become the PT_INTERP string used if an
# executable links in $target_name via its transitive $deps.
# - Type: list(label)
#
# * data_deps, metadata, visibility, testonly
# - Optional: As for source_set().
#
template("kernel_elf_interp") {
main_target = target_name
inc_target = "$target_name.incbin.inc"
inc_label = ":$inc_target"
gen_dir = get_label_info(inc_label, "target_gen_dir")
elf_interp_inc_file = "$target_name.elf-interp.inc"
elf_interp_inc = "$gen_dir/$elf_interp_inc_file"
# Assemble a tiny file that defines an allocated `.interp` section.
source_set(main_target) {
forward_variables_from(invoker,
[
"data_deps",
"metadata",
"visibility",
"testonly",
])
sources = [ "//zircon/kernel/phys/elf-interp.S" ]
defines = [ "ELF_INTERP_INC=\"$elf_interp_inc_file\"" ]
include_dirs = [ gen_dir ]
inputs = [ elf_interp_inc ]
deps = [ inc_label ]
}
# Generate a file containing `.incbin "FILENAME"` to be used in the assembly.
# The source_set() depends on this so that elf-interp.S can #include the file
# in a fresh build, though since it's an #include the depfiles from the doing
# the assembly will track that (redundantly). However, those depfiles are
# only from the compiler driver doing the preprocessing; the assembler itself
# doesn't emit any depfile information about the `.incbin` use of the input
# file. So to ensure that the assembler step is repeated when *that* file
# changes, we unconditionally update this generated one-liner file whenever
# the file `.incbin` will make the assembler read was touched. This happens
# only implicitly via the depfile that the script writes, since we don't know
# what that actual file name is until we derive it from the rspfile below.
# What we use is the .stamp file that buildidtool writes. This has a name
# that's the same as the link_ouptut_path plus ".build-id.stamp" and is an
# implicit output of the linking step. GN doesn't really care that this
# output file exists, but GN tells Ninja about it being an output of the link
# step. That's enough for Ninja to ingest a depfile that refers to it and
# ensure that the next incremental build will regenerate $elf_interp_inc when
# and only when the $deps linking target was actually relinked.
#
# **NOTE:** This generation has to be evaluated separately in each toolchain
# because there's no other way to be sure that the `deps` list is resolved to
# the intended toolchain. Even if it used explicit toolchain labels, then
# those would be generated using `$current_cpu` and the like, which gets
# re-evaluated in a toolchain redirect and e.g. in $default_toolchain might
# not be the same CPU that a particular kernel or phys toolchain is using.
rspfile_target = "$target_name.interp.rspfile"
interp_rspfile = "$target_gen_dir/$target_name.elf-interp.rspfile"
action(inc_target) {
visibility = [ ":$main_target" ]
forward_variables_from(invoker, [ "testonly" ])
script = "//zircon/kernel/phys/kernel-elf-interp.sh"
sources = [ interp_rspfile ]
deps = [ ":$rspfile_target" ]
outputs = [ elf_interp_inc ]
depfile = "$elf_interp_inc.d"
args = rebase_path(sources + outputs + [ depfile ], root_build_dir)
metadata = {
# Don't propagate from zbi_input()-compatible or resource() targets.
zbi_input_barrier = []
distribution_entries_barrier = []
}
}
# Before all else, we need an rspfile that shows the file name that the
# link step wrote. The handy template generates an rspfile that contains
# the name of the main output file. The buildidtool file we need has a
# name that can be derived from this file name.
link_output_rspfile(rspfile_target) {
visibility = [ ":$inc_target" ]
forward_variables_from(invoker,
[
"deps",
"testonly",
])
outputs = [ interp_rspfile ]
}
}