blob: 4990c58e4118ad0e98245e4302d9f05bc362d732 [file] [log] [blame]
# Copyright 2025 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")
import("//src/zircon/lib/zircon/libzircon.gni")
import("../libc.gni")
libc_source_set("startup") {
sources = []
libc_deps = [
":processargs-preinit",
":start-main",
":startup-random-impl",
]
}
libc_test("unittests") {
sources = []
}
# These are referenced by StartCompilerAbi in one basic_abi libc_source_set()
# and defined in a different basic_abi libc_source_set() for modularity.
startup_relocate_symbols = [
"${libc_namespace}_StartupRelocate",
"${libc_namespace}_StartupProtectRelro",
]
libc_source_set("shared-only") {
visibility = [ "..:*" ]
basic_abi = true
global_symbols = startup_relocate_symbols
sources = [ "stub-relocate.cc" ]
deps = [ ":headers" ]
}
libc_source_set("static-only") {
visibility = [ "..:*" ]
sources = []
libc_deps = [
":crt1",
":static-pie-relocate",
]
}
libc_source_set("static-pie-relocate") {
visibility = [ ":*" ]
basic_abi = true
global_symbols = startup_relocate_symbols + [ "_ld_abi" ]
undefined_symbols = [
"${libc_namespace}_gLog",
# These will be defined implicitly by the linker in the outer link.
"_DYNAMIC",
"_GLOBAL_OFFSET_TABLE_",
"__ehdr_start",
"_end",
]
# All the vDSO's symbols are safe since it uses only the basic ABI anyway.
undefined_symbols += libzircon_linkage_names
sources = [ "static-pie-relocate.cc" ]
libc_deps = [ "../ld:log-panic" ]
deps = [
":headers",
"//sdk/lib/ld:headers",
"//src/lib/elfldltl:hermetic",
]
}
# This doesn't go into libc, but becomes the Scrt1.o linked into executables.
# It defines the _start entry point symbol the linker looks for, and calls
# __libc_start_main using only the basic machine ABI.
libc_source_set("crt1") {
visibility = [ ":*" ]
# This doesn't really need to be in an hermetic_source_set() or redirect to
# the user.basic environment, because it's just assembly code anyway. But
# doing so does the explicit check on what it's defining and referencing, and
# also gives the output .o file a well-known path that can be copied around.
basic_abi = true
global_symbols = [ "_start" ]
undefined_symbols = [
"__libc_start_main",
"main",
]
sources = [ "crt1.S" ]
deps = [ "//zircon/kernel/lib/arch:headers" ]
objfile_metadata = {
libc_startfiles =
[ rebase_path("$target_out_dir/$target_name.o", root_build_dir) ]
}
}
# This will be a response file of the path for the right user.basic toolchain's
# $target_out_dir/crt1.o relative to $root_build_dir.
crt1_rspfile = "$target_gen_dir/crt1.rsp"
# The sysroot setup depends on this to populate the sysroot's crt1 file, and
# direct dependents know the $outputs path to use as an input file. It
# provides transitive order-only deps on getting the real crt1.o built too,
# though it doesn't directly contribute any link inputs by being in deps. This
# will be instantiated in every toolchain that needs a sysroot.
toolchain_utils_action("startfiles") {
visibility = [
"//zircon/public/sysroot/*",
"//zircon/public/sysroot_sdk/*",
]
sysroot_gen_dir = get_label_info("//zircon/public/sysroot", "target_gen_dir")
outputs = [ "$sysroot_gen_dir/lib/Scrt1.o" ]
# toolchain_utils_action() is really only being used here for its response
# file expansion, which a copy() target can't do. No actual utils are
# needed, so there's no implied PROGRAM argument and instead ln is the
# program and found in the PATH. Since it's a fundamental system command,
# there's no need for GN/Ninja to know about a dependency on it as with the
# toolchain utilities or scripts.
utils = []
script = true
deps = [ ":crt1.rsp" ]
args = [
"ln",
"-f",
"@" + rebase_path(crt1_rspfile, root_build_dir),
rebase_path(outputs[0], root_build_dir),
]
}
# This collects metadata to produce $crt1_rspfile. The crt1.basic.objfile
# redirect propagates the order-only build deps along with the metadata.
generated_file("crt1.rsp") {
visibility = [ ":*" ]
outputs = [ crt1_rspfile ]
output_conversion = "list lines"
data_keys = [ "libc_startfiles" ]
deps = [ ":crt1.basic.objfile" ]
}
# Add this to deps when using -nostartfiles to get a link input for libc's
# startfiles that acts like it was first in the link as default startfiles are.
user_basic_redirect("nostartfiles") {
public_deps = [ ":nostartfiles.basic" ]
}
# The subtargets are reached via the :nostartfiles redirect, so they're in the
# same toolchain where the $target_out_dir/crt1.o is actually built. This
# input linker script finds that with a path relative to the script's own
# location, but marked to tell the linker to move it first in the link order as
# the sysroot's crt1 would be without -nostartfiles.
generated_file("nostartfiles.ldscript") {
visibility = [ ":nostartfiles.basic" ]
outputs = [ "$target_gen_dir/nostartfiles.ld" ]
output_conversion = "list lines"
_label = get_label_info(":$target_name", "label_with_toolchain")
_crt1_path = rebase_path("$target_out_dir/crt1.o", target_gen_dir)
contents = [
"/* Generated by $_label. DO NOT EDIT!",
" * This is used as an explicit link input when using -nostartfiles.",
" */",
"STARTUP($_crt1_path)",
]
# Propagate order-only deps on the referenced file. The linker depfile will
# track it for triggering relinks, so it doesn't need to be a declared input.
data_deps = [ ":crt1.objfile" ]
}
# This is reached by the user_basic_redirect() to make that a link input.
basic_source_set("nostartfiles.basic") {
visibility = [ ":*" ]
# This is required in deps to use the generated_file() output as an input via
# libs, but also serves to propagate the order-only deps on crt1.objfile so
# the underlying file gets built (and triggers relinks via depfile).
deps = [ ":nostartfiles.ldscript" ]
libs = get_target_outputs(deps[0])
}
# The headers for the things used across hermetic boundaries are in this
# separate headers-only target to avoid deps from any hermetic_source_set() to
# any other targets providing link inputs. Each hermetic_source_set() can have
# its own `public` list if it's in deps of other non-hermetic targets. But no
# hermetic_source_set()'s own deps list can need to include any code targets
# that don't go into the same hermetic partial link.
source_set("headers") {
visibility = [ "../*" ]
public = [
"start-main.h",
"startup-relocate.h",
"startup-trampoline.h",
]
public_deps = [
"../zircon:vmar.headers",
"//zircon/system/ulib/zx",
]
deps = [ "..:asm-linkage" ]
}
# :startup-random-impl is a basic ABI hermetic_source_set() defining this
# symbol. It's directly in deps of :startup to get into the outer link. The
# symbol will be used by other basic ABI hermetic partial link targets but they
# don't have deps on :startup-random-impl to get it into each hermetic link.
# If they did, those hermetic links would need to include the undefined_symbols
# list here and wouldn't distinguish where the references came from. Instead,
# they just need to add startup_random_symbols to undefined_symbols and the
# expected references from startup-random.cc are checked by each separate
# hermetic link. Both hermetic and non-hermetic users of startup-random.h need
# deps on :startup-random just for the header visibility.
startup_random_symbols = [ "${libc_namespace}_InitStartupRandom" ]
source_set("startup-random") {
visibility = [ "../*" ]
public = [ "startup-random.h" ]
deps = [ "..:asm-linkage" ]
}
libc_source_set("startup-random-impl") {
visibility = [ ":startup" ]
# This is called too early in startup to use the compiler ABI.
basic_abi = true
global_symbols = startup_random_symbols
# These will be defined implicitly by the linker in the outer link.
undefined_symbols = [
"__start_${libc_namespace}_StartupRandom",
"__stop_${libc_namespace}_StartupRandom",
]
# All the vDSO's symbols are safe since it uses only the basic ABI anyway.
undefined_symbols += libzircon_linkage_names
# This helps the legacy C code call the function declared only in C++.
public_configs = [ ":startup-random.musl-glue" ]
visibility += [ "//zircon/third_party/ulib/musl/src/env:start-main" ]
sources = [ "startup-random.cc" ]
deps = [
":startup-random",
"//sdk/lib/ld:headers",
"//src/zircon/lib/zircon:zircon.as-needed",
]
}
config("startup-random.musl-glue") {
visibility = [ ":*" ]
defines = [ "__libc_init_randoms=${startup_random_symbols[0]}" ]
}
# These parts go into libc: __libc_start_main and its call graph.
libc_source_set("startup-trampoline") {
visibility = [ ":*" ]
public_deps = [ ":headers" ]
basic_abi = true
global_symbols = [ "__libc_start_main" ]
undefined_symbols = [
"${libc_namespace}_SetStartHandles",
"${libc_namespace}_gLog",
"${libc_namespace}_start_main",
"_zx_startup_get_handles",
] + startup_relocate_symbols + startup_random_symbols +
libzircon_linkage_names
undefined_symbols += [
# TODO(https://fxbug.dev/342469121): These won't be used anymore when
# ../threads:musl-tls is removed.
"${libc_namespace}_GetTlsLayout",
"${libc_namespace}_InitializeTls",
# TODO(https://fxbug.dev/342469121): This won't be used anymore when
# :musl-glue is removed.
"${libc_namespace}_InitialStackSize",
]
sources = [ "startup-trampoline.S" ]
libc_deps = [
":start-compiler-abi",
"../ld:log-panic",
]
deps = [
"..:asm-linkage",
"//zircon/kernel/lib/arch",
]
}
libc_source_set("start-compiler-abi") {
visibility = [ ":*" ]
public_deps = [ ":headers" ]
sources = [ "start-compiler-abi.cc" ]
deps = [
":startup-random",
"../ld:log.headers",
"../threads:shadow-call-stack",
"../threads:thread-storage",
"//zircon/system/ulib/runtime:headers",
"//zircon/system/ulib/zx",
"//zircon/third_party/ulib/musl:musl_internal",
]
}
# This the second half of __libc_start_main, outside the basic_abi bubble.
# It's called by :startup-trampoline, but the deps go the other way, since
# that target needs hermeticity that this target doesn't.
libc_source_set("start-main") {
visibility = [ ":*" ]
public_deps = [ ":headers" ]
sources = [ "start-main.cc" ]
deps = [
":startup-trampoline",
"../stdlib:exit",
"../threads:thread-list",
"//sdk/lib/ld:fuchsia-debugdata",
"//zircon/system/ulib/runtime",
"//zircon/third_party/ulib/musl:musl_internal",
]
}
# This is used in the first half of __libc_start_main, in the basic ABI.
libc_source_set("processargs-get-handles") {
visibility = [ ":*" ]
public = [ "processargs.h" ]
public_deps = [
":headers",
"..:asm-linkage",
"//sdk/lib/ld:processargs",
"//zircon/system/ulib/zx",
]
basic_abi = true
global_symbols = [
"${libc_namespace}_ProcessargsGetHandles",
"_zx_startup_get_handles",
]
undefined_symbols = libzircon_linkage_names + [
"${libc_namespace}_gLog",
"__libc",
]
sources = [ "processargs-get-handles.cc" ]
libc_deps = [
"../ld:log-panic",
"../zircon:vmar",
]
deps = [
"//sdk/lib/ld:processargs",
"//zircon/system/ulib/zircon-internal",
]
configs = [ "//build/config:Wno-vla-cxx-extension" ]
}
# This is used in the second half of __libc_start_main, with the full ABI.
libc_source_set("processargs-preinit") {
visibility = [ ":*" ]
sources = [ "processargs-preinit.cc" ]
libc_deps = [ ":processargs-get-handles" ]
deps = [
"..:weak",
"../ld:log.headers",
"//zircon/third_party/ulib/musl:musl_internal",
]
}