I've successfully been using a late prototype of an implementation of the dlpi_tls_modid field of struct dl_phdr_info on Solaris 11.5 Beta. This allowed me to get pretty reasonable test results using sections_elf_shared.d on Solaris.
This pretty straightforward patch implements this. Only a few points are worth mentioning: * libdruntime/rt/bss_sections.c refers to __bss_start, which only gld defines. Unfortunately, it's marked weak, so the absence with Solaris ld went unnoticed at first. Lacking an exact equivalent, I'm using _edata instead, which is pretty close modulo section alignment. * As detailed in the PR, not dlclose()ing the handle in handleForName is necessary to avoid an assertion failure. * I'm removing sections_solaris.d since it wouldn't even compile and seems pretty useless. This patch gave me the following testsuite results on Solaris 11.5/x86 (a few more minor testsuite fixes were included, too): === gdc tests === Running target unix FAIL: gdc.test/runnable/nulltype.d execution test FAIL: gdc.test/runnable/nulltype.d -O2 execution test FAIL: gdc.test/runnable/nulltype.d -O2 -shared-libphobos execution test FAIL: gdc.test/runnable/nulltype.d -g execution test FAIL: gdc.test/runnable/nulltype.d -g -O2 execution test FAIL: gdc.test/runnable/nulltype.d -g -O2 -shared-libphobos execution test FAIL: gdc.test/runnable/nulltype.d -g -shared-libphobos execution test FAIL: gdc.test/runnable/nulltype.d -shared-libphobos execution test === gdc Summary for unix === # of expected passes 30785 # of unexpected failures 8 Running target unix/-m64 === gdc Summary for unix/-m64 === # of expected passes 30793 === gdc Summary === # of expected passes 61578 # of unexpected failures 8 /var/gcc/gcc-9.0.1-20190128/11.5-gcc-gas-libphobos/gcc/gdc version 9.0.1 20190128 (experimental) [trunk revision 268335] (GCC) === libphobos tests === Running target unix FAIL: libphobos.shared/load.d -shared-libphobos -ldl execution test FAIL: libphobos.shared/load_13414.d -shared-libphobos -ldl execution test FAIL: libphobos.shared/finalize.d -shared-libphobos -ldl execution test FAIL: libphobos.shared/linkD.c lib.so -ldl -pthread execution test FAIL: libphobos.unittests/druntime/shared/core.sync.mutex FAIL: libphobos.unittests/druntime/shared/core.time === libphobos Summary for unix === # of expected passes 119 # of unexpected failures 6 Running target unix/-m64 FAIL: libphobos.shared/load.d -shared-libphobos -ldl execution test FAIL: libphobos.shared/load_13414.d -shared-libphobos -ldl execution test FAIL: libphobos.shared/finalize.d -shared-libphobos -ldl execution test FAIL: libphobos.shared/linkD.c lib.so -ldl -pthread execution test FAIL: libphobos.unittests/druntime/shared/ld.so.1: FAIL: libphobos.unittests/druntime/shared/unittest: FAIL: libphobos.unittests/druntime/shared/fatal: FAIL: libphobos.unittests/druntime/shared/libgdruntime_t.so.0: FAIL: libphobos.unittests/druntime/shared/open FAIL: libphobos.unittests/druntime/shared/failed: FAIL: libphobos.unittests/druntime/shared/No FAIL: libphobos.unittests/druntime/shared/such FAIL: libphobos.unittests/druntime/shared/file FAIL: libphobos.unittests/druntime/shared/or FAIL: libphobos.unittests/druntime/shared/directory === libphobos Summary for unix/-m64 === # of expected passes 78 # of unexpected failures 15 === libphobos Summary === # of expected passes 197 # of unexpected failures 21 The 32-bit nulltype.d failures occur on Linux, too (PR d/87824), and the 64-bit libphobos.unittests/druntime/shared failures happen because libgdruntime_t.so.0 is only built for the default multilib. The libphobos.shared failures clearly bear investigating. For the amd64 results, I needed a separate patch to workaround an ld bug, to be submitted shortly. While I did run a sparc-sun-solaris2.11 bootstrap, too, results are pretty useless due to PR d/88462 (the minfo alignment issue). Rainer -- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University 2018-11-21 Rainer Orth <r...@cebitec.uni-bielefeld.de> libphobos: PR d/88150 * libdruntime/core/sys/solaris/dlfcn.d: Mark @nogc. * libdruntime/core/sys/solaris/link.d (struct dl_phdr_info): Declare dlpi_tls_modid, dlpi_tls_data members. * libdruntime/core/sys/solaris/sys/link.d (Elf32_Dyn, Elf64_Dyn): Fix syntax. * libdruntime/rt/sections_elf_shared.d [Solaris] (SharedELF): Set to true. Import core.sys.solaris.dlfcn, core.sys.solaris.link, core.sys.solaris.sys.elf, core.sys.solaris.sys.link. (dummy_ref): Declare. (initSections): Initialize dummy_ref. (_Dmodule_ref): Declare. (getDependencies): Set strtab. (handleForName): Don't dlclose handle. (findDSOInfoForAddr): New function. (getprogname): Declare. (progname): Use it. (getCopyRelocSection): Set exeBaseAddr. * libdruntime/rt/sections.d [Solaris]: Import rt.sections_elf_shared instead of rt.sections_solaris. * libdruntime/rt/bss_section.c: Also build if __sun__ && __svr4__. [__sun__ && __svr4__] (_edata): Declare. (rt_get_bss_start): Return &_edata. * libdruntime/rt/sections_solaris.d: Remove. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Remove rt/sections_solaris.d. * libdruntime/Makefile.in: Regenerate.
# HG changeset patch # Parent 7f08ce6ae7a8b4709e973ef8e3765976030c4f53 Use sections_elf_shared.d on Solaris 11.5 (PR d/88150) Fixes for dlpi_tls_modid support. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -181,7 +181,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/a rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d rt/memory.d \ rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \ rt/sections_android.d rt/sections_elf_shared.d rt/sections_osx.d \ - rt/sections_solaris.d rt/sections_win32.d rt/sections_win64.d \ + rt/sections_win32.d rt/sections_win64.d \ rt/switch_.d rt/tlsgc.d rt/typeinfo/ti_Acdouble.d \ rt/typeinfo/ti_Acfloat.d rt/typeinfo/ti_Acreal.d \ rt/typeinfo/ti_Adouble.d rt/typeinfo/ti_Afloat.d rt/typeinfo/ti_Ag.d \ diff --git a/libphobos/libdruntime/core/sys/solaris/dlfcn.d b/libphobos/libdruntime/core/sys/solaris/dlfcn.d --- a/libphobos/libdruntime/core/sys/solaris/dlfcn.d +++ b/libphobos/libdruntime/core/sys/solaris/dlfcn.d @@ -9,6 +9,7 @@ module core.sys.solaris.dlfcn; version (Solaris): extern (C): nothrow: +@nogc: public import core.sys.posix.dlfcn; import core.stdc.config; @@ -109,4 +110,4 @@ struct Dl_serinfo Dl_serpath[1] dls_serpath; } -// FIXME: Dl_argsinfo, Dl_mapinfo, Dl_amd64_unwindinfo are missing \ No newline at end of file +// FIXME: Dl_argsinfo, Dl_mapinfo, Dl_amd64_unwindinfo are missing diff --git a/libphobos/libdruntime/core/sys/solaris/link.d b/libphobos/libdruntime/core/sys/solaris/link.d --- a/libphobos/libdruntime/core/sys/solaris/link.d +++ b/libphobos/libdruntime/core/sys/solaris/link.d @@ -165,6 +165,8 @@ struct dl_phdr_info { ElfW!"Half" dlpi_phnum; uint64_t dlpi_adds; uint64_t dlpi_subs; + size_t dlpi_tls_modid; + void* dlpi_tls_data; }; private alias extern(C) int function(dl_phdr_info*, size_t, void *) dl_iterate_phdr_cb; diff --git a/libphobos/libdruntime/core/sys/solaris/sys/link.d b/libphobos/libdruntime/core/sys/solaris/sys/link.d --- a/libphobos/libdruntime/core/sys/solaris/sys/link.d +++ b/libphobos/libdruntime/core/sys/solaris/sys/link.d @@ -15,22 +15,22 @@ import core.stdc.config; struct Elf32_Dyn { Elf32_Sword d_tag; - union d_un + union _d_un { Elf32_Word d_val; Elf32_Addr d_ptr; Elf32_Off d_off; - } + } _d_un d_un; } struct Elf64_Dyn { Elf64_Xword d_tag; - union d_un + union _d_un { Elf64_Xword d_val; Elf64_Addr d_ptr; - } + } _d_un d_un; } enum DT_NULL = 0; diff --git a/libphobos/libdruntime/rt/bss_section.c b/libphobos/libdruntime/rt/bss_section.c --- a/libphobos/libdruntime/rt/bss_section.c +++ b/libphobos/libdruntime/rt/bss_section.c @@ -10,12 +10,20 @@ /* These symbols are defined in the linker script and bracket the * .bss, .lbss, .lrodata and .ldata sections. */ -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || (defined(__sun__) && defined(__svr4__)) // Need to use weak linkage to workaround a bug in ld.bfd (Bugzilla 13025). extern int __attribute__((weak)) __bss_start, _end; +#if defined(__sun__) && defined(__svr4__) +extern int _edata; +#endif __attribute__ ((visibility ("hidden"))) void* rt_get_bss_start(); __attribute__ ((visibility ("hidden"))) void* rt_get_end(); +#if defined(__sun__) && defined(__svr4__) +// FIXME: This is wrong: begin of .bss and _edata don't always coincide. +void* rt_get_bss_start() { return (void*)&_edata; } +#else void* rt_get_bss_start() { return (void*)&__bss_start; } +#endif void* rt_get_end() { return (void*)&_end; } #endif diff --git a/libphobos/libdruntime/rt/sections.d b/libphobos/libdruntime/rt/sections.d --- a/libphobos/libdruntime/rt/sections.d +++ b/libphobos/libdruntime/rt/sections.d @@ -26,7 +26,7 @@ else version (FreeBSD) else version (NetBSD) public import rt.sections_elf_shared; else version (Solaris) - public import rt.sections_solaris; + public import rt.sections_elf_shared; else version (Darwin) { version (X86_64) 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 @@ -13,6 +13,7 @@ module rt.sections_elf_shared; version (CRuntime_Glibc) enum SharedELF = true; else version (FreeBSD) enum SharedELF = true; else version (NetBSD) enum SharedELF = true; +else version (Solaris) enum SharedELF = true; else enum SharedELF = false; static if (SharedELF): @@ -40,6 +41,13 @@ else version (NetBSD) import core.sys.netbsd.sys.elf; import core.sys.netbsd.sys.link_elf; } +else version (Solaris) +{ + import core.sys.solaris.dlfcn; + import core.sys.solaris.link; + import core.sys.solaris.sys.elf; + import core.sys.solaris.sys.link; +} else { static assert(0, "unimplemented"); @@ -123,6 +131,7 @@ private: version (FreeBSD) private __gshared void* dummy_ref; version (NetBSD) private __gshared void* dummy_ref; +version (Solaris) private __gshared void* dummy_ref; /**** * Gets called on program startup just before GC is initialized. @@ -133,6 +142,7 @@ void initSections() nothrow @nogc // reference symbol to support weak linkage version (FreeBSD) dummy_ref = &_d_dso_registry; version (NetBSD) dummy_ref = &_d_dso_registry; + version (Solaris) dummy_ref = &_d_dso_registry; } @@ -263,6 +273,7 @@ private: // start of linked list for ModuleInfo references version (FreeBSD) deprecated extern (C) __gshared void* _Dmodule_ref; version (NetBSD) deprecated extern (C) __gshared void* _Dmodule_ref; +version (Solaris) deprecated extern (C) __gshared void* _Dmodule_ref; version (Shared) { @@ -677,6 +688,8 @@ version (Shared) strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate else version (NetBSD) strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate + else version (Solaris) + strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate else static assert(0, "unimplemented"); break; @@ -703,7 +716,8 @@ version (Shared) void* handleForName(const char* name) nothrow @nogc { auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY); - if (handle !is null) .dlclose(handle); // drop reference count + version (Solaris) { } + else if (handle !is null) .dlclose(handle); // drop reference count return handle; } } @@ -799,6 +813,23 @@ else version (NetBSD) bool findDSOInfoFo auto dg = DG(addr, result); return dl_iterate_phdr(&callback, &dg) != 0; } +else version (Solaris) bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc +{ + static struct DG { const(void)* addr; dl_phdr_info* result; } + + extern(C) int callback(dl_phdr_info* info, size_t sz, void* arg) nothrow @nogc + { + auto p = cast(DG*)arg; + if (findSegmentForAddr(*info, p.addr)) + { + if (p.result !is null) *p.result = *info; + return 1; // break; + } + return 0; // continue iteration + } + auto dg = DG(addr, result); + return dl_iterate_phdr(&callback, &dg) != 0; +} /********************************* * Determine if 'addr' lies within shared object 'info'. @@ -825,12 +856,14 @@ version (linux) import core.sys.linux.er // should be in core.sys.freebsd.stdlib version (FreeBSD) extern(C) const(char)* getprogname() nothrow @nogc; version (NetBSD) extern(C) const(char)* getprogname() nothrow @nogc; +version (Solaris) extern(C) const(char)* getprogname() nothrow @nogc; @property const(char)* progname() nothrow @nogc { version (linux) return program_invocation_name; version (FreeBSD) return getprogname(); version (NetBSD) return getprogname(); + version (Solaris) return getprogname(); } const(char)[] dsoName(const char* dlpi_name) nothrow @nogc @@ -871,6 +904,8 @@ const(void)[] getCopyRelocSection() noth enum ElfW!"Addr" exeBaseAddr = 0; else version (NetBSD) enum ElfW!"Addr" exeBaseAddr = 0; + else version (Solaris) + enum ElfW!"Addr" exeBaseAddr = 0; dl_phdr_info info = void; findDSOInfoForAddr(bss_start, &info) || assert(0); diff --git a/libphobos/libdruntime/rt/sections_solaris.d b/libphobos/libdruntime/rt/sections_solaris.d deleted file mode 100644 --- a/libphobos/libdruntime/rt/sections_solaris.d +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Written in the D programming language. - * This module provides Solaris-specific support for sections. - * - * Copyright: Copyright Martin Nowak 2012-2013. - * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). - * Authors: Martin Nowak - * Source: $(DRUNTIMESRC src/rt/_sections_solaris.d) - */ - -module rt.sections_solaris; - -version (Solaris): - -// debug = PRINTF; -debug(PRINTF) import core.stdc.stdio; -import core.stdc.stdlib : malloc, free; -import rt.deh, rt.minfo; - -struct SectionGroup -{ - static int opApply(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - static int opApplyReverse(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - @property immutable(ModuleInfo*)[] modules() const nothrow @nogc - { - return _moduleGroup.modules; - } - - @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc - { - return _moduleGroup; - } - - @property immutable(FuncTable)[] ehTables() const nothrow @nogc - { - auto pbeg = cast(immutable(FuncTable)*)&__start_deh; - auto pend = cast(immutable(FuncTable)*)&__stop_deh; - return pbeg[0 .. pend - pbeg]; - } - - @property inout(void[])[] gcRanges() inout nothrow @nogc - { - return _gcRanges[]; - } - -private: - ModuleGroup _moduleGroup; - void[][1] _gcRanges; -} - -void initSections() nothrow @nogc -{ - auto mbeg = cast(immutable ModuleInfo**)&__start_minfo; - auto mend = cast(immutable ModuleInfo**)&__stop_minfo; - _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]); - - auto pbeg = cast(void*)&__dso_handle; - auto pend = cast(void*)&_end; - _sections._gcRanges[0] = pbeg[0 .. pend - pbeg]; -} - -void finiSections() nothrow @nogc -{ -} - -void[] initTLSRanges() nothrow @nogc -{ - auto pbeg = cast(void*)&_tlsstart; - auto pend = cast(void*)&_tlsend; - return pbeg[0 .. pend - pbeg]; -} - -void finiTLSRanges(void[] rng) nothrow @nogc -{ -} - -void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow -{ - dg(rng.ptr, rng.ptr + rng.length); -} - -private: - -__gshared SectionGroup _sections; - -extern(C) -{ - /* Symbols created by the compiler/linker and inserted into the - * object file that 'bracket' sections. - */ - extern __gshared - { - void* __start_deh; - void* __stop_deh; - void* __start_minfo; - void* __stop_minfo; - int __dso_handle; - int _end; - } - - extern - { - void* _tlsstart; - void* _tlsend; - } -}