| # 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/cpp/library_headers.gni") |
| import("//build/cpp/verify_public_symbols.gni") |
| import("//build/toolchain/ifs_extract.gni") |
| import("//build/toolchain/ifs_shared_library.gni") |
| import("//build/toolchain/toolchain_environment.gni") |
| import("//build/toolchain/zircon/user_basic_redirect.gni") |
| |
| # This provides access to additional <lib/ld/...> headers for support code in |
| # the `ld` namespace, which isn't itself part of of the passive ABI. |
| library_headers("headers") { |
| headers = [ |
| "lib/ld/decoded-module-in-memory.h", |
| "lib/ld/decoded-module.h", |
| "lib/ld/diagnostics.h", |
| "lib/ld/load-module.h", |
| "lib/ld/load.h", |
| "lib/ld/memory.h", |
| "lib/ld/tlsdesc.h", |
| ] |
| |
| public_deps = [ |
| ":abi-headers", |
| "//sdk/lib/fit", |
| "//src/lib/symbolizer-markup", |
| "//zircon/kernel/lib/arch:headers", |
| ] |
| |
| if (is_fuchsia) { |
| headers += [ |
| "lib/ld/remote-abi-heap.h", |
| "lib/ld/remote-abi-stub.h", |
| "lib/ld/remote-abi-transcriber.h", |
| "lib/ld/remote-abi.h", |
| "lib/ld/remote-decoded-module.h", |
| "lib/ld/remote-dynamic-linker.h", |
| "lib/ld/remote-load-module.h", |
| "lib/ld/remote-zygote.h", |
| ] |
| |
| public_deps += [ |
| # <lib/ld/remote-decoded-module.h> has `#include <fbl/ref_ptr.h>`. |
| "//zircon/system/ulib/fbl", |
| ] |
| |
| # Make sure that there's no transitive deps on libzircon, so header-only |
| # use of the library doesn't affect dynamic linking dependencies. |
| if (zircon_toolchain == false) { |
| _headers = "" |
| } else { |
| _headers = ":headers" |
| } |
| public_deps += [ |
| "//src/zircon/lib/zircon:headers", |
| "//zircon/system/ulib/zx$_headers", |
| ] |
| } |
| } |
| |
| # This is the linkable target for using the passive ABI. |
| # It gives access to the passive ABI dynamic linkage symbols |
| # and to the header files declaring the `ld::abi` namespace. |
| ifs_shared_library("ld") { |
| abi = "ld.ifs" |
| public_deps = [ ":abi-headers" ] |
| } |
| |
| # This provides access to the <lib/ld/...> headers that specify the passive ABI |
| # defined in the `ld::abi` C++ namespace. |
| library_headers("abi-headers") { |
| headers = [ |
| "lib/ld/abi.h", |
| "lib/ld/module.h", |
| "lib/ld/tls.h", |
| ] |
| |
| public_deps = [ |
| "//sdk/lib/stdcompat", |
| "//src/lib/elfldltl:headers", |
| ] |
| } |
| |
| # This is the SONAME reflecting the passive ABI defined here. |
| # It has to match what's in ld.ifs and in ld::abi::kSoname (<lib/ld/abi.h>). |
| abi_soname = "ld.so.1" |
| config("abi-soname") { |
| ldflags = [ "-Wl,-soname=$abi_soname" ] |
| } |
| |
| config("abi-interp") { |
| ldflags = [ "-Wl,-dynamic-linker=${toolchain_variant.libprefix}$abi_soname" ] |
| } |
| |
| # This provides the __tls_get_addr ABI symbol used by TLS GD accesses when |
| # TLSDESC is not in use. This implementation uses the passive ABI to resolve |
| # references in the initial exec set's static TLS layout. A different |
| # implementation would be required to also support post-startup modules. |
| source_set("static-tls-get-addr") { |
| sources = [ "static-tls-get-addr.cc" ] |
| deps = [ "." ] |
| } |
| |
| # `verify_ld_abi(ld) {}` defines "$ld.verify-abi" to check that the |
| # shared_library(ld) or loadable_module(ld) matches the passive ABI. |
| template("verify_ld_abi") { |
| ld_target = target_name |
| verify_target = "$ld_target.verify-abi" |
| extract_target = "$ld_target.ifs" |
| ifs_file = "$target_out_dir/$extract_target" |
| |
| if (defined(invoker.variant_target)) { |
| # Do variant selection as if for the ld_target, approximately. |
| variant_selection_target = verify_target |
| verify_target += ".variant" |
| variant_target("group") { |
| visibility = [ "./*" ] |
| variant_selector_target_type = invoker.variant_target |
| target_name = variant_selection_target |
| variant_shared_redirection = true |
| data_deps = [ ":$verify_target" ] |
| } |
| } |
| |
| ifs_extract(extract_target) { |
| visibility = [ ":*" ] |
| forward_variables_from(invoker, [ "testonly" ]) |
| outputs = [ ifs_file ] |
| deps = [ ":$ld_target" ] |
| } |
| |
| verify_public_symbols(verify_target) { |
| visibility = [ "./*" ] |
| forward_variables_from(invoker, [ "testonly" ]) |
| deps = [ ":$extract_target" ] |
| current = ifs_file |
| reference = "ld.ifs" |
| library_name = get_label_info(":$ld_target", "label_with_toolchain") |
| } |
| } |
| |
| # There's no real difference between a shared library and a loadable module |
| # with a SONAME, but loadable_module() does its own variant selection. Since |
| # the stub ld.so is really just a data ABI image, there's no meaningful sense |
| # in which it could be in the same variant as its users. |
| loadable_module("ld-stub") { |
| configs += [ |
| "//build/config/fuchsia:no_cpp_standard_library", |
| "//build/config/zircon:nolibc", |
| ":abi-soname", |
| ] |
| deps = [ |
| ":abi", |
| ":tlsdesc.no-gc", |
| ] |
| |
| # Since it has no C++ code (only a data definition), it doesn't really matter |
| # for this to use the user.basic build environment as the startup dynamic |
| # linker must. But we don't want it to have any instrumentation hair that |
| # might be generated even with no C++ functions. |
| exclude_toolchain_tags = [ "instrumented" ] |
| } |
| |
| # This redirects to the user.basic toolchain where ld-stub.so should be built. |
| # It only serves to get it built and reached via data_deps so it will be |
| # included in a package. |
| user_basic_redirect("ld-stub.basic") { |
| public_deps = [ ":ld-stub.verify-abi" ] |
| } |
| |
| verify_ld_abi("ld-stub") { |
| variant_target = "loadable_module" |
| } |
| |
| source_set("abi") { |
| visibility = [ ":*" ] |
| |
| public = [ "mutable-abi.h" ] |
| sources = [ "mutable-abi.cc" ] |
| deps = [ ":headers" ] |
| } |
| |
| source_set("bootstrap") { |
| visibility = [ ":*" ] |
| |
| public = [ "bootstrap.h" ] |
| public_deps = [ |
| ":headers", |
| "//src/lib/elfldltl", |
| |
| # TODO(https://fxbug.dev/42080826): This gets users of bootstrap.h the config that |
| # plumbs the HAVE_LLVM_PROFDATA predefine used there. |
| "//src/lib/llvm-profdata", |
| ] |
| } |
| |
| # This is a proper archive library of the bits from libc and the stubs that can |
| # be used in the standalone implementation. Having the source_set() targets as |
| # direct or transitive deps not via a `complete_static_lib=true` archive would |
| # eagerly link unused code into the standalone binary and rely on linker GC to |
| # remove it, which is suboptimal. |
| static_library("standalone") { |
| visibility = [ "./*" ] |
| |
| complete_static_lib = true |
| |
| sources = [ "standalone-assert.cc" ] |
| deps = [ |
| "//zircon/system/public", |
| "//zircon/system/ulib/c/stdlib:hermetic", |
| "//zircon/system/ulib/c/string:hermetic", |
| ] |
| |
| if (is_linux) { |
| deps += [ ":linux-syscalls" ] |
| } |
| |
| public_configs = [ ":standalone.config" ] |
| } |
| |
| config("standalone.config") { |
| visibility = [ "./*" ] |
| |
| configs = [ "//build/config/zircon:nolibc" ] |
| |
| ldflags = [] |
| if (!is_gcc) { |
| # The standard profiling runtime can't be used in the minimal standalone |
| # context of ld.so. |
| # |
| # TODO(https://fxbug.dev/42080826): The instrumentation works fine to collect data, |
| # but the data needs to be plumbed out somewhere using a custom |
| # runtime. For now, the data is just ignored. |
| ldflags += [ "-noprofilelib" ] |
| } |
| } |
| |
| source_set("posix-header") { |
| public = [ "posix.h" ] |
| public_deps = [ |
| ":startup-load", |
| "//src/lib/elfldltl", |
| ] |
| } |
| |
| source_set("zircon") { |
| public = [ "zircon.h" ] |
| public_deps = [ |
| ":startup-diagnostics", |
| ":startup-load", |
| "//sdk/lib/stdcompat", |
| "//src/lib/elfldltl", |
| ] |
| sources = [ |
| "ldsvc.cc", |
| "procargs.cc", |
| ] |
| deps = [ |
| "//zircon/system/ulib/ldmsg", |
| "//zircon/system/ulib/processargs", |
| "//zircon/system/ulib/zircon-internal", |
| ] |
| |
| # TODO(https://fxbug.dev/42085293): delete the below and fix compiler warnings |
| configs += [ "//build/config:Wno-vla-cxx-extension" ] |
| } |
| |
| source_set("startup-load") { |
| public = [ "startup-load.h" ] |
| public_deps = [ |
| ":abi", |
| ":allocator", |
| ":bootstrap", |
| ":headers", |
| ":startup-diagnostics", |
| "//src/lib/elfldltl", |
| "//zircon/system/ulib/fbl", |
| ] |
| } |
| |
| shared_library("ld-startup") { |
| configs += [ ":abi-soname" ] |
| |
| sources = [] |
| deps = [ |
| ":standalone", |
| ":startup-load", |
| ":tlsdesc", |
| ] |
| |
| if (is_fuchsia) { |
| sources += [ |
| "zircon-startup.S", |
| "zircon-startup.cc", |
| ] |
| deps += [ |
| ":zircon", |
| ":zircon-diagnostics", |
| "//sdk/lib/stdcompat", |
| "//src/lib/llvm-profdata", |
| "//src/zircon/lib/zircon", |
| "//zircon/kernel/lib/arch", |
| "//zircon/system/ulib/zx", |
| ] |
| } else { |
| sources += [ |
| "posix-startup.S", |
| "posix-startup.cc", |
| ] |
| deps += [ |
| ":posix-diagnostics", |
| ":posix-header", |
| "//zircon/kernel/lib/arch:headers", |
| ] |
| |
| # There is no way to get the data out anyway. |
| configs += [ "//build/config:no_profile" ] |
| } |
| |
| output_path = "$root_out_dir/lib$target_name.so" |
| |
| metadata = { |
| distribution_entries = [ |
| { |
| destination = "lib/${toolchain_variant.libprefix}$abi_soname" |
| source = rebase_path(output_path, root_build_dir) |
| label = get_label_info(target_name, "label_with_toolchain") |
| }, |
| ] |
| |
| # This is collected by test:ld-test-switches.rsp. The user_basic_redirect |
| # may wind up in a different variant than the one requested, if the test's |
| # variant isn't available in user.basic, so we don't know statically which |
| # libprefix the test should load from. |
| ld_test_switches = |
| [ "'-DLD_TEST_LIBPREFIX=\"${toolchain_variant.libprefix}\"'" ] |
| } |
| } |
| |
| source_set("startup-diagnostics") { |
| visibility = [ ":*" ] |
| public = [ "startup-diagnostics.h" ] |
| public_deps = [ |
| ":headers", |
| "//src/lib/elfldltl", |
| ] |
| sources = [ "startup-diagnostics.cc" ] |
| } |
| |
| source_set("posix-diagnostics") { |
| visibility = [ ":*" ] |
| sources = [ "posix-diagnostics.cc" ] |
| deps = [ |
| ":posix-header", |
| ":startup-diagnostics", |
| "//zircon/system/ulib/c/stdio:snprintf", |
| "//zircon/system/ulib/c/stdio/printf_core:wrapper", |
| ] |
| } |
| |
| source_set("zircon-diagnostics") { |
| visibility = [ ":*" ] |
| sources = [ "zircon-diagnostics.cc" ] |
| deps = [ |
| ":startup-diagnostics", |
| ":zircon", |
| "//src/lib/symbolizer-markup", |
| "//zircon/system/ulib/c/stdio/printf_core:wrapper", |
| "//zircon/system/ulib/zx", |
| ] |
| } |
| |
| source_set("allocator") { |
| visibility = [ ":*" ] |
| public = [ "allocator.h" ] |
| public_deps = [ |
| ":startup-diagnostics", |
| "//src/lib/trivial-allocator", |
| ] |
| deps = [ "//src/lib/trivial-allocator:stub-delete" ] |
| } |
| |
| source_set("linux-syscalls") { |
| visibility = [ ":*" ] |
| sources = [ "linux-syscalls.cc" ] |
| include_dirs = [ "//third_party/linux-syscall-support/src" ] |
| } |
| |
| # The TLSDESC runtime assembly code is provided in library form as needed for |
| # use by an in-process dynamic linker (ld-startup and libdl). The stub dynamic |
| # linker includes this code but with neither references nor exported symbols, |
| # so it needs a mandatory-linked version of the code that's immune to GC. |
| template("_tlsdesc_runtime") { |
| target(invoker.target_type, target_name) { |
| public_deps = [ |
| ":headers", |
| "//zircon/kernel/lib/arch", |
| ] |
| sources = [ |
| "tlsdesc-runtime-static.S", |
| "tlsdesc-runtime-undefined-weak.S", |
| ] |
| defines = [ "TLSDESC_RETAIN=${invoker.retain}" ] |
| } |
| } |
| |
| _tlsdesc_runtime("tlsdesc") { |
| target_type = "static_library" |
| retain = "" |
| } |
| |
| _tlsdesc_runtime("tlsdesc.no-gc") { |
| target_type = "source_set" |
| retain = "R" |
| } |
| |
| user_basic_redirect("ld-startup.basic") { |
| public_deps = [ ":ld-startup" ] |
| } |
| |
| # This is reached from test:ld-startup.test-data, where it will be instantiated |
| # in each environment and variant for which any tests are built. |
| verify_ld_abi("ld-startup") { |
| } |
| |
| group("tests") { |
| testonly = true |
| |
| deps = [ |
| ":ld-stub.basic", # This just gets it built and its ABI verified. |
| "test:tests", |
| ] |
| } |