Index | Thread | Search

From:
ASOU Masato <takeasou.masato@gmail.com>
Subject:
Re: ld.so not calling destructor
To:
Alexander Bluhm <bluhm@openbsd.org>
Cc:
tech@openbsd.org, Philip Guenther <guenther@openbsd.org>
Date:
Fri, 17 Jan 2025 14:19:33 +0900

Download raw body.

Thread
I applied your patch and following diff:

diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c
index 43b19855551..53df24cf857 100644
--- a/libexec/ld.so/library_subr.c
+++ b/libexec/ld.so/library_subr.c
@@ -457,7 +457,8 @@ _dl_child_refcnt_decrement(elf_object_t *object)
        struct object_vector vec;
        int i;

-       object->refcount--;
+       if (object->refcount > 0)
+               object->refcount--;
        if (OBJECT_REF_CNT(object) == 0)
                for (vec = object->child_vec, i = 0; i < vec.len; i++)
                        _dl_child_refcnt_decrement(vec.vec[i]);
@@ -532,6 +533,17 @@ _dl_link_child(elf_object_t *dep, elf_object_t *p)
            p->load_name));
 }


As a result, do-prog[1234] were succeeded.  However, run-regress-prog1 failed.

==== do-prog1 ====
./prog1 | cmp -s
/usr/src/regress/libexec/ld.so/initfirst/test1/prog1/expected1 -

==== do-prog2 ====
./prog2 | cmp -s
/usr/src/regress/libexec/ld.so/initfirst/test1/prog1/expected2 -

==== do-prog3 ====
./prog3 | cmp -s
/usr/src/regress/libexec/ld.so/initfirst/test1/prog1/expected3 -

==== do-prog4 ====
./prog4 | cmp -s
/usr/src/regress/libexec/ld.so/initfirst/test1/prog1/expected4 -

===> initfirst/test2
===> initfirst/test2/libae
===> initfirst/test2/libad
===> initfirst/test2/libac
===> initfirst/test2/libab
===> initfirst/test2/libaa
===> initfirst/test2/prog1
==== run-regress-prog1 ====
[ "`./prog1`" = "DBECAPpacebd" ]
*** Error 1 in initfirst/test2/prog1 (Makefile:56 'run-regress-prog1')
FAILED


The test expects "DBECAPpacebd", but prog1 outputs "DBECAPacebdp" as berow:

$ ./initfirst/test2/prog1/obj/prog1
DBECAPacebdp%
--
ASOU Masato


On Fri, Jan 17, 2025 at 9:07 AM ASOU Masato <takeasou.masato@gmail.com> wrote:
>
> I applied the patch and ran make in
> /usr/src/regress/libexec/ld.so/initfirst/test1/prog1 and it failed
> with following:
>
> $ cd /usr/src/regress/libexec/ld.so/initfirst/test1/prog1
> $ make
> ==== do-prog1 ====
> ./prog1 | cmp -s
> /usr/src/regress/libexec/ld.so/initfirst/test1/prog1/expected1 -
> *** Error 1 in . (Makefile:22 'do-prog1')
> FAILED
> *** Error 1 in /usr/src/regress/libexec/ld.so/initfirst/test1/prog1
> (<bsd.regress.mk>:105 'regress': if make -C
> /usr/src/regress/libexec/ld....)
> $ obj/prog1
> init if1
> init if2
> init normal
> main
> func normal
> $ cat expected1
> init if1
> init if2
> init normal
> main
> func normal
> fini normal
> fini if1
> fini if2
> $
>
> The destructor is not called.  Before applying the patch this test
> passed.
>
> I'm investigating this issue.
> --
> ASOU Masato
>
> On Sat, Dec 21, 2024 at 12:37 AM Alexander Bluhm <bluhm@openbsd.org> wrote:
> >
> > Hi,
> >
> > The test suite of my new devel/llvm-openmp port fails as ld.so does
> > not call the destructor.  OpenMP registers it like this.
> >
> > __attribute__((destructor)) void __kmp_internal_end_dtor(void) {
> >   __kmp_internal_end_atexit();
> > }
> >
> > Debugging in ld.so shows that the library refcount is never decremented
> > and so the callback is never invoked.  Diff below fixes the issue.
> >
> > I this approach correct?
> >
> > bluhm
> >
> > Index: libexec/ld.so/library_subr.c
> > ===================================================================
> > RCS file: /mount/openbsd/cvs/src/libexec/ld.so/library_subr.c,v
> > diff -u -p -r1.55 library_subr.c
> > --- libexec/ld.so/library_subr.c        27 Apr 2023 12:27:56 -0000      1.55
> > +++ libexec/ld.so/library_subr.c        6 Dec 2024 20:28:11 -0000
> > @@ -533,6 +533,17 @@ _dl_link_child(elf_object_t *dep, elf_ob
> >  }
> >
> >  void
> > +_dl_unlink_children(void)
> > +{
> > +       elf_object_t *node;
> > +
> > +       for (node = _dl_objects; node != NULL; node = node->next) {
> > +               if (node->refcount > 0)
> > +                       _dl_child_refcnt_decrement(node);
> > +       }
> > +}
> > +
> > +void
> >  object_vec_grow(struct object_vector *vec, int more)
> >  {
> >         vec->alloc += more;
> > Index: libexec/ld.so/loader.c
> > ===================================================================
> > RCS file: /mount/openbsd/cvs/src/libexec/ld.so/loader.c,v
> > diff -u -p -r1.223 loader.c
> > --- libexec/ld.so/loader.c      22 Jan 2024 02:08:31 -0000      1.223
> > +++ libexec/ld.so/loader.c      6 Dec 2024 20:25:07 -0000
> > @@ -202,6 +202,7 @@ _dl_dtors(void)
> >
> >         /* ORDER? */
> >         _dl_unload_dlopen();
> > +       _dl_unlink_children();
> >
> >         DL_DEB(("doing dtors\n"));
> >
> > Index: libexec/ld.so/resolve.h
> > ===================================================================
> > RCS file: /mount/openbsd/cvs/src/libexec/ld.so/resolve.h,v
> > diff -u -p -r1.108 resolve.h
> > --- libexec/ld.so/resolve.h     21 May 2024 05:00:47 -0000      1.108
> > +++ libexec/ld.so/resolve.h     6 Dec 2024 20:23:31 -0000
> > @@ -318,6 +318,7 @@ int _dl_load_dep_libs(elf_object_t *obje
> >  int _dl_rtld(elf_object_t *object);
> >  void _dl_call_init(elf_object_t *object);
> >  void _dl_link_child(elf_object_t *dep, elf_object_t *p);
> > +void _dl_unlink_children(void);
> >  void _dl_link_grpsym(elf_object_t *object);
> >  void _dl_cache_grpsym_list_setup(elf_object_t *_object);
> >  void _dl_link_grpref(elf_object_t *load_group, elf_object_t *load_object);
> >