Rainer Orth <r...@cebitec.uni-bielefeld.de> writes:

> Before Solaris 11.5, struct dl_phdr_info lacked the dlpi_tls_modid
> member.  While the support might be backported to Solaris 11.4, it
> certainly won't to previous Solaris releases.  To work around this, I've
> used the following patch.  Again, it's pretty straightforward.
>
> Point of note:
>
> * On Solaris, FreeBSD and NetBSD, dl_phdr_info is always visible in
>   <link.h>, while on Linux one needs to define _GNU_SOURCE.
>   AC_USE_SYSTEM_EXTENSION takes care of this, but needs to be called
>   early (i.e. not in DRUNTIME_OS_DLPI_TLS_MODID) to avoid an autoconf
>   warning:
>
> configure.ac:129: warning: AC_COMPILE_IFELSE was called before 
> AC_USE_SYSTEM_EXTENSIONS
> m4/druntime/os.m4:190: DRUNTIME_OS_DLPI_TLS_MODID is expanded from...
> configure.ac:129: the top level
>
> Tested on i386-pc-solaris2.11 (Solaris 11.4) and x86_64-pc-linux-gnu.
>
> Not unexpectedly, there are a couple of regressions compared to the
> Solaris 11.5/x86 results:
>
> +FAIL: gdc.test/runnable/testaa.d   execution test
> +FAIL: gdc.test/runnable/testaa.d -fPIC   execution test
> +FAIL: gdc.test/runnable/testaa.d -fPIC -shared-libphobos   execution test
> +FAIL: gdc.test/runnable/testaa.d -shared-libphobos   execution test
>
>   32 and 64-bit
>
> +FAIL: gdc.test/runnable/xtest55.d   execution test
> +FAIL: gdc.test/runnable/xtest55.d -shared-libphobos   execution test
>
>   64-bit only
>
> +FAIL: libphobos.shared/link_linkdep.d 
> -I/vol/gcc/src/hg/trunk/local/libphobos/t
> estsuite/libphobos.shared liblinkdep.so lib.so -shared-libphobos execution 
> test
>
> +FAIL: libphobos.shared/load_linkdep.d -shared-libphobos -ldl execution test
> +FAIL: libphobos.shared/load_loaddep.d -shared-libphobos -ldl execution test
>
> +FAIL: libphobos.shared/linkDR.c -shared-libphobos -ldl -pthread execution 
> test
> +FAIL: libphobos.shared/host.c -ldl -pthread execution test
> +FAIL: libphobos.shared/loadDR.c -ldl -pthread -g execution test
>
>   32 and 64-bit
>
> +FAIL: libphobos.shared/link.d 
> -I/vol/gcc/src/hg/trunk/local/libphobos/testsuite/libphobos.shared lib.so 
> -shared-libphobos execution test
>
>   64-bit only
>
> I haven't looked much closer yet, just posting this to see if anything
> along those lines could be acceptable at all.

Fortunately, Iain just discovered a way better way to work around the
lack of dlpi_tls_modid: dlinfo(RTLD_DI_LINKMAP) returns not only a
pointer to a Link_map * as documented in the man page, but rather a
pointer to a struct Rt_map which also includes a rt_tlsmodid member.
It has been this way since at least Solaris 9 and the Solaris/Illumos
sources ($SRC/cmd/sgs/include/rtld.h) explicitly have a comment around
the start of the structure stateing

        Exposed to rtld_db - don't move, don't delete

which pretty much guarantees that this can be relied on.

The only other quirk of note is that before dlpi_tls_modid got added,
tlsmodid started at 0 for the main executable, not 1 as the glibc spec
required and libdruntime assumes.  I account for this by adjusting
_tlsMod on dlinfo and undoing the adjustment before passing it to
__tls_get_adddr, the only consumer.

With the revised patch below, I get clean gdc testresults on Solaris
11.3 and 11.4 (and still on 11.5 which uses the dlpi_tls_modid path),
and almost identical libphobos testresults on all three versions.

I hope this is good to go in (the sections_elf_shared.d part via
upstream, the rest directly) now?

Thanks a lot to Iain for discovering this.

        Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University


2019-01-22  Rainer Orth  <r...@cebitec.uni-bielefeld.de>
            Iain Buclaw  <ibuc...@gdcproject.org>

        PR d/88150
        * m4/druntime/os.m4 (DRUNTIME_OS_DLPI_TLS_MODID): New macro.
        * configure.ac: Use it.
        Call AC_USE_SYSTEM_EXTENSIONS.
        * configure: Regenerate.
        * Makefile.in, libdruntime/Makefile.in, src/Makefile.in,
        testsuite/Makefile.in: Regenerate.
        * libdruntime/gcc/config.d.in (OS_Have_Dlpi_Tls_Modid): Define.
        * libdruntime/rt/sections_elf_shared.d (scanSegments) <PT_TLS>:
        [OS_Have_Dlpi_Tls_Modid]: Use dlpi_tls_modid.
        [Solaris]: Use dlinfo(RTLD_DI_LINKMAP) to get rt_tlsmodid.
        Otherwise clear pdso._tlsMod, pdso._tlsSize.
        (getTLSRange) [Solaris && !OS_Have_Dlpi_Tls_Modid]: Readjust mod.

