platform_bionic/linker/Android.bp
Peter Collingbourne c630da5928 Disable Android relocation packing in linker.
Newer versions of lld write ifunc relocations for PLT entries
to .rela.dyn instead of .rela.plt. This causes a problem because
.rela.dyn is subject to Android relocation packing and we don't
support relocation packing when calling the linker's own ifunc
resolvers. Resolve the problem by passing --pack-dyn-relocs=relr
which disables Android relocation packing but keeps RELR packing
enabled which covers most of the relocations in the linker.

With the current toolchain there are only two entries in the linker's
.rela.dyn (and these entries look like a bug anyway) so there should
be no substantial change to binary size as a result of this change.

Relocation section '.rela.dyn' at offset 0x8e8 contains 2 entries:
    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
00000000001691d8  0000000100000401 R_AARCH64_GLOB_DAT     0000000000000000 ZSTD_trace_decompress_begin + 0
00000000001691e0  0000000200000401 R_AARCH64_GLOB_DAT     0000000000000000 ZSTD_trace_decompress_end + 0

Bug: 331450960
Change-Id: Idf403e775d134cbe208d6b1635a84a2a3e70b74b
2024-03-27 18:38:28 -07:00

617 lines
16 KiB
Text

// ========================================================
// linker_wrapper - Linux Bionic (on the host)
// ========================================================
// This is used for bionic on (host) Linux to bootstrap our linker embedded into
// a binary.
//
// Host bionic binaries do not have a PT_INTERP section, instead this gets
// embedded as the entry point, and the linker is embedded as ELF sections in
// each binary. There's a linker script that sets all of that up (generated by
// extract_linker), and defines the extern symbols used in this file.
package {
default_team: "trendy_team_native_tools_libraries",
default_applicable_licenses: ["bionic_linker_license"],
}
license {
name: "bionic_linker_license",
visibility: [":__subpackages__"],
license_kinds: [
"SPDX-license-identifier-BSD",
],
license_text: [
"NOTICE",
],
}
cc_object {
name: "linker_wrapper",
host_supported: true,
device_supported: false,
enabled: false,
target: {
linux_bionic: {
enabled: true,
},
},
cflags: [
"-fno-stack-protector",
"-Wstrict-overflow=5",
"-fvisibility=hidden",
"-Wall",
"-Wextra",
"-Wno-unused",
"-Werror",
],
srcs: [
"linker_wrapper.cpp",
],
arch: {
arm64: {
srcs: ["arch/arm64/linker_wrapper_begin.S"],
},
riscv64: {
srcs: ["arch/riscv64/linker_wrapper_begin.S"],
},
x86_64: {
srcs: ["arch/x86_64/linker_wrapper_begin.S"],
},
},
header_libs: ["libc_headers"],
// We need to access Bionic private headers in the linker.
include_dirs: ["bionic/libc"],
}
// ========================================================
// linker default configuration
// ========================================================
// Configuration for the linker binary and any of its static libraries.
cc_defaults {
name: "linker_defaults",
arch: {
arm: {
cflags: ["-D__work_around_b_24465209__"],
},
x86: {
cflags: ["-D__work_around_b_24465209__"],
},
},
cflags: [
"-fno-stack-protector",
"-Wstrict-overflow=5",
"-fvisibility=hidden",
"-Wall",
"-Wextra",
"-Wunused",
"-Werror",
],
// TODO: split out the asflags.
asflags: [
"-fno-stack-protector",
"-Wstrict-overflow=5",
"-fvisibility=hidden",
"-Wall",
"-Wextra",
"-Wunused",
"-Werror",
],
product_variables: {
debuggable: {
cppflags: ["-DUSE_LD_CONFIG_FILE"],
},
},
cppflags: ["-Wold-style-cast"],
static_libs: [
"libziparchive",
"libbase",
"libz",
"libasync_safe",
"liblog_for_runtime_apex",
],
// We need to access Bionic private headers in the linker.
include_dirs: ["bionic/libc"],
}
// ========================================================
// linker components
// ========================================================
// Enable a module on all targets the linker runs on (ordinary Android targets, Linux Bionic, and
// native bridge implementations).
cc_defaults {
name: "linker_all_targets",
defaults: ["linux_bionic_supported"],
recovery_available: true,
vendor_ramdisk_available: true,
native_bridge_supported: true,
}
cc_library_static {
name: "liblinker_main",
defaults: [
"linker_defaults",
"linker_all_targets",
],
srcs: ["linker_main.cpp"],
// Ensure that the compiler won't insert string function calls before ifuncs are resolved.
cflags: ["-ffreestanding"],
apex_available: [
"com.android.runtime",
],
}
cc_library_static {
name: "liblinker_malloc",
defaults: [
"linker_defaults",
"linker_all_targets",
],
srcs: ["linker_memory.cpp"],
apex_available: [
"com.android.runtime",
],
}
cc_library_static {
name: "liblinker_debuggerd_stub",
defaults: [
"linker_defaults",
"linker_all_targets",
],
srcs: ["linker_debuggerd_stub.cpp"],
}
// ========================================================
// template for the linker binary
// ========================================================
filegroup {
name: "linker_sources",
srcs: [
"dlfcn.cpp",
"linker.cpp",
"linker_auxv.cpp",
"linker_block_allocator.cpp",
"linker_dlwarning.cpp",
"linker_cfi.cpp",
"linker_config.cpp",
"linker_debug.cpp",
"linker_gdb_support.cpp",
"linker_globals.cpp",
"linker_libc_support.c",
"linker_libcxx_support.cpp",
"linker_namespaces.cpp",
"linker_logger.cpp",
"linker_mapped_file_fragment.cpp",
"linker_note_gnu_property.cpp",
"linker_phdr.cpp",
"linker_relocate.cpp",
"linker_sdk_versions.cpp",
"linker_soinfo.cpp",
"linker_transparent_hugepage_support.cpp",
"linker_tls.cpp",
"linker_utils.cpp",
"rt.cpp",
],
}
filegroup {
name: "linker_sources_arm",
srcs: [
"arch/arm/begin.S",
"arch/arm_neon/linker_gnu_hash_neon.cpp",
],
}
filegroup {
name: "linker_sources_arm64",
srcs: [
"arch/arm64/begin.S",
"arch/arm64/tlsdesc_resolver.S",
"arch/arm_neon/linker_gnu_hash_neon.cpp",
],
}
filegroup {
name: "linker_sources_riscv64",
srcs: [
"arch/riscv64/begin.S",
],
}
filegroup {
name: "linker_sources_x86",
srcs: [
"arch/x86/begin.S",
],
}
filegroup {
name: "linker_sources_x86_64",
srcs: [
"arch/x86_64/begin.S",
],
}
cc_defaults {
name: "linker_version_script_overlay",
arch: {
arm: {
version_script: "linker.arm.map",
},
arm64: {
version_script: "linker.generic.map",
},
riscv64: {
version_script: "linker.generic.map",
},
x86: {
version_script: "linker.generic.map",
},
x86_64: {
version_script: "linker.generic.map",
},
},
}
// A template for the linker binary. May be inherited by native bridge implementations.
cc_defaults {
name: "linker_bin_template",
defaults: ["linker_defaults"],
srcs: [":linker_sources"],
arch: {
arm: {
srcs: [":linker_sources_arm"],
// Arm 32 bit does not produce complete exidx unwind information
// so keep the .debug_frame which is relatively small and does
// include needed unwind information.
// See b/242162222 for details.
strip: {
keep_symbols_and_debug_frame: true,
},
},
arm64: {
srcs: [":linker_sources_arm64"],
// Leave the symbols in the shared library so that stack unwinders can produce
// meaningful name resolution.
strip: {
keep_symbols: true,
},
},
riscv64: {
srcs: [":linker_sources_riscv64"],
// Leave the symbols in the shared library so that stack unwinders can produce
// meaningful name resolution.
strip: {
keep_symbols: true,
},
},
x86: {
srcs: [":linker_sources_x86"],
// Leave the symbols in the shared library so that stack unwinders can produce
// meaningful name resolution.
strip: {
keep_symbols: true,
},
},
x86_64: {
srcs: [":linker_sources_x86_64"],
// Leave the symbols in the shared library so that stack unwinders can produce
// meaningful name resolution.
strip: {
keep_symbols: true,
},
},
},
// -shared is used to overwrite the -Bstatic and -static flags triggered by enabling
// static_executable. This dynamic linker is actually a shared object linked with static
// libraries.
ldflags: [
"-shared",
"-Wl,-Bsymbolic",
"-Wl,--exclude-libs,ALL",
"-Wl,-soname,ld-android.so",
// When the linker applies its own IRELATIVE relocations, it will only read DT_REL[A] and
// DT_JMPREL, not DT_ANDROID_REL[A], which can also theoretically contain IRELATIVE
// relocations. lld has been taught to not store them there as a bug workaround (see
// https://llvm.org/pr86751) but the workaround could be removed at some point in the
// future. So we explicitly prevent it from doing so by disabling DT_ANDROID_REL[A] when
// linking the linker (DT_RELR cannot encode IRELATIVE relocations).
"-Wl,--pack-dyn-relocs=relr",
],
// we are going to link libc++_static manually because
// when stl is not set to "none" build system adds libdl
// to the list of static libraries which needs to be
// avoided in the case of building loader.
stl: "none",
// we don't want crtbegin.o (because we have begin.o), so unset it
// just for this module
nocrt: true,
static_executable: true,
// Insert an extra objcopy step to add prefix to symbols. This is needed to prevent gdb
// looking up symbols in the linker by mistake.
prefix_symbols: "__dl_",
sanitize: {
hwaddress: false,
},
static_libs: [
"liblinker_main",
"liblinker_malloc",
"libc++_static",
"libc_nomalloc",
"libc_dynamic_dispatch",
"libm",
"libunwind",
],
// Ensure that if the linker needs __gnu_Unwind_Find_exidx, then the linker will have a
// definition of the symbol. The linker links against libgcc.a, whose arm32 unwinder has a weak
// reference to __gnu_Unwind_Find_exidx, which isn't sufficient to pull in the strong definition
// of __gnu_Unwind_Find_exidx from libc. An unresolved weak reference would create a
// non-relative dynamic relocation in the linker binary, which complicates linker startup.
//
// This line should be unnecessary because the linker's dependency on libunwind_llvm.a should
// override libgcc.a, but this line provides a simpler guarantee. It can be removed once the
// linker stops linking against libgcc.a's arm32 unwinder.
whole_static_libs: ["libc_unwind_static"],
system_shared_libs: [],
// Opt out of native_coverage when opting out of system_shared_libs
native_coverage: false,
}
// ========================================================
// linker[_asan][64] binary
// ========================================================
cc_binary {
name: "linker",
defaults: [
"linker_bin_template",
"linux_bionic_supported",
"linker_version_script_overlay",
],
srcs: [
"linker_translate_path.cpp",
],
symlinks: ["linker_asan"],
arch: {
arm64: {
symlinks: ["linker_hwasan"],
},
},
multilib: {
lib64: {
suffix: "64",
},
},
compile_multilib: "both",
recovery_available: true,
vendor_ramdisk_available: true,
apex_available: [
"//apex_available:platform",
"com.android.runtime",
],
target: {
android: {
srcs: [
"linker_debuggerd_android.cpp",
],
static_libs: [
"libc++demangle",
"libdebuggerd_handler_fallback",
],
},
linux_bionic: {
static_libs: [
"liblinker_debuggerd_stub",
],
},
},
afdo: true,
}
// ========================================================
// assorted modules
// ========================================================
sh_binary {
name: "ldd",
src: "ldd.sh",
}
// Used to generate binaries that can be backed by transparent hugepages.
cc_defaults {
name: "linker_hugepage_aligned",
arch: {
arm64: {
ldflags: ["-z max-page-size=0x200000"],
},
x86_64: {
ldflags: ["-z max-page-size=0x200000"],
},
},
}
cc_library {
// NOTE: --exclude-libs=libgcc.a makes sure that any symbols ld-android.so pulls from
// libgcc.a are made static to ld-android.so. This in turn ensures that libraries that
// a) pull symbols from libgcc.a and b) depend on ld-android.so will not rely on ld-android.so
// to provide those symbols, but will instead pull them from libgcc.a. Specifically,
// we use this property to make sure libc.so has its own copy of the code from
// libgcc.a it uses.
//
// DO NOT REMOVE --exclude-libs!
ldflags: [
"-Wl,--exclude-libs=libgcc.a",
"-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-riscv64-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
"-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
],
// for x86, exclude libgcc_eh.a for the same reasons as above
arch: {
x86: {
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
},
x86_64: {
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
},
},
srcs: ["ld_android.cpp"],
cflags: [
"-Wall",
"-Wextra",
"-Wunused",
"-Werror",
],
stl: "none",
name: "ld-android",
defaults: [
"linux_bionic_supported",
"linker_version_script_overlay",
],
ramdisk_available: true,
vendor_ramdisk_available: true,
recovery_available: true,
native_bridge_supported: true,
nocrt: true,
system_shared_libs: [],
header_libs: ["libc_headers"],
// Opt out of native_coverage when opting out of system_shared_libs
native_coverage: false,
sanitize: {
never: true,
},
apex_available: [
"//apex_available:platform",
"com.android.runtime",
],
}
cc_test {
name: "linker-unit-tests",
test_suites: ["device-tests"],
cflags: [
"-g",
"-Wall",
"-Wextra",
"-Wunused",
"-Werror",
],
// We need to access Bionic private headers in the linker.
include_dirs: ["bionic/libc"],
srcs: [
// Tests.
"linker_block_allocator_test.cpp",
"linker_config_test.cpp",
"linked_list_test.cpp",
"linker_note_gnu_property_test.cpp",
"linker_sleb128_test.cpp",
"linker_utils_test.cpp",
"linker_gnu_hash_test.cpp",
"linker_crt_pad_segment_test.cpp",
// Parts of the linker that we're testing.
":elf_note_sources",
"linker_block_allocator.cpp",
"linker_config.cpp",
"linker_debug.cpp",
"linker_note_gnu_property.cpp",
"linker_test_globals.cpp",
"linker_utils.cpp",
"linker_phdr.cpp",
"linker_mapped_file_fragment.cpp",
"linker_sdk_versions.cpp",
"linker_dlwarning.cpp",
],
static_libs: [
"libasync_safe",
"libbase",
"liblog_for_runtime_apex",
"libprocinfo", // For procinfo::MappedFileSize()
],
data_libs: [
"crt_pad_segment_disabled",
"crt_pad_segment_enabled",
"no_crt_pad_segment",
],
arch: {
arm: {
srcs: ["arch/arm_neon/linker_gnu_hash_neon.cpp"],
},
arm64: {
srcs: ["arch/arm_neon/linker_gnu_hash_neon.cpp"],
},
},
}
cc_benchmark {
name: "linker-benchmarks",
srcs: [
"linker_gnu_hash_benchmark.cpp",
],
arch: {
arm: {
srcs: ["arch/arm_neon/linker_gnu_hash_neon.cpp"],
},
arm64: {
srcs: ["arch/arm_neon/linker_gnu_hash_neon.cpp"],
},
},
}