This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]