summary refs log tree commit diff
path: root/sysdeps/mips/dl-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mips/dl-machine.h')
-rw-r--r--sysdeps/mips/dl-machine.h319
1 files changed, 55 insertions, 264 deletions
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index 0d87b65691..a8a41fff02 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -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,23 +407,41 @@ elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
     }
 }
 
-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)
 {
   /* Do nothing.  */
 }
 
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
+		  const ElfW(Sym) *sym, const struct r_found_version *version,
+		 void *const reloc_addr)
+{
+}
+
+auto inline void
+__attribute__((always_inline))
+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+			   void *const reloc_addr)
+{
+}
+
 #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 +454,9 @@ elf_machine_got_rel (struct link_map *map, int lazy)
       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 +528,8 @@ elf_machine_got_rel (struct link_map *map, int lazy)
 /* 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 +565,4 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */