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]

HEAD and gcc4 build fixes for MIPS


This patch lets glibc build again on mips-linux, using HEAD binutils and gcc.

The only architecture independent change is to the LinuxThreads
thread_self(); it's a pure function, not a const function.  Const functions
are not allowed to read from global memory.  GCC 4.0 hoisted the call to
__pthread_find_self above the checks for the main and manager threads, so
single-threaded applications linked to libpthread.so walked right off the
end of the __pthread_handles array.


The only remaining failures are:

math/test-float.out
math/test-double.out
test-ifloat.out
	These have been around on MIPS for a long time, so I didn't look at
	them.

stdio-common/tst-fseek.out
libio/tst-atime.out
glibc/io/test-utime.out
	These are artifacts of my NFS setup.  Never managed to get rid of
	them.  May need to try a different NFS server...

elf/tst-audit1.out
	I added all the relevant bits to support auditing, but MIPS already
	didn't support LD_PROFILE, so it doesn't work.  MIPS's "funny" GOT
	relocation means that this will be a bit of work to fix.  I'll look
	into it, but not right this moment.

I haven't tested mips64-linux yet, but it can't be any more broken than it
was before, and I did proofread for potential MIPS64 problems.  I'll be doing
testing on mips64-linux a couple of weeks - after I finish up the 32-bit
NPTL port.

Is this patch OK?

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-02-09  Daniel Jacobowitz  <dan@codesourcery.com>

	* elf/tst-auditmod1.c: Add MIPS support.
	* sysdeps/generic/ldsodefs.h (La_mips_32_regs, La_mips_32_retval,
	La_mips_64_regs, La_mips_64_retval): New.
	(struct audit_ifaces): Add MIPS entries.
	* sysdeps/mips/dl-machine.h: Check RESOLVE_MAP instead of RESOLVE.
	(elf_machine_runtime_link_map, ELF_DL_FRAME_SIZE,
	ELF_DL_SAVE_ARG_REGS, ELF_DL_RESTORE_ARG_REGS,
	ELF_MACHINE_RUNTIME_TRAMPOLINE): Remove.
	(RTLD_START): Align the stack before calling _dl_init_internal.
	Use .ent for _dl_start_user.
	(ARCH_LA_PLTENTER, ARCH_LA_PLTEXIT): Define.
	(elf_machine_rel, elf_machine_rel_relative, elf_machine_lazy_rel)
	(elf_machine_runtime_setup): Use "auto inline".
	(elf_machine_got_rel): Likewise.  Use RESOLVE_MAP.
	* sysdeps/mips/dl-trampoline.c: New file.
	* sysdeps/mips/bits/link.h: New file.
	* sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
	(internal_syscall5, internal_syscall6, internal_syscall7): Use
	register operands instead of non-lvalue memory operands.

2005-02-09  Daniel Jacobowitz  <dan@codesourcery.com>

	* descr.h (__pthread_find_self, thread_self): Mark as pure
	instead of const.


Index: elf/tst-auditmod1.c
===================================================================
RCS file: /cvs/glibc/libc/elf/tst-auditmod1.c,v
retrieving revision 1.10
diff -u -p -r1.10 tst-auditmod1.c
--- elf/tst-auditmod1.c	29 Jan 2005 04:10:56 -0000	1.10
+++ elf/tst-auditmod1.c	9 Feb 2005 22:24:54 -0000
@@ -6,7 +6,9 @@
 #include <unistd.h>
 #include <bits/wordsize.h>
 #include <gnu/lib-names.h>
-
+#ifdef __mips__
+#include <sgidefs.h>
+#endif
 
 unsigned int
 la_version (unsigned int v)
