This is the mail archive of the
libc-hacker@sourceware.cygnus.com
mailing list for the glibc project.
Re: DL patch for glibc 2.0.7 and 2.1
- To: drepper@cygnus.com (Ulrich Drepper)
- Subject: Re: DL patch for glibc 2.0.7 and 2.1
- From: hjl@lucon.org (H.J. Lu)
- Date: Fri, 1 May 1998 08:52:41 -0700 (PDT)
- Cc: gafton@redhat.com, libc-hacker@cygnus.com (GNU C Library)
>
> > Hi,
> >
> > While working on the DL bug, I found some bogus codes in dl-close.c
> > in both glibc 2.0.7 and 2.1. The code below is supposed to remove
> > a shared object if it is on the global scope list.
> >
> > if (imap->l_global)
> > {
> > /* This object is in the global scope list. Remove it. */
> > struct link_map **tail = _dl_global_scope_end;
> > do
> > --tail;
> > while (*tail != imap);
> > while (tail < _dl_global_scope_end)
> > {
> > tail[0] = tail[1];
> > ++tail;
> > }
> > --_dl_global_scope_end;
> > }
> >
> > The problem is if we call dlopen () from a statically linked executable,
> > the shared object being loaded is always put on the global scope list
> > no matter what you do. Now when you call dlclose () on it, it is removed
> > from memory, but it is still on the global scope list if imap->l_global
> > is false. Now we get a problem. It gets even worse when we have
> > multiple calls to dlopen/dlclose at random order from a statically
> > linked executable. We should fix it for bothe 2.0.7 and 2.1.
> >
> >
>
> This is the patch I came up with. The real bug is in dl-open.c. Once
> it is put on the global scope list. You have to keep it in memory by
> incrementing the open count. My patch corrects the open count. It
> should be applied to both 2.0.7 and 2.1.
>
> One problem with dl-open.c is that the new shared object is put on the
> global scope list without even being asked to do so when dlopen () is
> called from the static binary.
>
> BTW, a test case is easy to create. I will provide several if necessary.
>
> Thanks.
>
>
> --
> H.J. Lu (hjl@gnu.org)
> ----
> Fri May 1 00:07:08 1998 H.J. Lu <hjl@gnu.org>
>
> * elf/dl-open.c (_dl_open): Increment the open count if it is
> put on the global scope list.
>
> Index: dl-open.c
> ===================================================================
> RCS file: /home/work/cvs/gnu/glibc/elf/dl-open.c,v
> retrieving revision 1.1.1.9
> diff -u -r1.1.1.9 dl-open.c
> --- dl-open.c 1998/04/04 16:27:09 1.1.1.9
> +++ dl-open.c 1998/05/01 06:59:36
> @@ -163,6 +163,11 @@
> }
> }
>
> + if (new->l_global || _dl_loaded == new)
> + /* We are put on the global scope list, one way or the other. We
> + have to live with it. Increment the open count. */
> + new->l_opencount++;
> +
>
> /* Notify the debugger we have added some objects. We need to call
> _dl_debug_initialize in a static program in case dynamic linking has
>
Here is a revised patch such that
handle = dlopen ("./libfoo.so", RTLD_GLOBAL);
...
dlclose (handle);
will have a chance to really remove ./libfoo.so from memory if it can
be safe to do so.
--
H.J. Lu (hjl@gnu.org)
-----
Fri May 1 08:47:01 1998 H.J. Lu <hjl@gnu.org>
* elf/dl-open.c (_dl_open): Increment the open count if it is
put at the first place on the global scope list.
Index: dl-open.c
===================================================================
RCS file: /home/work/cvs/gnu/glibc-2.0/elf/dl-open.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 dl-open.c
--- dl-open.c 1998/03/31 16:18:44 1.1.1.5
+++ dl-open.c 1998/05/01 15:44:11
@@ -142,6 +142,12 @@
}
}
+ if (_dl_loaded == new)
+ /* We are put at the first place on the global scope list, one way
+ or the other. We may be used by other shared objects. We have to
+ make sure that it stays in memory for them. Increment the open
+ count. */
+ new->l_opencount++;
/* Notify the debugger we have added some objects. We need to call
_dl_debug_initialize in a static program in case dynamic linking has