Hi Iain,

> On Tue, 9 Apr 2019 at 21:27, Rainer Orth <r...@cebitec.uni-bielefeld.de> 
> wrote:
>>
>> 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.
>>
>
> I've finally managed to get around to moving the guts of rt.sections_*
> to gcc.sections.*, with the patch amended to apply to
> gcc/sections/elf_shared.d, this is OK.

Here's the rebased patch for this.  Tested as the previous one and
installed on mainline.

        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/gcc/sections/elf_shared.d: Import gcc.config.
        (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  88c053a22857705ed80d4c41da85c0ff943abecc
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)
@@ -125,6 +126,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/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -74,6 +74,7 @@ else
     static assert(0, "unimplemented");
 }
 import core.sys.posix.pthread;
+import gcc.config;
 import rt.deh;
 import rt.dmain2;
 import rt.minfo;
@@ -792,8 +793,40 @@ void scanSegments(in ref dl_phdr_info in
 
         case PT_TLS: // TLS segment
             safeAssert(!pdso._tlsSize, "Multiple TLS segments in image header.");
-            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:
@@ -1004,6 +1037,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