@@ -162,6 +164,24 @@ la_symbind64 (Elf64_Sym *sym, unsigned i
 # define La_regs La_ia64_regs
 # define La_retval La_ia64_retval
 # define int_retval lrv_r8
+#elif defined __mips__ && _MIPS_SIM == _ABIO32
+# define pltenter la_mips_o32_gnu_pltenter
+# define pltexit la_mips_o32_gnu_pltexit
+# define La_regs La_mips_32_regs
+# define La_retval La_mips_32_retval
+# define int_retval lrv_v0
+#elif defined __mips__ && _MIPS_SIM == _ABIN32
+# define pltenter la_mips_n32_gnu_pltenter
+# define pltexit la_mips_n32_gnu_pltexit
+# define La_regs La_mips_64_regs
+# define La_retval La_mips_64_retval
+# define int_retval lrv_v0
+#elif defined __mips__ && _MIPS_SIM == _ABIN64
+# define pltenter la_mips_n64_gnu_pltenter
+# define pltexit la_mips_n64_gnu_pltexit
+# define La_regs La_mips_64_regs
+# define La_retval La_mips_64_retval
+# define int_retval lrv_v0
 #else
 # error "architecture specific code needed"
 #endif
Index: linuxthreads/descr.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/descr.h,v
retrieving revision 1.14
diff -u -p -r1.14 descr.h
--- linuxthreads/descr.h	17 Sep 2003 09:39:00 -0000	1.14
+++ linuxthreads/descr.h	9 Feb 2005 22:24:56 -0000
@@ -239,9 +239,9 @@ extern int __pthread_nonstandard_stacks;
 
 /* Recover thread descriptor for the current thread */
 
-extern pthread_descr __pthread_find_self (void) __attribute__ ((const));
+extern pthread_descr __pthread_find_self (void) __attribute__ ((pure));
 
-static inline pthread_descr thread_self (void) __attribute__ ((const));
+static inline pthread_descr thread_self (void) __attribute__ ((pure));
 static inline pthread_descr thread_self (void)
 {
 #ifdef THREAD_SELF
Index: sysdeps/generic/ldsodefs.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/generic/ldsodefs.h,v
retrieving revision 1.115
diff -u -p -r1.115 ldsodefs.h
--- sysdeps/generic/ldsodefs.h	29 Jan 2005 04:11:24 -0000	1.115
+++ sysdeps/generic/ldsodefs.h	9 Feb 2005 22:24:59 -0000
@@ -195,6 +195,10 @@ struct La_s390_64_regs;
 struct La_s390_64_retval;
 struct La_ia64_regs;
 struct La_ia64_retval;
+struct La_mips_32_regs;
+struct La_mips_32_retval;
+struct La_mips_64_regs;
+struct La_mips_64_retval;
 
 struct audit_ifaces
 {
@@ -251,6 +255,18 @@ struct audit_ifaces
 				     uintptr_t *, struct La_ia64_regs *,
 				     unsigned int *, const char *name,
 				     long int *framesizep);
+    uintptr_t (*mips_o32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+					uintptr_t *, const struct La_mips_32_regs *,
+					unsigned int *, const char *name,
+					long int *framesizep);
+    uintptr_t (*mips_n32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+					uintptr_t *, const struct La_mips_64_regs *,
+					unsigned int *, const char *name,
+					long int *framesizep);
+    uintptr_t (*mips_n64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+					uintptr_t *, const struct La_mips_64_regs *,
+					unsigned int *, const char *name,
+					long int *framesizep);
   };
   union
   {
@@ -294,6 +310,15 @@ struct audit_ifaces
 				      uintptr_t *,
 				      const struct La_ia64_regs *,
 				      struct La_ia64_retval *, const char *);
+    unsigned int (*mips_o32_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+					  uintptr_t *, const struct La_mips_32_regs *,
+					  struct La_mips_32_retval *, const char *);
+    unsigned int (*mips_n32_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+					  uintptr_t *, const struct La_mips_64_regs *,
+					  struct La_mips_64_retval *, const char *);
+    unsigned int (*mips_n64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+					  uintptr_t *, const struct La_mips_64_regs *,
+					  struct La_mips_64_retval *, const char *);
   };
   unsigned int (*objclose) (uintptr_t *);
 
Index: sysdeps/mips/dl-machine.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/mips/dl-machine.h,v
retrieving revision 1.77
diff -u -p -r1.77 dl-machine.h
--- sysdeps/mips/dl-machine.h	24 Nov 2004 04:36:09 -0000	1.77
+++ sysdeps/mips/dl-machine.h	9 Feb 2005 22:25:01 -0000
@@ -188,248 +188,6 @@ do {									\
 } while(0)
 
 
-/* Get link map for callers object containing STUB_PC.  */
-static inline struct link_map *
-elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
-{
-  extern int _dl_mips_gnu_objects;
-
-  /* got[1] is reserved to keep its link map address for the shared
-     object generated by the gnu linker.  If all are such objects, we
-     can find the link map from current GPREG simply.  If not so, get
-     the link map for caller's object containing STUB_PC.  */
-
-  if (_dl_mips_gnu_objects)
-    {
-      ElfW(Addr) *got = elf_mips_got_from_gpreg (gpreg);
-      ElfW(Word) g1;
-
-      g1 = ((ElfW(Word) *) got)[1];
-
-      if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
-	{
-	  struct link_map *l =
-	    (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
-	  ElfW(Addr) base, limit;
-	  const ElfW(Phdr) *p = l->l_phdr;
-	  ElfW(Half) this, nent = l->l_phnum;
-
-	  /* For the common case of a stub being called from the containing
-	     object, STUB_PC will point to somewhere within the object that
-	     is described by the link map fetched via got[1].  Otherwise we
-	     have to scan all maps.  */
-	  for (this = 0; this < nent; this++)
-	    {
-	      if (p[this].p_type == PT_LOAD)
-		{
-		  base = p[this].p_vaddr + l->l_addr;
-		  limit = base + p[this].p_memsz;
-		  if (stub_pc >= base && stub_pc < limit)
-		    return l;
-		}
-	    }
-	}
-    }
-
-    struct link_map *l;
-    Lmid_t nsid;
-
-    for (nsid = 0; nsid < DL_NNS; ++nsid)
-      for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
-	{
-	  ElfW(Addr) base, limit;
-	  const ElfW(Phdr) *p = l->l_phdr;
-	  ElfW(Half) this, nent = l->l_phnum;
-
-	  for (this = 0; this < nent; ++this)
-	    {
-	      if (p[this].p_type == PT_LOAD)
-		{
-		  base = p[this].p_vaddr + l->l_addr;
-		  limit = base + p[this].p_memsz;
-		  if (stub_pc >= base && stub_pc < limit)
-		    return l;
-		}
-	    }
-	}
-
-  _dl_signal_error (0, NULL, NULL, "cannot find runtime link map");
-  return NULL;
-}
-
-#if _MIPS_SIM == _ABIO32
-#define ELF_DL_FRAME_SIZE 40
-
-#define ELF_DL_SAVE_ARG_REGS "\
-	sw	$15, 36($29)\n						      \
-	sw	$4, 16($29)\n						      \
-	sw	$5, 20($29)\n						      \
-	sw	$6, 24($29)\n						      \
-	sw	$7, 28($29)\n						      \
-"
-
-#define ELF_DL_RESTORE_ARG_REGS "\
-	lw	$31, 36($29)\n						      \
-	lw	$4, 16($29)\n						      \
-	lw	$5, 20($29)\n						      \
-	lw	$6, 24($29)\n						      \
-	lw	$7, 28($29)\n						      \
-"
-
-#define IFABIO32(X) X
-
-#else /* _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 */
-
-#define ELF_DL_FRAME_SIZE 80
-
-#define ELF_DL_SAVE_ARG_REGS "\
-	sd	$15, 72($29)\n						      \
-	sd	$4, 8($29)\n						      \
-	sd	$5, 16($29)\n						      \
-	sd	$6, 24($29)\n						      \
-	sd	$7, 32($29)\n						      \
-	sd	$8, 40($29)\n						      \
-	sd	$9, 48($29)\n						      \
-	sd	$10, 56($29)\n						      \
-	sd	$11, 64($29)\n						      \
-"
-
-#define ELF_DL_RESTORE_ARG_REGS "\
-	ld	$31, 72($29)\n						      \
-	ld	$4, 8($29)\n						      \
-	ld	$5, 16($29)\n						      \
-	ld	$6, 24($29)\n						      \
-	ld	$7, 32($29)\n						      \
-	ld	$8, 40($29)\n						      \
-	ld	$9, 48($29)\n						      \
-	ld	$10, 56($29)\n						      \
-	ld	$11, 64($29)\n						      \
-"
-
-#define IFABIO32(X)
-
-#endif
-
-/* Define mips specific runtime resolver. The function __dl_runtime_resolve
-   is called from assembler function _dl_runtime_resolve which converts
-   special argument registers t7 ($15) and t8 ($24):
-     t7  address to return to the caller of the function
-     t8  index for this function symbol in .dynsym
-   to usual c arguments.
-
-   Other architectures call fixup from dl-runtime.c in
-   _dl_runtime_resolve.  MIPS instead calls __dl_runtime_resolve.  We
-   have to use our own version because of the way the got section is
-   treated on MIPS (we've also got ELF_MACHINE_PLT defined).  */
-
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE					      \
-/* The flag _dl_mips_gnu_objects is set if all dynamic objects are	      \
-   generated by the gnu linker. */					      \
-int _dl_mips_gnu_objects = 1;						      \
-									      \
-/* This is called from assembly stubs below which the compiler can't see.  */ \
-static ElfW(Addr)							      \
-__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr))	      \
-		  __attribute_used__;					      \
-									      \
-static ElfW(Addr)							      \
-__dl_runtime_resolve (ElfW(Word) sym_index,				      \
-		      ElfW(Word) return_address,			      \
-		      ElfW(Addr) old_gpreg,				      \
-		      ElfW(Addr) stub_pc)				      \
-{									      \
-  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);     \
-  const ElfW(Sym) *const symtab						      \
-    = (const ElfW(Sym) *) D_PTR (l, l_info[DT_SYMTAB]);			      \
-  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);	      \
-  ElfW(Addr) *got							      \
-    = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);			      \
-  const ElfW(Word) local_gotno						      \
-    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;	      \
-  const ElfW(Word) gotsym						      \
-    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;	      \
-  const ElfW(Sym) *sym = &symtab[sym_index];				      \
-  ElfW(Addr) value;							      \
-									      \
-  /* FIXME: The symbol versioning stuff is not tested yet.  */		      \
-  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)	      \
-    {									      \
-      switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)			      \
-	{								      \
-	default:							      \
-	  {								      \
-	    const ElfW(Half) *vernum =					      \
-	      (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);	      \
-	    ElfW(Half) ndx = vernum[sym_index] & 0x7fff;		      \
-	    const struct r_found_version *version = &l->l_versions[ndx];      \
-									      \
-	    if (version->hash != 0)					      \
-	      {								      \
-		value = _dl_lookup_symbol_x (strtab + sym->st_name, l, 	      \
-					     &sym, l->l_scope, version,	      \
-					     ELF_RTYPE_CLASS_PLT, 0, 0);      \
-		break;							      \
-	      }								      \
-	    /* Fall through.  */					      \
-	  }								      \
-	case 0:								      \
-	  value = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,	      \
-				       l->l_scope, 0, ELF_RTYPE_CLASS_PLT,    \
-				       DL_LOOKUP_ADD_DEPENDENCY, 0);	      \
-	}								      \
-									      \
-      /* Currently value contains the base load address of the object	      \
-	 that defines sym.  Now add in the symbol offset.  */		      \
-      value = (sym ? value + sym->st_value : 0);			      \
-    }									      \
-  else									      \
-    /* We already found the symbol.  The module (and therefore its load	      \
-       address) is also known.  */					      \
-    value = l->l_addr + sym->st_value;					      \
-									      \
-  /* Apply the relocation with that value.  */				      \
-  *(got + local_gotno + sym_index - gotsym) = value;			      \
-									      \
-  return value;								      \
-}									      \
-									      \
-asm ("\n								      \
-	.text\n								      \
-	.align	2\n							      \
-	.globl	_dl_runtime_resolve\n					      \
-	.type	_dl_runtime_resolve,@function\n				      \
-	.ent	_dl_runtime_resolve\n					      \
-_dl_runtime_resolve:\n							      \
-	.frame	$29, " STRINGXP(ELF_DL_FRAME_SIZE) ", $31\n		      \
-	.set noreorder\n						      \
-	# Save GP.\n							      \
-	move	$3, $28\n						      \
-	# Save arguments and sp value in stack.\n			      \
-	" STRINGXP(PTR_SUBIU) "  $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n	      \
-	# Modify t9 ($25) so as to point .cpload instruction.\n		      \
-	" IFABIO32(STRINGXP(PTR_ADDIU) "	$25, 12\n") "		      \
-	# Compute GP.\n							      \
-	" STRINGXP(SETUP_GP) "\n					      \
-	" STRINGXV(SETUP_GP64 (0, _dl_runtime_resolve)) "\n		      \
-	.set reorder\n							      \
-	# Save slot call pc.\n						      \
-	move	$2, $31\n						      \
-	" IFABIO32(STRINGXP(CPRESTORE(32))) "\n				      \
-	" ELF_DL_SAVE_ARG_REGS "					      \
-	move	$4, $24\n						      \
-	move	$5, $15\n						      \
-	move	$6, $3\n						      \
-	move	$7, $2\n						      \
-	jal	__dl_runtime_resolve\n					      \
-	" ELF_DL_RESTORE_ARG_REGS "					      \
-	" STRINGXP(RESTORE_GP64) "\n					      \
-	" STRINGXP(PTR_ADDIU) "	$29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n	      \
-	move	$25, $2\n						      \
-	jr	$25\n							      \
-	.end	_dl_runtime_resolve\n					      \
-	.previous\n							      \
-");
-
 /* Mask identifying addresses reserved for the user program,
    where the dynamic linker should not map anything.  */
 #define ELF_MACHINE_USER_ADDRESS_MASK	0x80000000UL
