This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: An optimization bug in egcs 1.0.2?
- To: rth at cygnus dot com
- Subject: Re: An optimization bug in egcs 1.0.2?
- From: hjl at lucon dot org (H.J. Lu)
- Date: Tue, 24 Mar 1998 08:28:55 -0800 (PST)
- Cc: egcs at cygnus dot com, drepper at cygnus dot com
>
> On Mon, Mar 23, 1998 at 04:53:09PM -0800, H.J. Lu wrote:
> > It is from the dynamic linker in glibc 2. memcpy is safe there.
> > memcpy is used for optimization.
>
> No, memcpy on overlapping objects is wrong.
>
> memcpy (tail, tail + 1,
> (void *) _dl_global_scope_end - (void *) tail);
>
> This may happen to work on the particular implementation
> of memcpy used on i386, but will fail for others.
>
I was wrong. The bug was in glibc 2.0.7. Here is the code in question.
As you can see, _dl_global_scope_end is adjusted before calling
memmove, which, BTW, is not inlined by egcs 1.0.2. The dynamic linker
will then call fixup () where there is
*_dl_global_scope_end = NULL;
As the result, when memmove is entered, memory pointed to by tail + 1
has been already changed.
Ulrich, we should go over every place in dl where _dl_global_scope_end
is used to double check if there is a similar bug.
Thanks.
--
H.J. Lu (hjl@gnu.org)
----
#include <string.h>
#include <link.h>
void
_dl_remove (struct link_map *map)
{
struct link_map **tail = _dl_global_scope_end;
do
--tail;
while (*tail != map);
--_dl_global_scope_end;
memmove (tail, tail + 1,
(char *) _dl_global_scope_end - (char *) tail);
_dl_global_scope_end [0] = NULL;
_dl_global_scope_end [1] = NULL;
}