Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Mon, 27 Aug 2018, Liu Hao wrote: This patch breaks libgcc. At the moment the `__main()` function which performs global initialization for static objects cannot handle `__CTOR_LIST__` with two pointers of `-1` in the front of it [1]. The code is presumed to call every function via pointers between the first `-1` and final null terminator in reverse order, which, if the second element is a duplicated `-1`, will result in a segfault at the last iteration of the loop. To clarify; mingw-w64-crt has got its own __main function, while libgcc provides another one. The one in mingw-w64 should handle this just fine, while the libgcc ones obviously doesn't. Probably this patch should be reverted. Yes, unless we come up with something better, soon. Feel free to revert, but please amend the commit message to clarify that there are two different implementations of the __main function; the one we have worked fine but the libgcc one didn't handle our special situation. I had an idea to try to move the defintion of these symbols from crtexe.c/crtdll.c into gccmain.c, but that makes them turn up too late in the link, after constructors from some object files, so that doesn't really work. If we revert this, my next alternative towards unifying this handling across binutils and lld, would be to first make mingw-w64 check for these symbols during the build so we can make the previous ifdefs a bit more flexible (not having to check for #ifdef __clang__, which the compiler doesn't say what linker one was going to use) - I have a pretty much ready patch for this already. Then secondly, we could make lld provide the symbols, to make things with gcc+binutils behave the same as with clang+lld, making the CRT object files compatible across both linkers at the same time. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
This patch breaks libgcc. At the moment the `__main()` function which performs global initialization for static objects cannot handle `__CTOR_LIST__` with two pointers of `-1` in the front of it [1]. The code is presumed to call every function via pointers between the first `-1` and final null terminator in reverse order, which, if the second element is a duplicated `-1`, will result in a segfault at the last iteration of the loop. Probably this patch should be reverted. [1] https://github.com/gcc-mirror/gcc/blob/master/libgcc/gbl-ctors.h#L75 -- Best regards, LH_Mouse -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Fri, 3 Aug 2018, Liu Hao wrote: 在 2018-08-03 03:16, Martin Storsjö 写道: GNU binutils ld traditionally provides __CTOR_LIST__ and __DTOR_LIST__ symbols via a linker script, while lld doesn't. (... ...) -#else -// old method that iterates the list twice because old linker scripts do not have __CTOR_END__ This drops the compatibility with those 'old linker scripts', doesn't it? (Explained before that it doesn't.) This patch looks good otherwise. Thanks, pushed now, after getting the corresponding comment in binutils tweaked a little. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Fri, 3 Aug 2018, Liu Hao wrote: 在 2018-08-03 03:16, Martin Storsjö 写道: GNU binutils ld traditionally provides __CTOR_LIST__ and __DTOR_LIST__ symbols via a linker script, while lld doesn't. (... ...) -#else -// old method that iterates the list twice because old linker scripts do not have __CTOR_END__ This drops the compatibility with those 'old linker scripts', doesn't it? No, it's still compatible - we provide our own __CTOR_END__ anyway, which is sorted in the right place by the linker due to the section name. In practice this comment seemed to be a bit misleading, because not even the latest binutils provide __CTOR_END__. It does store the terminating null pointer here, but it doesn't provide any symbol pointing to it. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
在 2018-08-03 03:16, Martin Storsjö 写道: > GNU binutils ld traditionally provides __CTOR_LIST__ and __DTOR_LIST__ > symbols via a linker script, while lld doesn't. > (... ...) > -#else > -// old method that iterates the list twice because old linker scripts do not > have __CTOR_END__ This drops the compatibility with those 'old linker scripts', doesn't it? This patch looks good otherwise. -- Best regards, LH_Mouse -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On 08/02/2018 08:25 PM, Martin Storsjö wrote: > On Thu, 2 Aug 2018, Liu Hao wrote: > >>> index 54cbf02..44ff653 100644 >>> --- a/mingw-w64-crt/crt/gccmain.c >>> +++ b/mingw-w64-crt/crt/gccmain.c >>> @@ -23,18 +23,24 @@ __do_global_dtors (void) >>> while (*p) >>> { >>> - (*(p)) (); >>> + // If the linker provided its own __DTOR_LIST__ in addition to >>> the >>> + // one we provide, we'd end up with the first pointer here being >>> + // a (func_ptr)-1 sentinel. >> >> jon_y used to require all comments be C89-ish. I am not totally clear >> about the reason. May he elaborate a little. > > I forgot to change this for this patch when I posted the updated > version, but I changed it for the cxa_atexit patchset before pushing. > > // Martin > > It's a preference, but not a hard one, seeing though C89 style comments are supported by all C compliant compilers. signature.asc Description: OpenPGP digital signature -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Thu, 2 Aug 2018, Liu Hao wrote: index 54cbf02..44ff653 100644 --- a/mingw-w64-crt/crt/gccmain.c +++ b/mingw-w64-crt/crt/gccmain.c @@ -23,18 +23,24 @@ __do_global_dtors (void) while (*p) { - (*(p)) (); + // If the linker provided its own __DTOR_LIST__ in addition to the + // one we provide, we'd end up with the first pointer here being + // a (func_ptr)-1 sentinel. jon_y used to require all comments be C89-ish. I am not totally clear about the reason. May he elaborate a little. I forgot to change this for this patch when I posted the updated version, but I changed it for the cxa_atexit patchset before pushing. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Thu, 2 Aug 2018, Martin Storsjö wrote: On Thu, 2 Aug 2018, Liu Hao wrote: 在 2018/8/2 19:02, Martin Storsjö 写道: -#ifdef __clang__ extern func_ptr __CTOR_END__[]; extern func_ptr __DTOR_END__[]; void __do_global_ctors (void) { static func_ptr *p = __CTOR_END__ - 1; + // If the linker provided its own __CTOR_LIST__ in addition to the one + // we provide, we'd actually stop at __CTOR_LIST__+1, but that's no problem + // for this function. while (*p != (func_ptr) -1) { (*(p))(); At the very firsts iteration, isn't `*p` null if there are two null termini in the list? (i.e. the list looks like `-1, -1, ... some `func_ptr`s ... , 0, 0`) I thought the same; that's why I did the extra check with "if (*p)", as I mentioned in the other mail. However, in practice, __CTOR_END__ points to the first 0-terminator. Not sure why that is, but you can check with -Wl,-Map,map.txt. But yes, it's safer with that extra check added, then both iterations should be fine, regardless which one the symbol points to, in both ends. This is because it seems like GNU LD actually never provides any __CTOR_END__ symbol. But we can have the extra check in any case, for safety and symmetry. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Thu, 2 Aug 2018, Liu Hao wrote: 在 2018/8/2 19:02, Martin Storsjö 写道: -#ifdef __clang__ extern func_ptr __CTOR_END__[]; extern func_ptr __DTOR_END__[]; void __do_global_ctors (void) { static func_ptr *p = __CTOR_END__ - 1; + // If the linker provided its own __CTOR_LIST__ in addition to the one + // we provide, we'd actually stop at __CTOR_LIST__+1, but that's no problem + // for this function. while (*p != (func_ptr) -1) { (*(p))(); At the very firsts iteration, isn't `*p` null if there are two null termini in the list? (i.e. the list looks like `-1, -1, ... some `func_ptr`s ... , 0, 0`) I thought the same; that's why I did the extra check with "if (*p)", as I mentioned in the other mail. However, in practice, __CTOR_END__ points to the first 0-terminator. Not sure why that is, but you can check with -Wl,-Map,map.txt. But yes, it's safer with that extra check added, then both iterations should be fine, regardless which one the symbol points to, in both ends. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
在 2018/8/2 19:02, Martin Storsjö 写道: > -#ifdef __clang__ > extern func_ptr __CTOR_END__[]; > extern func_ptr __DTOR_END__[]; > > void __do_global_ctors (void) > { > static func_ptr *p = __CTOR_END__ - 1; > + // If the linker provided its own __CTOR_LIST__ in addition to the one > + // we provide, we'd actually stop at __CTOR_LIST__+1, but that's no problem > + // for this function. > while (*p != (func_ptr) -1) { > (*(p))(); At the very firsts iteration, isn't `*p` null if there are two null termini in the list? (i.e. the list looks like `-1, -1, ... some `func_ptr`s ... , 0, 0`) > p--; > @@ -42,30 +48,6 @@ void __do_global_ctors (void) > atexit (__do_global_dtors); > } > -- Best regards, LH_Mouse -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] crt: Unify and simplify handling of constructor/destructor lists
On Thu, 2 Aug 2018, Liu Hao wrote: 在 2018-08-02 19:02, Martin Storsjö 写道: Signed-off-by: Martin Storsjö --- mingw-w64-crt/crt/crtdll.c | 2 -- mingw-w64-crt/crt/crtexe.c | 2 -- mingw-w64-crt/crt/gccmain.c | 34 -- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/mingw-w64-crt/crt/crtdll.c b/mingw-w64-crt/crt/crtdll.c index 50a9eb4..af69573 100644 --- a/mingw-w64-crt/crt/crtdll.c +++ b/mingw-w64-crt/crt/crtdll.c @@ -40,12 +40,10 @@ extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[]; extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[]; extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[]; -#ifdef __clang__ __attribute__ (( __section__ (".ctors"), __used__ , aligned(sizeof(void * const void * __CTOR_LIST__ = (void *) -1; __attribute__ (( __section__ (".dtors"), __used__ , aligned(sizeof(void * const void * __DTOR_LIST__ = (void *) -1; __attribute__ (( __section__ (".ctors.9"), __used__ , aligned(sizeof(void * const void * __CTOR_END__ = (void *) 0; __attribute__ (( __section__ (".dtors.9"), __used__ , aligned(sizeof(void * const void * __DTOR_END__ = (void *) 0; -#endif Does GNU LD recognize the `.9` suffix? The known and working way to sort sections for GNU LD for Windows is .ctors$ .ctors$foo .ctors$ and such sections are sorted in alphabet order rather than numeric order. This could explain why these symbols are not emitted for GCC. Yes, GNU LD supports it - you get similar things emitted by GCC if you specify a constructor priority. Case example: $ cat test.cpp void other(void); class Foo { public: Foo() { other(); } }; Foo foo1 __attribute__((init_priority(101))); Foo foo2 __attribute__((init_priority(65534))); $ x86_64-w64-mingw32-g++ -S test.cpp -o - -O2 | grep ctors .section.ctors.65434,"w" .section.ctors.1,"w" The number after .ctors is 65535 minus the value specified in init_priority. The values are padded to 5 digits with leading zeros, and GNU LD sorts them alphabetically when linking, which is equal to numeric order when it's zero padded. Since the values are in the range 0-65535, the sentinel at 9 will always be sorted last. diff --git a/mingw-w64-crt/crt/gccmain.c b/mingw-w64-crt/crt/gccmain.c index 54cbf02..44ff653 100644 --- a/mingw-w64-crt/crt/gccmain.c +++ b/mingw-w64-crt/crt/gccmain.c @@ -23,18 +23,24 @@ __do_global_dtors (void) while (*p) { - (*(p)) (); + // If the linker provided its own __DTOR_LIST__ in addition to the + // one we provide, we'd end up with the first pointer here being + // a (func_ptr)-1 sentinel. jon_y used to require all comments be C89-ish. I am not totally clear about the reason. May he elaborate a little. I can change them to that style if there's a preference for that - I'll not repost any new version of the patch just for that though. Just to be safe, I'm amending the patch locally like this as well: @@ -42,7 +42,8 @@ void __do_global_ctors (void) // we provide, we'd actually stop at __CTOR_LIST__+1, but that's no problem // for this function. while (*p != (func_ptr) -1) { -(*(p))(); +if (*p) + (*(p))(); p--; } That doesn't turn out to be necessary in my testing with GNU LD, but it's safer that way. // Martin -- Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public