@@ -451,8 +209,8 @@ _dl_runtime_resolve:\n							      \
       and not just plain _start.  */
 
 #define RTLD_START asm (\
-	".text\n"\
-	_RTLD_PROLOGUE(ENTRY_POINT) "\
+	".text\n\
+	" _RTLD_PROLOGUE(ENTRY_POINT) "\
 	" STRINGXV(SETUP_GPX($25)) "\n\
 	" STRINGXV(SETUP_GPX64($18,$25)) "\n\
 	# i386 ABI book says that the first entry of GOT holds\n\
@@ -475,10 +233,10 @@ _dl_runtime_resolve:\n							      \
 	" STRINGXP(PTR_ADDIU) " $29, 16\n\
 	# Get the value of label '_dl_start_user' in t9 ($25).\n\
 	" STRINGXP(PTR_LA) " $25, _dl_start_user\n\
-	.globl _dl_start_user\n\
-	.type _dl_start_user,@function\n\
-	.aent _dl_start_user\n\
-_dl_start_user:\n\
+	" _RTLD_EPILOGUE(ENTRY_POINT) "\
+	\n\
+	\n\
+	" _RTLD_PROLOGUE(_dl_start_user) "\
 	" STRINGXP(SETUP_GP) "\n\
 	" STRINGXV(SETUP_GP64($18,_dl_start_user)) "\n\
 	move $16, $28\n\
@@ -504,34 +262,48 @@ _dl_start_user:\n\
 	sll $7, $5, " STRINGXP (PTRLOG) "\n\
 	" STRINGXP(PTR_ADDU) " $7, $7, $6\n\
 	" STRINGXP(PTR_ADDU) " $7, $7, " STRINGXP (PTRSIZE) " \n\
-	" STRINGXP(PTR_SUBIU) " $29, 32\n\
+	# Make sure the stack pointer is aligned for _dl_init_internal.\n\
+	and $2, $29, -2 * " STRINGXP(SZREG) "\n\
+	" STRINGXP(PTR_S) " $29, -4($2)\n\
+	" STRINGXP(PTR_SUBIU) " $29, $2, 32\n\
 	" STRINGXP(SAVE_GP(16)) "\n\
 	# Call the function to run the initializers.\n\
 	jal _dl_init_internal\n\