# HG changeset patch
# Parent  3b397b651aecb48e300966e0d709ac6e5cf0c3b8
Work around lack of dlpi_tls_modid before Solaris 11.5

diff --git a/libphobos/configure.ac b/libphobos/configure.ac
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -32,6 +32,7 @@ AC_CONFIG_HEADERS(config.h)
 
 AM_ENABLE_MULTILIB(, ..)
 AC_CANONICAL_SYSTEM
+AC_USE_SYSTEM_EXTENSIONS
 
 target_alias=${target_alias-$target}
 AC_SUBST(target_alias)
@@ -126,6 +127,7 @@ DRUNTIME_OS_SOURCES
 DRUNTIME_OS_THREAD_MODEL
 DRUNTIME_OS_ARM_EABI_UNWINDER
 DRUNTIME_OS_MINFO_BRACKETING
+DRUNTIME_OS_DLPI_TLS_MODID
 DRUNTIME_OS_LINK_SPEC
 DRUNTIME_LIBRARIES_CLIB
 
diff --git a/libphobos/libdruntime/gcc/config.d.in b/libphobos/libdruntime/gcc/config.d.in
--- a/libphobos/libdruntime/gcc/config.d.in
+++ b/libphobos/libdruntime/gcc/config.d.in
@@ -35,6 +35,9 @@ enum ThreadModel
 
 enum ThreadModel GNU_Thread_Model = ThreadModel.@DCFG_THREAD_MODEL@;
 
+// Whether struct dl_phdr_info has dlpi_tls_modid member.
+enum OS_Have_Dlpi_Tls_Modid = @DCFG_DLPI_TLS_MODID@;
+
 // Whether target has support for builtin atomics.
 enum GNU_Have_Atomics = @DCFG_HAVE_ATOMIC_BUILTINS@;
 
diff --git a/libphobos/libdruntime/rt/sections_elf_shared.d b/libphobos/libdruntime/rt/sections_elf_shared.d
--- a/libphobos/libdruntime/rt/sections_elf_shared.d
+++ b/libphobos/libdruntime/rt/sections_elf_shared.d
@@ -750,8 +750,40 @@ void scanSegments(in ref dl_phdr_info in
 
         case PT_TLS: // TLS segment
             assert(!pdso._tlsSize); // is unique per DSO
-            pdso._tlsMod = info.dlpi_tls_modid;
-            pdso._tlsSize = phdr.p_memsz;
+            static if (OS_Have_Dlpi_Tls_Modid)
+            {
+                pdso._tlsMod = info.dlpi_tls_modid;
+                pdso._tlsSize = phdr.p_memsz;
+            }
+            else version (Solaris)
+            {
+                struct Rt_map
+                {
+                    Link_map rt_public;
+                    const char* rt_pathname;
+                    c_ulong rt_padstart;
+                    c_ulong rt_padimlen;
+                    c_ulong rt_msize;
+                    uint rt_flags;
+                    uint rt_flags1;
+                    c_ulong rt_tlsmodid;
+                }
+
+                Rt_map* map;
+                version (Shared)
+                    dlinfo(handleForName(info.dlpi_name), RTLD_DI_LINKMAP, &map);
+                else
+                    dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
+                // Until Solaris 11.4, tlsmodid for the executable is 0.
+                // Let it start at 1 as the rest of the code expects.
+                pdso._tlsMod = map.rt_tlsmodid + 1;
+                pdso._tlsSize = phdr.p_memsz;
+            }
+            else
+            {
+                pdso._tlsMod = 0;
+                pdso._tlsSize = 0;
+            }
             break;
 
         default:
@@ -1055,6 +1087,12 @@ void[] getTLSRange(size_t mod, size_t sz
     if (mod == 0)
         return null;
 
+    version (Solaris)
+    {
+        static if (!OS_Have_Dlpi_Tls_Modid)
+            mod -= 1;
+    }
+
     // base offset
     auto ti = tls_index(mod, 0);
     return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -184,6 +184,20 @@ AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING],
   AC_LANG_POP([C])
 ])
 
+# DRUNTIME_OS_DLPI_TLS_MODID
+# ----------------------------
+# Check if struct dl_phdr_info includes the dlpi_tls_modid member and  
+# substitute DCFG_DLPI_TLS_MODID.
+AC_DEFUN([DRUNTIME_OS_DLPI_TLS_MODID],
+[
+  AC_LANG_PUSH([C])
+  AC_CHECK_MEMBER([struct dl_phdr_info.dlpi_tls_modid],
+		  [DCFG_DLPI_TLS_MODID=true], [DCFG_DLPI_TLS_MODID=false],
+		  [[#include <link.h>]])
+  AC_SUBST(DCFG_DLPI_TLS_MODID)
+  AC_LANG_POP([C])
+])
+
 # DRUNTIME_OS_LINK_SPEC
 # ---------------------
 # Add target-specific link options to link_spec.

Reply via email to