libsanitizer: Fix Solaris 11.3 compilation [PR105531]
Commit Message
The libsanitizer build has been broken on Solaris 11.3 by the latest
import. An upstream patch to fix this has now been committed:
[sanitizer_common] Support Solaris < 11.4 in GetStaticTlsBoundary
https://reviews.llvm.org/D120059
I'd like to cherry-pick it into libsanitizer, too.
Bootstrapped without regressions on sparc-sun-solaris2.11,
i386-pc-solaris2.11 (both Solaris 11.3 and 11.4), and
x86_64-pc-linux-gnu.
Ok for trunk?
Rainer
Comments
On Fri, Jul 22, 2022 at 11:29 AM Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
>
> The libsanitizer build has been broken on Solaris 11.3 by the latest
> import. An upstream patch to fix this has now been committed:
>
> [sanitizer_common] Support Solaris < 11.4 in GetStaticTlsBoundary
> https://reviews.llvm.org/D120059
>
> I'd like to cherry-pick it into libsanitizer, too.
>
> Bootstrapped without regressions on sparc-sun-solaris2.11,
> i386-pc-solaris2.11 (both Solaris 11.3 and 11.4), and
> x86_64-pc-linux-gnu.
>
> Ok for trunk?
OK.
> Rainer
>
> --
> -----------------------------------------------------------------------------
> Rainer Orth, Center for Biotechnology, Bielefeld University
>
>
> 2022-07-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
>
> libsanitizer:
> PR sanitizer/105531
> * libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp,
> libsanitizer/sanitizer_common/sanitizer_solaris.h:: Cherry-pick
> llvm-project revision 3776db9a4fd2080d23d6a5f52e405eea44558761.
>
# HG changeset patch
# Parent 755774c20b0c4c41572195333c097be29d392b53
libsanitizer: Fix Solaris 11.3 compilation [PR105531]
@@ -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()
@@ -62,6 +63,7 @@
#endif
#if SANITIZER_SOLARIS
+#include <stddef.h>
#include <stdlib.h>
#include <thread.h>
#endif
@@ -350,19 +352,43 @@ static uptr TlsGetOffset(uptr ti_module,
extern "C" void *__tls_get_addr(size_t *);
#endif
+static size_t main_tls_modid;
+
static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
void *data) {
- if (!info->dlpi_tls_modid)
+ size_t tls_modid;
+#if SANITIZER_SOLARIS
+ // dlpi_tls_modid is only available since Solaris 11.4 SRU 10. Use
+ // dlinfo(RTLD_DI_LINKMAP) instead which works on all of Solaris 11.3,
+ // 11.4, and Illumos. The tlsmodid of the executable was changed to 1 in
+ // 11.4 to match other implementations.
+ if (size >= offsetof(dl_phdr_info_test, dlpi_tls_modid))
+ main_tls_modid = 1;
+ else
+ main_tls_modid = 0;
+ g_use_dlpi_tls_data = 0;
+ Rt_map *map;
+ dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
+ tls_modid = map->rt_tlsmodid;
+#else
+ main_tls_modid = 1;
+ tls_modid = info->dlpi_tls_modid;
+#endif
+
+ if (tls_modid < main_tls_modid)
return 0;
- uptr begin = (uptr)info->dlpi_tls_data;
+ uptr begin;
+#if !SANITIZER_SOLARIS
+ begin = (uptr)info->dlpi_tls_data;
+#endif
if (!g_use_dlpi_tls_data) {
// Call __tls_get_addr as a fallback. This forces TLS allocation on glibc
// and FreeBSD.
#ifdef __s390__
begin = (uptr)__builtin_thread_pointer() +
- TlsGetOffset(info->dlpi_tls_modid, 0);
+ TlsGetOffset(tls_modid, 0);
#else
- size_t mod_and_off[2] = {info->dlpi_tls_modid, 0};
+ size_t mod_and_off[2] = {tls_modid, 0};
begin = (uptr)__tls_get_addr(mod_and_off);
#endif
}
@@ -370,7 +396,7 @@ static int CollectStaticTlsBlocks(struct
if (info->dlpi_phdr[i].p_type == PT_TLS) {
static_cast<InternalMmapVector<TlsBlock> *>(data)->push_back(
TlsBlock{begin, begin + info->dlpi_phdr[i].p_memsz,
- info->dlpi_phdr[i].p_align, info->dlpi_tls_modid});
+ info->dlpi_phdr[i].p_align, tls_modid});
break;
}
return 0;
@@ -382,11 +408,11 @@ static int CollectStaticTlsBlocks(struct
dl_iterate_phdr(CollectStaticTlsBlocks, &ranges);
uptr len = ranges.size();
Sort(ranges.begin(), len);
- // Find the range with tls_modid=1. For glibc, because libc.so uses PT_TLS,
- // this module is guaranteed to exist and is one of the initially loaded
- // modules.
+ // Find the range with tls_modid == main_tls_modid. For glibc, because
+ // libc.so uses PT_TLS, this module is guaranteed to exist and is one of
+ // the initially loaded modules.
uptr one = 0;
- while (one != len && ranges[one].tls_modid != 1) ++one;
+ while (one != len && ranges[one].tls_modid != main_tls_modid) ++one;
if (one == len) {
// This may happen with musl if no module uses PT_TLS.
*addr = 0;
new file mode 100644
@@ -0,0 +1,56 @@
+//===-- 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;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SOLARIS
+
+#endif // SANITIZER_SOLARIS_H