-	" STRINGXP(PTR_ADDIU)  " $29, 32\n\
+	# Restore the stack pointer for _start.\n\
+	" STRINGXP(PTR_L)  " $29, 28($29)\n\
 	# Pass our finalizer function to the user in $2 as per ELF ABI.\n\
 	" STRINGXP(PTR_LA) " $2, _dl_fini\n\
 	# Jump to the user entry point.\n\
 	move $25, $17\n\
 	jr $25\n\t"\
-	_RTLD_EPILOGUE(ENTRY_POINT)\
+	_RTLD_EPILOGUE(_dl_start_user)\
 	".previous"\
 );
 
 /* The MIPS never uses Elfxx_Rela relocations.  */
 #define ELF_MACHINE_NO_RELA 1
 
+/* Names of the architecture-specific auditing callback functions.  */
+# if _MIPS_SIM == _ABIO32
+#  define ARCH_LA_PLTENTER mips_o32_gnu_pltenter
+#  define ARCH_LA_PLTEXIT mips_o32_gnu_pltexit
+# elif _MIPS_SIM == _ABIN32
+#  define ARCH_LA_PLTENTER mips_n32_gnu_pltenter
+#  define ARCH_LA_PLTEXIT mips_n32_gnu_pltexit
+# else
+#  define ARCH_LA_PLTENTER mips_n64_gnu_pltenter
+#  define ARCH_LA_PLTEXIT mips_n64_gnu_pltexit
+# endif
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-static inline void
-#ifdef RTLD_BOOTSTRAP
-  __attribute__ ((always_inline))
-#endif
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
 		 const ElfW(Sym) *sym, const struct r_found_version *version,
 		 void *const reloc_addr)
@@ -635,14 +407,16 @@ elf_machine_rel (struct link_map *map, c
     }
 }
 
-static inline void
+auto inline void
+__attribute__((always_inline))
 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
 			  void *const reloc_addr)
 {
   /* XXX Nothing to do.  There is no relative relocation, right?  */
 }
 
