blob: 29b78c7bffd1cb7635328334eeb79ef1ad19f597 [file] [log] [blame]
# Copyright 2019 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("$zx/public/gn/toolchain/c_utils.gni")
import("$zx/public/gn/toolchain/environment_redirect.gni")
import("$zx/public/gn/zbi.gni")
zx_library("userabi") {
kernel = true
sources = []
public_deps = [
# <lib/userabi/userboot.h> has #include <lib/instrumentation/vmo.h>.
"$zx/kernel/lib/instrumentation:headers",
]
if (is_kernel) {
deps = [
":userboot",
":vdso",
"$zx/kernel/lib/instrumentation",
]
public_configs = [ ":vdso-valid-sysret" ]
public_deps += [
# Dependents can use the generated header via $public_configs
# (above), and so need to depend on the generation action.
":gen-vdso-valid-sysret",
# <lib/userabi/rodso.h> has #include <object/handle.h>.
"$zx/kernel/object",
]
} else {
# Our own embedded "user" code needs some shared headers.
visibility = [
"./*",
"$zx/system/ulib/zircon/*",
]
}
}
# Embed an RODSO layout object and extract address constants from it.
#
# The userboot loadable_module() and the vdso (libzircon) shared_library()
# both use the special RODSO layout (by default in lld or via rodso.ld in
# gold). The kernel needs to use address constants extracted from these
# ELF files' headers and symbols.
#
# This generates three targets:
# * "$target_name-code.h" generates the eponymous header in $target_gen_dir
# * "$target_name.rsp" generates the eponymous link_output_rspfile()
# * "$target_name.image" is a source_set() to embed the image in the kernel
#
# Parameters
#
# name
# - Required: "USERBOOT" or "VDSO", used in generated macro names
# - Type: string
#
# deps
# - Required; Should reach the loadable_module() or library() target
# and no other linking targets; see link_output_rspfile().
# - Type: list(label)
#
# writable
# - Optional: Writable segments allowed (not for userboot or vDSO!).
# - Type: bool
# - Default: false
#
template("rodso") {
rspfile_target = "$target_name.rsp"
rspfile = "$target_gen_dir/$rspfile_target"
link_output_rspfile(rspfile_target) {
forward_variables_from(invoker,
[
"deps",
"testonly",
"visibility",
])
outputs = [ rspfile ]
}
if (is_kernel) {
# This generated header file tells the kernel code where the segment
# boundaries and entry points are.
header_target = "$target_name-code.h"
header = "$target_gen_dir/$header_target"
toolchain_utils_action(header_target) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
deps = [ ":$rspfile_target" ]
outputs = [ header ]
depfile = "$header.d"
script = "gen-rodso-code.sh"
utils = [
"nm",
"readelf",
]
sources = [ rspfile ]
args = [
"--depfile",
rebase_path(depfile, root_build_dir),
rebase_path(header, root_build_dir),
]
if (defined(invoker.writable) && invoker.writable) {
args += [ "--writable" ]
}
args += [
invoker.name,
"@" + rebase_path(rspfile, root_build_dir),
]
metadata = {
generated_sources = rebase_path(outputs, root_build_dir)
# Prevent deps from propagating up to code that uses this action.
manifest_barrier = []
}
}
# Embed the image itself.
rodso_name = target_name
source_set("$target_name.image") {
visibility = [ ":*" ]
sources = [ "$target_gen_dir/$target_name.S" ]
# The generated header is also needed to tell .incbin how much of the
# image file to embed (see rodso-asm.h).
header = rebase_path(header, target_gen_dir)
include_dirs = [
target_gen_dir,
".",
]
deps = [ ":$header_target" ]
# $target_name.S includes the image contents and so must be
# reassembled when that changes. We can't express that in $inputs here
# because we don't know the exact name of the file since that depends
# on the toolchain selected. Fortunately, we already depend on the
# generated $header, which is always regenerated whenever the image
# binary itself changes. So this indirect dependency is sufficient.
if (defined(invoker.writable) && invoker.writable) {
code_or_data = "DATA"
} else {
code_or_data = "CODE"
}
write_file(sources[0],
[
"#include \"rodso-asm.h\"",
"#include \"$header\"",
"RODSO_IMAGE($rodso_name, ${invoker.name}, $code_or_data)",
])
}
} else {
not_needed(invoker, [ "name" ])
}
}
# Redirect to the userland vDSO shared library target.
environment_redirect("userland-vdso") {
visibility = [ ":*" ]
environment_label = "$zx/public/gn/toolchain:user"
deps = [ "$zx/system/ulib/zircon" ]
}
rodso("vdso") {
visibility = [ "./*" ]
name = "VDSO"
deps = [ ":userland-vdso" ]
}
if (is_kernel) {
# Support for loading embedded ELF files, used for both vdso and userboot.
source_set("rodso") {
visibility = [ ":*" ]
sources = [ "rodso.cc" ]
deps = [
":headers",
"$zx/kernel/vm:headers",
]
}
# Initializing, supporting, and validating the vDSO itself.
source_set("vdso") {
visibility = [ ":*" ]
sources = [ "vdso.cc" ]
deps = [
":headers",
":rodso",
":vdso-code.h",
":vdso.image",
"$zx/kernel/lib/cmdline",
"$zx/kernel/lib/syscalls",
"$zx/kernel/lib/version",
"$zx/kernel/vm:headers",
"$zx/system/ulib/affine",
"$zx/system/ulib/fbl",
]
}
config("vdso-valid-sysret") {
visibility = [ ":*" ]
include_dirs = [ target_gen_dir ]
}
action("gen-vdso-valid-sysret") {
visibility = [ ":*" ]
script = "gen-vdso-valid-sysret.sh"
deps = [ ":vdso-code.h" ]
sources = get_target_outputs(":vdso-code.h")
outputs = [ "$target_gen_dir/vdso-valid-sysret.h" ]
args = rebase_path(sources + outputs)
}
group("vdso-code-header") {
deps = [ ":vdso-code.h" ]
public_configs = [ ":vdso-code-header.config" ]
# The following metadata allows the vDSO header to be exposed to the GN
# build under //zircon/public/lib/vdso-code-header.
metadata = {
legacy_barrier = []
legacy_dirs = [ "lib/vdso-code-header" ]
legacy_targets = [
{
_zircon_public = "lib"
import = "//build/zircon/zircon_library.gni"
target_type = "zircon_library"
target_name = "vdso-code-header"
include_dirs = [ target_gen_dir ]
compilation_include_dirs = []
compilation_defines = []
disable_ubsan = false
headers = [ "$target_gen_dir/vdso-code.h" ]
publishable = false
sources = []
deps = []
public_deps = []
install = []
debug = []
}
]
}
}
config("vdso-code-header.config") {
visibility = [ ":vdso-code-header" ]
include_dirs = [ target_gen_dir ]
}
decompress_zbi = zbi_compression_algorithm != "none"
# Loading and launching userboot, which loads and launches "real" userland.
source_set("userboot") {
visibility = [ ":*" ]
sources = [ "userboot.cc" ]
include_dirs = [ target_gen_dir ]
deps = [
":headers",
":rodso",
":userboot-code.h",
":userboot.image",
"$zx/kernel/lib/cmdline",
"$zx/kernel/lib/console",
"$zx/kernel/lib/counters",
"$zx/system/ulib/elf-psabi",
"$zx/system/ulib/zircon-internal",
]
if (decompress_zbi) {
defines = [ "DECOMPRESS_ZBI" ]
deps += [
":decompress_zbi-code.h",
":decompress_zbi.image",
]
}
}
rodso("userboot") {
visibility = [ ":*" ]
name = "USERBOOT"
deps = [ "userboot" ]
}
if (zbi_compression_algorithm != "none") {
rodso("decompress_zbi") {
visibility = [ ":*" ]
name = "DECOMPRESS_ZBI"
deps = [ "$zx/system/ulib/hermetic-decompressor:decompress-$zbi_compression_algorithm" ]
# It's hermetic, but it's allowed to have data and bss.
writable = true
}
}
}