Re: gcc14 static linking ends with segfault

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Mon, 27 Jan 2025 20:43:54 UTC
On Mon, Jan 27, 2025 at 09:23:36PM +0100, Dimitry Andric wrote:
> On 27 Jan 2025, at 20:24, Konstantin Belousov <kostikbel@gmail.com> wrote:
> > 
> > On Mon, Jan 27, 2025 at 10:42:25AM -0800, Steve Kargl wrote:
> ...
> >> If I move gcc14/.../crtend.o out of the way, then the segfault goes away
> >> as the linker shows
> >> 
> >> -V -Bstatic -o z
> >> /usr/lib/crt1.o
> >> /usr/lib/crti.o
> >> /usr/lib/crtbeginT.o
> >> ...
> >> /usr/lib/crtend.o
> >> /usr/lib/crtn.o
> > 
> > The following patch worked for me without changing anything in gcc.
> > 
> > From 976aa780b8ad212127d84a47a5a05f1bd6aef60c Mon Sep 17 00:00:00 2001
> > From: Konstantin Belousov <kib@FreeBSD.org>
> > Date: Mon, 27 Jan 2025 21:21:20 +0200
> > Subject: [PATCH] crtbegin: accurately check for the end of .dtors
> > 
> > not relying only on the end section marker, but also checking for the
> > section size when iterating.
> > 
> > Reported by: kargl
> > Analyzed by: dim
> > Sponsored by: The FreeBSD Foundation
> > MFC after: 1 week
> > ---
> > lib/csu/common/crtbegin.c | 10 +++++++++-
> > 1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/lib/csu/common/crtbegin.c b/lib/csu/common/crtbegin.c
> > index d6978859af4a..06fe990052f7 100644
> > --- a/lib/csu/common/crtbegin.c
> > +++ b/lib/csu/common/crtbegin.c
> > @@ -66,19 +66,27 @@ static crt_func __DTOR_LIST__[] __section(".dtors") __used = {
> > (crt_func)-1
> > };
> > 
> > +extern const char startof_dtors[] __asm(".startof..dtors")
> > +    __weak_symbol __hidden;
> > +extern const char sizeof_dtors[] __asm(".sizeof..dtors")
> > +    __weak_symbol __hidden;
> > +
> > static void
> > __do_global_dtors_aux(void)
> > {
> > crt_func fn;
> > + uintptr_t dtors_end;
> > int n;
> > 
> > #ifdef SHARED
> > run_cxa_finalize();
> > #endif
> > 
> > + dtors_end = (uintptr_t)&startof_dtors + (uintptr_t)&sizeof_dtors;
> > for (n = 1;; n++) {
> > fn = __DTOR_LIST__[n];
> > - if (fn == (crt_func)0 || fn == (crt_func)-1)
> > + if (fn == (crt_func)0 || fn == (crt_func)-1 || (dtors_end > 0 &&
> > +     (uintptr_t)&__DTOR_LIST__[n] >= dtors_end))
> > break;
> > fn();
> > }
> 
> Yes, this looks good to me, thanks! Note that even with this safety belt
> applied to crtbegin, it's still a good idea to fix the gcc side... :)
Definitely, I do not think that one fix should exclude another.

> 
> Btw, it would also be nice to add a similar safety belt for ctors?
D48700