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

Reply via email to