This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
[PATCH] Fix PLT infinite loop for cris-*-*.
- From: Hans-Peter Nilsson <hans-peter dot nilsson at axis dot com>
- To: libc-alpha at sources dot redhat dot com
- Cc: Uwe_Reimann at gmx dot net
- Date: Wed, 17 Sep 2003 04:28:05 +0200
- Subject: [PATCH] Fix PLT infinite loop for cris-*-*.
The following program, compiled with -fpic or -fPIC (other options
unimportant; no current GCC optimizes strcasecmp), causes an infinite
loop on cris-axis-linux-gnu.
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
return strcasecmp ? strcasecmp ("X", "Y") != 0 : 1;
}
The infinite loop is due to the .got.plt entry for strcasecmp being
relocated to its own PLT entry when resolving global symbols by
ld.so.1 at program start-up. As the comment in the patch says, the
linker unifies a .got.plt entry with a .got entry if both types of
entries exist for the same symbol. This optimization happens for CRIS
only, AFAIK. It's not critical; not many symbols are used with both a
PLT-type relocation and a GOT-type relocation, but it saves a
relocation and supposedly a symbol lookup at run-time and it seemed
like a good idea at the time.
Uwe saw this problem with glibc-2.3.1 and he sent me a patch to fix it
(thanks!). I tweaked the patch as follows, adding an explanatory
comment and reformatted it as per the GNU coding standard. I saw the
same behavior with glibc-pre-2.2.4, allowing PLT entries as
resolutions for lookups of global symbols. It seems current glibc CVS
has the same behavior.
Now, why is the address of a PLT entry being considered as a valid
symbol value at all? Can this not cause a function pointer in one
object to have a visibly different value than the final function
address (in another object)? If it does happen, that's a (glibc) bug,
right?
I think most dl-machine.h comments at the elf_machine_type_class
definitions are a bit misleading (see patch): it isn't really "iff"
(if and only if), because that'd mean that R_CRIS_GLOB_DAT shouldn't
be classified as ELF_RTYPE_CLASS_PLT because it's used for "normal"
global symbols too. I see in
<URL:http://sources.redhat.com/ml/libc-hacker/2001-08/msg00146.html>
that it's actually supposed to be a bit-mask; a relocation can
belong to several classes. Also, the equality-test at
elf/dl-lookup.c:276 looks wrong; it should be a bit-test. (No, it
doesn't seem to matter for existing ports and rtype-classes but
nevertheless.)
The point is that the patch should be applied iff ;-) you consider the
linker optimization valid. If it's invalid I'd like to be convinced
of why, so I can fix binutils instead. Oh, I don't have CVS write
access to the glibc repo, so if you please.
Thanks.
2003-09-17 Uwe Reimann <Uwe_Reimann@gmx.net>
Hans-Peter Nilsson <hp@axis.com>
* sysdeps/cris/dl-machine.h (elf_machine_type_class): Classify
R_CRIS_GLOB_DAT as ELF_RTYPE_CLASS_PLT. Clarify comment.
Index: dl-machine.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/cris/dl-machine.h,v
retrieving revision 1.11
diff -p -c -r1.11 dl-machine.h
*** dl-machine.h 31 Jul 2003 06:33:51 -0000 1.11
--- dl-machine.h 17 Sep 2003 02:12:17 -0000
*************** _dl_start_user:\n\
*** 228,239 ****
.size _dl_start_user, . - _dl_start_user\n\
.previous");
! /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
! PLT entries should not be allowed to define the value.
! ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
! of the main executable's symbols, as for a COPY reloc. */
! #define elf_machine_type_class(type) \
! ((((type) == R_CRIS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
--- 228,247 ----
.size _dl_start_user, . - _dl_start_user\n\
.previous");
! /* The union of reloc-type-classes where the reloc TYPE is a member.
!
! TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a
! relocation for a PLT entry, that is, for which a PLT entry should not
! be allowed to define the value. The GNU linker for CRIS can merge a
! .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT),
! so we need to match both these reloc types.
!
! TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed
! to resolve to one of the main executable's symbols, as for a COPY
! reloc. */
! #define elf_machine_type_class(type) \
! ((((((type) == R_CRIS_JUMP_SLOT)) \
! || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
brgds, H-P