-static inline void
+auto inline void
+__attribute__((always_inline))
 elf_machine_lazy_rel (struct link_map *map,
 		      ElfW(Addr) l_addr, const ElfW(Rel) *reloc)
 {
@@ -651,7 +425,8 @@ elf_machine_lazy_rel (struct link_map *m
 
 #ifndef RTLD_BOOTSTRAP
 /* Relocate GOT. */
-static inline void
+auto inline void
+__attribute__((always_inline))
 elf_machine_got_rel (struct link_map *map, int lazy)
 {
   ElfW(Addr) *got;
@@ -664,9 +439,9 @@ elf_machine_got_rel (struct link_map *ma
       const ElfW(Sym) *ref = sym;					  \
       const struct r_found_version *version				  \
         = vernum ? &map->l_versions[vernum[sym_index] & 0x7fff] : NULL;	  \
-      ElfW(Addr) value;							  \
-      value = RESOLVE (&ref, version, R_MIPS_REL32);			  \
-      (ref)? value + ref->st_value: 0;					  \
+      struct link_map *sym_map;						  \
+      sym_map = RESOLVE_MAP (&ref, version, R_MIPS_REL32);		  \
+      ref ? sym_map->l_addr + ref->st_value : 0;			  \
     })
 
   if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
@@ -738,7 +513,8 @@ elf_machine_got_rel (struct link_map *ma
 /* Set up the loaded object described by L so its stub function
    will jump to the on-demand fixup code __dl_runtime_resolve.  */
 
-static inline int
+auto inline int
+__attribute__((always_inline))
 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
 # ifndef RTLD_BOOTSTRAP
@@ -774,4 +550,4 @@ elf_machine_runtime_setup (struct link_m
   return lazy;
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
Index: sysdeps/mips/dl-trampoline.c
===================================================================
RCS file: sysdeps/mips/dl-trampoline.c
diff -N sysdeps/mips/dl-trampoline.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sysdeps/mips/dl-trampoline.c	9 Feb 2005 22:25:01 -0000
@@ -0,0 +1,273 @@
+/* PLT trampoline.  MIPS version.
+   Copyright (C) 1996-2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/*  FIXME: Profiling of shared libraries is not implemented yet.  */
+
+#include <sgidefs.h>
+#include <sysdep.h>
+#include <link.h>
+#include <elf.h>
+#include <ldsodefs.h>
+#include <dl-machine.h>
+
+/* Get link map for callers object containing STUB_PC.  */
+static inline struct link_map *
+elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
+{
+  extern int _dl_mips_gnu_objects;
+
+  /* got[1] is reserved to keep its link map address for the shared
+     object generated by the gnu linker.  If all are such objects, we
+     can find the link map from current GPREG simply.  If not so, get
+     the link map for caller's object containing STUB_PC.  */
+
+  if (_dl_mips_gnu_objects)
+    {
+      ElfW(Addr) *got = elf_mips_got_from_gpreg (gpreg);
+      ElfW(Word) g1;
+
+      g1 = ((ElfW(Word) *) got)[1];
+
+      if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
+	{
+	  struct link_map *l =
+	    (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
+	  ElfW(Addr) base, limit;
+	  const ElfW(Phdr) *p = l->l_phdr;
+	  ElfW(Half) this, nent = l->l_phnum;
+
+	  /* For the common case of a stub being called from the containing
+	     object, STUB_PC will point to somewhere within the object that
+	     is described by the link map fetched via got[1].  Otherwise we
+	     have to scan all maps.  */
+	  for (this = 0; this < nent; this++)
+	    {
+	      if (p[this].p_type == PT_LOAD)
+		{
+		  base = p[this].p_vaddr + l->l_addr;
+		  limit = base + p[this].p_memsz;
+		  if (stub_pc >= base && stub_pc < limit)
+		    return l;
+		}
+	    }
+	}
+    }
+
+    struct link_map *l;
+    Lmid_t nsid;
+
+    for (nsid = 0; nsid < DL_NNS; ++nsid)
+      for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+	{
+	  ElfW(Addr) base, limit;
+	  const ElfW(Phdr) *p = l->l_phdr;
+	  ElfW(Half) this, nent = l->l_phnum;
+
+	  for (this = 0; this < nent; ++this)
+	    {
+	      if (p[this].p_type == PT_LOAD)
+		{
+		  base = p[this].p_vaddr + l->l_addr;
+		  limit = base + p[this].p_memsz;
+		  if (stub_pc >= base && stub_pc < limit)
+		    return l;
+		}
+	    }
+	}
+
+  _dl_signal_error (0, NULL, NULL, "cannot find runtime link map");
+  return NULL;
+}
+
+/* Define mips specific runtime resolver. The function __dl_runtime_resolve
+   is called from assembler function _dl_runtime_resolve which converts
+   special argument registers t7 ($15) and t8 ($24):
+     t7  address to return to the caller of the function
+     t8  index for this function symbol in .dynsym
+   to usual c arguments.
+
+   Other architectures call fixup from dl-runtime.c in
+   _dl_runtime_resolve.  MIPS instead calls __dl_runtime_resolve.  We
+   have to use our own version because of the way the got section is
+   treated on MIPS (we've also got ELF_MACHINE_PLT defined).  */
+
+/* The flag _dl_mips_gnu_objects is set if all dynamic objects are
+   generated by the gnu linker. */
+int _dl_mips_gnu_objects = 1;
+
+#define VERSYMIDX(sym)  (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
+
+/* This is called from assembly stubs below which the compiler can't see.  */
+static ElfW(Addr)
+__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr))
+		  __attribute_used__;
+
+static ElfW(Addr)
+__dl_runtime_resolve (ElfW(Word) sym_index,
+		      ElfW(Word) return_address,
+		      ElfW(Addr) old_gpreg,
+		      ElfW(Addr) stub_pc)
+{
+  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);
+  const ElfW(Sym) *const symtab
+    = (const ElfW(Sym) *) D_PTR (l, l_info[DT_SYMTAB]);
+  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
+  ElfW(Addr) *got
+    = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+  const ElfW(Word) local_gotno
+    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
+  const ElfW(Word) gotsym
+    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
+  const ElfW(Sym) *sym = &symtab[sym_index];
+  struct link_map *sym_map;
+  ElfW(Addr) value;
+
+  /* FIXME: The symbol versioning stuff is not tested yet.  */
+  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
+    {
+      switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+	{
+	default:
+	  {
+	    const ElfW(Half) *vernum =
+	      (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
+	    ElfW(Half) ndx = vernum[sym_index] & 0x7fff;
+	    const struct r_found_version *version = &l->l_versions[ndx];
+
+	    if (version->hash != 0)
+	      {
+		sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l, 
+					       &sym, l->l_scope, version,
+					       ELF_RTYPE_CLASS_PLT, 0, 0);
+		break;
+	      }
+	    /* Fall through.  */
+	  }
+	case 0:
+	  sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+					 l->l_scope, 0, ELF_RTYPE_CLASS_PLT,
+					 DL_LOOKUP_ADD_DEPENDENCY, 0);
+	}
+
+      /* Currently value contains the base load address of the object
+	 that defines sym.  Now add in the symbol offset.  */
+      value = (sym ? sym_map->l_addr + sym->st_value : 0);
+    }
+  else
+    /* We already found the symbol.  The module (and therefore its load
+       address) is also known.  */
+    value = l->l_addr + sym->st_value;
+
+  /* Apply the relocation with that value.  */
+  *(got + local_gotno + sym_index - gotsym) = value;
+
+  return value;
+}
+
+#if _MIPS_SIM == _ABIO32
+#define ELF_DL_FRAME_SIZE 40
+
+#define ELF_DL_SAVE_ARG_REGS "\
+	sw	$15, 36($29)\n						      \
+	sw	$4, 16($29)\n						      \
+	sw	$5, 20($29)\n						      \
+	sw	$6, 24($29)\n						      \
+	sw	$7, 28($29)\n						      \
+"
+
+#define ELF_DL_RESTORE_ARG_REGS "\
+	lw	$31, 36($29)\n						      \
+	lw	$4, 16($29)\n						      \
+	lw	$5, 20($29)\n						      \
+	lw	$6, 24($29)\n						      \
+	lw	$7, 28($29)\n						      \
+"
+
+#define IFABIO32(X) X
+
+#else /* _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 */
+
+#define ELF_DL_FRAME_SIZE 80
+
+#define ELF_DL_SAVE_ARG_REGS "\
+	sd	$15, 72($29)\n						      \
+	sd	$4, 8($29)\n						      \
+	sd	$5, 16($29)\n						      \
+	sd	$6, 24($29)\n						      \
+	sd	$7, 32($29)\n						      \
+	sd	$8, 40($29)\n						      \
+	sd	$9, 48($29)\n						      \
+	sd	$10, 56($29)\n						      \
+	sd	$11, 64($29)\n						      \
+"
+
+#define ELF_DL_RESTORE_ARG_REGS "\
+	ld	$31, 72($29)\n						      \
+	ld	$4, 8($29)\n						      \
+	ld	$5, 16($29)\n						      \
+	ld	$6, 24($29)\n						      \
+	ld	$7, 32($29)\n						      \
+	ld	$8, 40($29)\n						      \
+	ld	$9, 48($29)\n						      \
+	ld	$10, 56($29)\n						      \
+	ld	$11, 64($29)\n						      \
+"
+
+#define IFABIO32(X)
+
+#endif
+
+asm ("\n\
+	.text\n\
+	.align	2\n\
+	.globl	_dl_runtime_resolve\n\
+	.type	_dl_runtime_resolve,@function\n\
+	.ent	_dl_runtime_resolve\n\
+_dl_runtime_resolve:\n\
+	.frame	$29, " STRINGXP(ELF_DL_FRAME_SIZE) ", $31\n\
+	.set noreorder\n\
+	# Save GP.\n\
+	move	$3, $28\n\
+	# Save arguments and sp value in stack.\n\
+	" STRINGXP(PTR_SUBIU) "  $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\
+	# Modify t9 ($25) so as to point .cpload instruction.\n\
+	" IFABIO32(STRINGXP(PTR_ADDIU) "	$25, 12\n") "\
+	# Compute GP.\n\
+	" STRINGXP(SETUP_GP) "\n\
+	" STRINGXV(SETUP_GP64 (0, _dl_runtime_resolve)) "\n\
+	.set reorder\n\
+	# Save slot call pc.\n\
+	move	$2, $31\n\
+	" IFABIO32(STRINGXP(CPRESTORE(32))) "\n\
+	" ELF_DL_SAVE_ARG_REGS "\
+	move	$4, $24\n\
+	move	$5, $15\n\
+	move	$6, $3\n\
+	move	$7, $2\n\
+	jal	__dl_runtime_resolve\n\
+	" ELF_DL_RESTORE_ARG_REGS "\
+	" STRINGXP(RESTORE_GP64) "\n\
+	" STRINGXP(PTR_ADDIU) "	$29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\
+	move	$25, $2\n\
+	jr	$25\n\
+	.end	_dl_runtime_resolve\n\
+	.previous\n\
+");
Index: sysdeps/mips/bits/link.h
===================================================================
RCS file: sysdeps/mips/bits/link.h
diff -N sysdeps/mips/bits/link.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sysdeps/mips/bits/link.h	9 Feb 2005 22:25:01 -0000
@@ -0,0 +1,118 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+#include <sgidefs.h>
+
+#if _MIPS_SIM == _ABIO32
+
+/* Registers for entry into PLT on MIPS.  */
+typedef struct La_mips_32_regs
+{
+  uint32_t lr_reg[4]; /* $a0 through $a3 */
+  double lr_fpreg[2]; /* $f12 and $f14 */
+  uint32_t lr_ra;
+  uint32_t lr_sp;
+} La_mips_32_regs;
+
+/* Return values for calls from PLT on MIPS.  */
+typedef struct La_mips_32_retval
+{
+  uint32_t lrv_v0;
+  uint32_t lrv_v1;
+  double lrv_f0;
+  double lrv_f2;
+} La_mips_32_retval;
+
+#else
+
+typedef struct La_mips_64_regs
+{
+  uint64_t lr_reg[8]; /* $a0 through $a7 */
+  double lr_fpreg[8]; /* $f12 throgh $f19 */
+  uint64_t lr_ra;
+  uint64_t lr_sp;
+} La_mips_64_regs;
+
+/* Return values for calls from PLT on MIPS.  */
+typedef struct La_mips_64_retval
+{
+  uint64_t lrv_v0;
+  uint64_t lrv_v1;
+  double lrv_f0;
+  double lrv_f2;
+} La_mips_64_retval;
+
+#endif
+
+__BEGIN_DECLS
+
+#if _MIPS_SIM == _ABIO32
+
+extern Elf32_Addr la_mips_o32_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    La_mips_32_regs *__regs,
+					    unsigned int *__flags,
+					    const char *__symname,
+					    long int *__framesizep);
+extern unsigned int la_mips_o32_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+					     uintptr_t *__refcook,
+					     uintptr_t *__defcook,
+					     const La_mips_32_regs *__inregs,
+					     La_mips_32_retval *__outregs,
+					     const char *symname);
+
+#elif _MIPS_SIM == _ABIN32
+
+extern Elf32_Addr la_mips_n32_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    La_mips_64_regs *__regs,
+					    unsigned int *__flags,
+					    const char *__symname,
+					    long int *__framesizep);
+extern unsigned int la_mips_n32_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+					     uintptr_t *__refcook,
+					     uintptr_t *__defcook,
+					     const La_mips_64_regs *__inregs,
+					     La_mips_64_retval *__outregs,
+					     const char *symname);
+
+#else
+
+extern Elf64_Addr la_mips_n64_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    La_mips_64_regs *__regs,
+					    unsigned int *__flags,
+					    const char *__symname,
+					    long int *__framesizep);
+extern unsigned int la_mips_n64_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+					     uintptr_t *__refcook,
+					     uintptr_t *__defcook,
+					     const La_mips_64_regs *__inregs,
+					     La_mips_64_retval *__outregs,
+					     const char *symname);
+
+#endif
+
+__END_DECLS
Index: sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h,v
retrieving revision 1.2
diff -u -p -r1.2 sysdep.h
--- sysdeps/unix/sysv/linux/mips/mips32/sysdep.h	18 Oct 2004 05:16:06 -0000	1.2
+++ sysdeps/unix/sysv/linux/mips/mips32/sysdep.h	9 Feb 2005 22:25:02 -0000
@@ -194,16 +194,15 @@
 	register long __a3 asm("$7") = (long) arg4; 			\
 	__asm__ volatile ( 						\
 	".set\tnoreorder\n\t" 						\
-	"lw\t$2, %6\n\t" 						\
 	"subu\t$29, 32\n\t" 						\
-	"sw\t$2, 16($29)\n\t" 						\
+	"sw\t%6, 16($29)\n\t" 						\
 	"li\t$2, %5\t\t\t# " #name "\n\t" 				\
 	"syscall\n\t" 							\
 	"addiu\t$29, 32\n\t" 						\
 	".set\treorder" 						\
 	: "=r" (__v0), "+r" (__a3) 					\
 	: "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), 	\
-	  "m" ((long)arg5) 						\
+	  "r" ((long)arg5) 						\
 	: __SYSCALL_CLOBBERS); 						\
 	err = __a3;							\
 	_sys_result = __v0;						\
@@ -223,18 +222,16 @@
 	register long __a3 asm("$7") = (long) arg4; 			\
 	__asm__ volatile ( 						\
 	".set\tnoreorder\n\t" 						\
-	"lw\t$2, %6\n\t" 						\
-	"lw\t$8, %7\n\t" 						\
 	"subu\t$29, 32\n\t" 						\
-	"sw\t$2, 16($29)\n\t" 						\
-	"sw\t$8, 20($29)\n\t" 						\
+	"sw\t%6, 16($29)\n\t" 						\
+	"sw\t%7, 20($29)\n\t" 						\
 	"li\t$2, %5\t\t\t# " #name "\n\t" 				\
 	"syscall\n\t" 							\
 	"addiu\t$29, 32\n\t" 						\
 	".set\treorder" 						\
 	: "=r" (__v0), "+r" (__a3) 					\
 	: "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), 	\
-	  "m" ((long)arg5), "m" ((long)arg6)				\
+	  "r" ((long)arg5), "r" ((long)arg6)				\
 	: __SYSCALL_CLOBBERS); 						\
 	err = __a3;							\
 	_sys_result = __v0;						\
@@ -254,20 +251,17 @@
 	register long __a3 asm("$7") = (long) arg4; 			\
 	__asm__ volatile ( 						\
 	".set\tnoreorder\n\t" 						\
-	"lw\t$2, %6\n\t" 						\
-	"lw\t$8, %7\n\t" 						\
-	"lw\t$9, %8\n\t" 						\
 	"subu\t$29, 32\n\t" 						\
-	"sw\t$2, 16($29)\n\t" 						\
-	"sw\t$8, 20($29)\n\t" 						\
-	"sw\t$9, 24($29)\n\t" 						\
+	"sw\t%6, 16($29)\n\t" 						\
+	"sw\t%7, 20($29)\n\t" 						\
+	"sw\t%8, 24($29)\n\t" 						\
 	"li\t$2, %5\t\t\t# " #name "\n\t" 				\
 	"syscall\n\t" 							\
 	"addiu\t$29, 32\n\t" 						\
 	".set\treorder" 						\
 	: "=r" (__v0), "+r" (__a3) 					\
 	: "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), 	\
-	  "m" ((long)arg5), "m" ((long)arg6), "m" ((long)arg7)		\
+	  "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7)		\
 	: __SYSCALL_CLOBBERS); 						\
 	err = __a3;							\
 	_sys_result = __v0;						\


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