From 6c72e46bff8a33df3ab2122e12388ef828ca3b07 Mon Sep 17 00:00:00 2001 From: Roland McGrath <mcgrathr@google.com> Date: Sat, 27 Apr 2019 00:31:42 +0000 Subject: [PATCH] [build][ldso] Use libprefix for all instrumented variants Also add an explicit option in environment() to enable a per-variant libprefix in all variants of a toolchain (or none). By default, each variant that has the "instrumented" tag gets "$variant/" appended to its ${toolchain.libprefix} value. Remove the "asan" variant's explicit toolchain_vars.libprefix setting, which is now redundant. The dynamic linker is compiled to request the libprefix from the loader service, and all executables have the prefixed name in PT_INTERP so they get the same variant's dynamic linker. Bug: BLD-429 #done Bug: ZX-3624 #done Change-Id: Ia74bc8d449aa6ce3ded00df8940b057e790486f4 --- zircon/public/gn/config/BUILD.gn | 16 +++-- zircon/public/gn/config/standard.gni | 3 - zircon/public/gn/toolchain/environment.gni | 69 +++++++++++++-------- zircon/third_party/ulib/musl/ldso/BUILD.gn | 7 +++ zircon/third_party/ulib/musl/ldso/dynlink.c | 5 ++ 5 files changed, 67 insertions(+), 33 deletions(-) diff --git a/zircon/public/gn/config/BUILD.gn b/zircon/public/gn/config/BUILD.gn index f7ccccbb3a8..23665bc2dac 100644 --- a/zircon/public/gn/config/BUILD.gn +++ b/zircon/public/gn/config/BUILD.gn @@ -520,11 +520,17 @@ config("user_executable") { compiler_flags = [ "-fPIE" ] asmflags = compiler_flags cflags = compiler_flags - ldflags = compiler_flags - ldflags += [ - "-Wl,-pie", - "-Wl,-dynamic-linker,ld.so.1", - ] + ldflags = compiler_flags + [ "-Wl,-pie" ] + } else { + ldflags = [] + } + + # Specify the dynamic linker if building a variant that uses a separate + # set of libraries. With GCC, the dynamic linker must be explicit even + # in the default case because the compiler driver is not inherently + # configured for Fuchsia as it is in Clang. + if (is_gcc || toolchain.libprefix != "") { + ldflags += [ "-Wl,-dynamic-linker,${toolchain.libprefix}ld.so.1" ] } } diff --git a/zircon/public/gn/config/standard.gni b/zircon/public/gn/config/standard.gni index dd303222d56..9ea36bf1f7b 100644 --- a/zircon/public/gn/config/standard.gni +++ b/zircon/public/gn/config/standard.gni @@ -233,9 +233,6 @@ standard_variants = [ add = [ "$zx/system/core/devmgr:driver_deps.$name" ] }, ] - toolchain_vars = { - libprefix = "asan/" - } tags = [ "instrumented", "useronly", diff --git a/zircon/public/gn/toolchain/environment.gni b/zircon/public/gn/toolchain/environment.gni index 6acbdf2dfb6..13ee1b9ba23 100644 --- a/zircon/public/gn/toolchain/environment.gni +++ b/zircon/public/gn/toolchain/environment.gni @@ -38,19 +38,21 @@ declare_args() { # Selector scope parameters # # * variant - # - Required: The variant to use when this selector matches. If this is a - # string then it must match a fully-defined variant elsewhere in the - # list (or in $default_variants + $standard_variants, which is appended - # implicitly to the $variants list). If it's a scope then it defines a - # new variant (see details below). + # - Required: The variant to use when this selector matches. If this + # is a string then it must match a fully-defined variant elsewhere in + # the list (or in $default_variants + $standard_variants, which is + # appended implicitly to the $variants list). If it's a scope then + # it defines a new variant (see details below). # - Type: string or scope, described below # # * cpu - # - Optional: If nonempty, match only when $current_cpu is one in the list. + # - Optional: If nonempty, match only when $current_cpu is one in the + # - list. # - Type: list(string) # # * os - # - Optional: If nonempty, match only when $current_os is one in the list. + # - Optional: If nonempty, match only when $current_os is one in the + # - list. # - Type: list(string) # # * host @@ -82,8 +84,9 @@ declare_args() { # - Type: list(string) # # * target_type - # - Optional: If nonempty, a list of target types to match. This is one of - # "executable", "host_tool", "loadable_module", "driver", or "test". + # - Optional: If nonempty, a list of target types to match. This is + # one of "executable", "host_tool", "loadable_module", "driver", or + # "test". # Note, test_driver() matches as "driver". # - Type: list(string) # @@ -106,9 +109,10 @@ declare_args() { # - Type: list(label_no_toolchain) # # * output_name - # - Optional: If nonempty, match only when the `output_name` of the target - # is one in the list. Note `output_name` defaults to `target_name`, - # and does not include prefixes or suffixes like ".so" or ".exe". + # - Optional: If nonempty, match only when the `output_name` of the + # target is one in the list. Note `output_name` defaults to + # `target_name`, and does not include prefixes or suffixes like ".so" + # or ".exe". # - Type: list(string) # # An element with a scope for `.variant` defines a new variant. Each @@ -297,14 +301,23 @@ declare_args() { # This is just like $toolchain_args passed to toolchain() in bare GN. # # * toolchain_vars -# - Optional: A scope imported into the $toolchain scope in these toolchains. -# This can store useful toolchain-specific variables that should be -# available within the toolchain. $toolchain automatically contains -# `tool_dir`, `tool_prefix`, `cc, and `cxx`, from c_toolchain(). -# If `variant_suffix` is defined here, terminal targets in the environment -# will have "$target_name$variant_suffix" aliases that get the same thing -# but in that particular variant installed under the suffixed name. -# The default `variant_suffix` is ".$variant" in each variant. +# - Optional: A scope imported into the $toolchain scope in these +# toolchains. This can store useful toolchain-specific variables that +# should be available within the toolchain. $toolchain automatically +# contains `tool_dir`, `tool_prefix`, `cc, and `cxx`, from +# c_toolchain(). If `variant_suffix` is defined here, terminal targets +# in the environment will have "$target_name$variant_suffix" aliases +# that get the same thing but in that particular variant installed +# under the suffixed name. The default `variant_suffix` is ".$variant" +# in each variant. +# +# * variant_libprefix +# - Optional: If true, each variant's name is used to form the +# ${toolchain.libprefix} value in that variant. The final libprefix +# is "${toolchain_vars.libprefix}${toolchain.variant}/". By default, +# this is true *only* in variants that have the "instrumented" tag. +# If explicitly set to true or false, that applies to *all* variants. +# - Type: bool # # * variant_selectors # - Optional: A list in the schema of the $variants build argument. This @@ -324,7 +337,7 @@ declare_args() { # .variant scope. If any of these strings appears in a .variant scope, # then $variant_selectors elements using that variant will be silently # ignored in this environment's toolchains. e.g. an environment that is -# incompatbile with instrumentation could list the "instrumentation" tag +# incompatbile with instrumentation could list the "instrumented" tag # and variants that enable instrumentation will be defined with that tag. # Then simple `variants=["asan"]` user configurations that would apply # ordinarily to all targets don't break the special-case execution @@ -905,15 +918,21 @@ template("environment") { # `variant`, so it can't be used any more in this block.) variant = variant.name + if (!defined(libprefix)) { + libprefix = "" + } + if ((defined(invoker.variant_libprefix) && + invoker.variant_libprefix) || + (!defined(invoker.variant_libprefix) && + tags + [ "instrumented" ] - [ "instrumented" ] != tags)) { + libprefix += "$variant/" + } + # Plumb through the suffix of this variant and the list of others. if (!defined(variant_suffix)) { variant_suffix = ".$variant" } - if (!defined(libprefix)) { - libprefix = "" - } - other_variants = [] foreach(other_variant, toolchain_variants) { if (other_variant.name != variant) { diff --git a/zircon/third_party/ulib/musl/ldso/BUILD.gn b/zircon/third_party/ulib/musl/ldso/BUILD.gn index 71b4c4da4c6..493979e2840 100644 --- a/zircon/third_party/ulib/musl/ldso/BUILD.gn +++ b/zircon/third_party/ulib/musl/ldso/BUILD.gn @@ -13,4 +13,11 @@ source_set("ldso") { "dynlink-sancov.S", "dynlink.c", ] + if (toolchain.libprefix != "") { + # The libprefix always ends with a / but that's not part of the + # "config" string in the loader-service protocol. + ldsvc_config = get_path_info("${toolchain.libprefix}libfoo.so", "dir") + assert(ldsvc_config != "" && ldsvc_config != ".") + defines = [ "DYNLINK_LDSVC_CONFIG=\"$ldsvc_config\"" ] + } } diff --git a/zircon/third_party/ulib/musl/ldso/dynlink.c b/zircon/third_party/ulib/musl/ldso/dynlink.c index ee8d26fad67..bf724807676 100644 --- a/zircon/third_party/ulib/musl/ldso/dynlink.c +++ b/zircon/third_party/ulib/musl/ldso/dynlink.c @@ -2090,6 +2090,11 @@ __NO_SAFESTACK NO_ASAN static dl_start_return_t __dls3(void* start_arg) { __NO_SAFESTACK NO_ASAN static void early_init(void) { #if __has_feature(address_sanitizer) __asan_early_init(); +#endif +#ifdef DYNLINK_LDSVC_CONFIG + // Inform the loader service to look for libraries of the right variant. + loader_svc_config(DYNLINK_LDSVC_CONFIG); +#elif __has_feature(address_sanitizer) // Inform the loader service that we prefer ASan-supporting libraries. loader_svc_config("asan"); #endif -- GitLab