ro updated this revision to Diff 307067. ro added a comment. Herald added a project: LLVM.
- Move declarations to new `sanitizer_solaris.h`. - Augment `check_linker_flag` do reject unknown `-z` options that GNU ld noisily accepts. Tested on `amd64-pc-solaris2.11`, `sparcv9-sun-solaris2.11`, and `x86_64-pc-linux-gnu`. `CMakeCache.txt` was unchanged on Solaris, while `LINKER_SUPPORTS_Z_RELAX_TRANSTLS` is now false on Linux, both for stage 1 and 2. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D91605/new/ https://reviews.llvm.org/D91605 Files: clang/include/clang/Config/config.h.cmake clang/lib/Driver/ToolChains/Solaris.cpp clang/tools/driver/CMakeLists.txt compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp compiler-rt/lib/sanitizer_common/sanitizer_solaris.h llvm/cmake/modules/CheckLinkerFlag.cmake
Index: llvm/cmake/modules/CheckLinkerFlag.cmake =================================================================== --- llvm/cmake/modules/CheckLinkerFlag.cmake +++ llvm/cmake/modules/CheckLinkerFlag.cmake @@ -1,6 +1,10 @@ -include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) function(check_linker_flag flag out_var) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${flag}") - check_cxx_compiler_flag("" ${out_var}) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}") + # GNU ld accepts every -z option, warning if it isn't supported, e.g. + # /usr/bin/ld: warning: -z relax=transtls ignored + check_cxx_source_compiles("int main() { return 0; }" ${out_var} FAIL_REGEX "warning: -z.* ignored") + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) endfunction() Index: compiler-rt/lib/sanitizer_common/sanitizer_solaris.h =================================================================== --- /dev/null +++ compiler-rt/lib/sanitizer_common/sanitizer_solaris.h @@ -0,0 +1,63 @@ +//===-- sanitizer_solaris.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of Sanitizer runtime. It contains Solaris-specific +// definitions. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_SOLARIS_H +#define SANITIZER_SOLARIS_H + +#include "sanitizer_internal_defs.h" + +#if SANITIZER_SOLARIS + +#include <link.h> + +namespace __sanitizer { + +// Beginning of declaration from OpenSolaris/Illumos +// $SRC/cmd/sgs/include/rtld.h. +struct Rt_map { + Link_map rt_public; + const char *rt_pathname; + ulong_t rt_padstart; + ulong_t rt_padimlen; + ulong_t rt_msize; + uint_t rt_flags; + uint_t rt_flags1; + ulong_t rt_tlsmodid; +}; + +// Structure matching the Solaris 11.4 struct dl_phdr_info used to determine +// presence of dlpi_tls_modid field at runtime. Cf. Solaris 11.4 +// dl_iterate_phdr(3C), Example 2. +struct dl_phdr_info_test { + ElfW(Addr) dlpi_addr; + const char *dlpi_name; + const ElfW(Phdr) * dlpi_phdr; + ElfW(Half) dlpi_phnum; + u_longlong_t dlpi_adds; + u_longlong_t dlpi_subs; + size_t dlpi_tls_modid; + void *dlpi_tls_data; +}; + +struct TLS_index { + unsigned long ti_moduleid; + unsigned long ti_tlsoffset; +}; + +extern "C" void *__tls_get_addr(TLS_index *); + +} // namespace __sanitizer + +#endif // SANITIZER_SOLARIS + +#endif // SANITIZER_SOLARIS_H Index: compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -27,6 +27,7 @@ #include "sanitizer_linux.h" #include "sanitizer_placement_new.h" #include "sanitizer_procmaps.h" +#include "sanitizer_solaris.h" #if SANITIZER_NETBSD #define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast() @@ -57,6 +58,7 @@ #endif #if SANITIZER_SOLARIS +#include <stddef.h> #include <stdlib.h> #include <thread.h> #endif @@ -451,6 +453,39 @@ void **); #endif +#if SANITIZER_SOLARIS +// dlpi_tls_modid is only available since Solaris 11.4 SRU 10. Use +// dlinfo(RTLD_DI_LINKMAP) instead which works on both Solaris 11.3 and Illumos. + +static size_t main_tls_modid; + +int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) { + const ElfW(Phdr) *hdr = info->dlpi_phdr; + const ElfW(Phdr) *last_hdr = hdr + info->dlpi_phnum; + + // With the introduction of dlpi_tls_modid, the tlsmodid of the executable + // was changed to 1 to match other implementations. + if (size >= offsetof(dl_phdr_info_test, dlpi_tls_modid)) + main_tls_modid = 1; + else + main_tls_modid = 0; + + for (; hdr != last_hdr; ++hdr) { + if (hdr->p_type == PT_TLS) { + Rt_map *map; + + dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map); + + if (map->rt_tlsmodid == main_tls_modid) { + *(uptr *)data = hdr->p_memsz; + return -1; + } + } + } + return 0; +} +#endif // SANITIZER_SOLARIS + #if !SANITIZER_GO static void GetTls(uptr *addr, uptr *size) { #if SANITIZER_ANDROID @@ -507,9 +542,15 @@ } } #elif SANITIZER_SOLARIS - // FIXME *addr = 0; *size = 0; + // Find size (p_memsz) of TLS block of the main program. + dl_iterate_phdr(GetSizeFromHdr, size); + + if (*size != 0) { + TLS_index ti = {(unsigned long)main_tls_modid, 0}; + *addr = (uptr)__tls_get_addr(&ti); + } #else #error "Unknown OS" #endif Index: clang/tools/driver/CMakeLists.txt =================================================================== --- clang/tools/driver/CMakeLists.txt +++ clang/tools/driver/CMakeLists.txt @@ -91,9 +91,10 @@ set(TOOL_INFO_BUILD_VERSION) endif() +include(CheckLinkerFlag) + if(CLANG_ORDER_FILE AND - (LLVM_LINKER_IS_LD64 OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD)) - include(CheckLinkerFlag) + (LLVM_LINKER_IS_LD64 OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD)) if (LLVM_LINKER_IS_LD64) set(LINKER_ORDER_FILE_OPTION "-Wl,-order_file,${CLANG_ORDER_FILE}") @@ -118,3 +119,5 @@ set_target_properties(clang PROPERTIES LINK_DEPENDS ${CLANG_ORDER_FILE}) endif() endif() + +check_linker_flag("-Wl,-z,relax=transtls" LINKER_SUPPORTS_Z_RELAX_TRANSTLS) Index: clang/lib/Driver/ToolChains/Solaris.cpp =================================================================== --- clang/lib/Driver/ToolChains/Solaris.cpp +++ clang/lib/Driver/ToolChains/Solaris.cpp @@ -14,6 +14,8 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -138,8 +140,19 @@ CmdArgs.push_back("-lgcc"); CmdArgs.push_back("-lm"); } - if (NeedsSanitizerDeps) + if (NeedsSanitizerDeps) { linkSanitizerRuntimeDeps(getToolChain(), CmdArgs); + + // Work around Solaris/amd64 ld bug when calling __tls_get_addr directly. + // However, ld -z relax=transtls is available since Solaris 11.2, but not + // in Illumos. + const SanitizerArgs &SA = getToolChain().getSanitizerArgs(); + if (LINKER_SUPPORTS_Z_RELAX_TRANSTLS && + getToolChain().getTriple().getArch() == llvm::Triple::x86_64 && + (SA.needsAsanRt() || SA.needsStatsRt() || + (SA.needsUbsanRt() && !SA.requiresMinimalRuntime()))) + CmdArgs.push_back("-zrelax=transtls"); + } } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { Index: clang/include/clang/Config/config.h.cmake =================================================================== --- clang/include/clang/Config/config.h.cmake +++ clang/include/clang/Config/config.h.cmake @@ -69,6 +69,9 @@ /* Linker version detected at compile time. */ #cmakedefine HOST_LINK_VERSION "${HOST_LINK_VERSION}" +/* Linker supports -z relax=transtls option. */ +#cmakedefine01 LINKER_SUPPORTS_Z_RELAX_TRANSTLS + /* pass --build-id to ld */ #cmakedefine ENABLE_LINKER_BUILD_ID
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits