blob: 0307d7a5fc547c6f98edf8059feef8254afea5f8 [file] [log] [blame]
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/zircon/c_utils.gni")
# Defines an hermetic code blob, which is defined by the following properties
# (enforced at link-time):
#
# * the named function (`entrypoint`) is first in the link order and all of the
# sources/deps together form a closed set that is collectively hermetic;
# * no dynamic relocations.
#
# It produces the raw binary content of a position-indepdendent executable,
# output to "$target_out_dir/$output_name.bin". This is the output file of the
# primary target. If $public, $public_configs, or $public_deps is provided
# (even if empty), then a "$target_name.public" source_set() target will also
# be defined; that can be used in $deps of compiling targets that use the
# $public headers.
#
# Parameters
#
# * allow_rodata
# - Optional: If true, .rodata* sections in the hermetic code are allowed.
# By default, only .text* (executable code) sections are permitted.
# - Type: bool
# - Default: false
#
# * add_configs
# - Optional: Additional configs added to the default list for compilation.
# - Type: list(label)
# - Default: []
#
# * entrypoint
# - Optional: The name of the symbol (or C function) that is the entrypoint
# to this code blob.
# - Type: string
# - Default: $target_name.
#
# * output_name
# - Optional: The output file will be "$target_out_dir/$output_name.bin".
# - Type: string
# - Default: target_name
#
# * public, public_deps, public_configs
# - Optional: As for source_set(). These are passed on to the
# "$target_name.public" target rather than the main target.
# The underlying executable() target implicitly depends on that
# target, so it gets these configs and deps indirectly and can
# use the $public headers itself.
#
# Other parameters are as for executable(), except for the `output_*`
# parameters.
#
template("hermetic_code_blob") {
image_target = target_name
executable_target = "_hermetic_code_blob.$target_name.executable"
if (defined(invoker.entrypoint)) {
entrypoint = invoker.entrypoint
} else {
entrypoint = target_name
}
allow_rodata = defined(invoker.allow_rodata) && invoker.allow_rodata
if (defined(invoker.public) || defined(invoker.public_configs) ||
defined(invoker.public_deps)) {
public_target = "$target_name.public"
public_target_deps = [ ":$public_target" ]
} else {
public_target_deps = []
}
executable(executable_target) {
forward_variables_from(invoker, [ "testonly" ])
visibility = [ ":*" ]
deps = []
ldflags = []
exclude_toolchain_tags = []
forward_variables_from(invoker,
"*",
[
"add_configs",
"allow_rodata",
"configs",
"entrypoint",
"metadata",
"output_dir",
"output_extension",
"public",
"public_configs",
"public_deps",
"testonly",
"visibility",
])
deps += public_target_deps
output_dir = target_out_dir
configs += [ "//build/config/zircon:hermetic-code-blob" ]
configs += [ "//build/config/zircon:static-pie-link" ]
configs -= [ "//build/config/zircon:static-pie-link" ]
if (defined(invoker.add_configs)) {
configs += invoker.add_configs
}
ldflags += [ "-Wl,-defsym,HERMETIC_ENTRY=$entrypoint" ]
if (allow_rodata) {
ldflags += [ "-Wl,-defsym,HERMETIC_RODATA_OK=1" ]
}
# This code should use the normal toolchain for its containing environment,
# kernel vs kernel.phys, etc. But it cannot use any fancy variants.
exclude_toolchain_tags += [ "instrumented" ]
}
image_binary(image_target) {
forward_variables_from(invoker,
[
"output_name",
"metadata",
"visibility",
"testonly",
])
deps = [ ":$executable_target" ]
output_dir = target_out_dir
# We expect no dynamic relocations.
pure = true
}
if (public_target_deps != []) {
source_set(public_target) {
forward_variables_from(invoker,
[
"public",
"public_configs",
"public_deps",
"testonly",
"visibility",
])
if (defined(visibility)) {
visibility += [ ":*" ]
}
}
}
}