about summary refs log tree commit diff
path: root/sysdeps/powerpc/powerpc64/dl-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc/powerpc64/dl-machine.h')
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h121
1 files changed, 100 insertions, 21 deletions
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index cec271bb3a..3fcf77df71 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -1,6 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.
    PowerPC64 version.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -107,6 +107,92 @@ elf_machine_dynamic (void)
 /* The PLT uses Elf64_Rela relocs.  */
 #define elf_machine_relplt elf_machine_rela
 
+/* This code gets called via a .glink stub which loads PLT0.  It is
+   used in dl-runtime.c to call the `fixup' function and then redirect
+   to the address `fixup' returns.
+
+   Enter with r0 = plt reloc index,
+   r2 = ld.so tocbase,
+   r11 = ld.so link map.  */
+
+#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
+  asm (".section \".text\"\n"						\
+"	.align	2\n"							\
+"	.type	" BODY_PREFIX #tramp_name ",@function\n"		\
+"	.section \".opd\",\"aw\"\n"					\
+"	.align	3\n"							\
+"	.globl	" #tramp_name "\n"					\
+"	" ENTRY_2(tramp_name) "\n"					\
+#tramp_name ":\n"							\
+"	" OPD_ENT(tramp_name) "\n"					\
+"	.previous\n"							\
+BODY_PREFIX #tramp_name ":\n"						\
+/* We need to save the registers used to pass parameters, ie. r3 thru	\
+   r10; the registers are saved in a stack frame.  */			\
+"	stdu	1,-128(1)\n"						\
+"	std	3,48(1)\n"						\
+"	mr	3,11\n"							\
+"	std	4,56(1)\n"						\
+"	sldi	4,0,1\n"						\
+"	std	5,64(1)\n"						\
+"	add	4,4,0\n"						\
+"	std	6,72(1)\n"						\
+"	sldi	4,4,3\n"						\
+"	std	7,80(1)\n"						\
+"	mflr	0\n"							\
+"	std	8,88(1)\n"						\
+/* Store the LR in the LR Save area of the previous frame.  */    	\
+"	std	0,128+16(1)\n"						\
+"	mfcr	0\n"							\
+"	std	9,96(1)\n"						\
+"	std	10,104(1)\n"						\
+/* I'm almost certain we don't have to save cr...  be safe.  */    	\
+"	std	0,8(1)\n"						\
+"	bl	" DOT_PREFIX #fixup_name "\n"				\
+/* Put the registers back.  */						\
+"	ld	0,128+16(1)\n"						\
+"	ld	10,104(1)\n"						\
+"	ld	9,96(1)\n"						\
+"	ld	8,88(1)\n"						\
+"	ld	7,80(1)\n"						\
+"	mtlr	0\n"							\
+"	ld	0,8(1)\n"						\
+"	ld	6,72(1)\n"						\
+"	ld	5,64(1)\n"						\
+"	ld	4,56(1)\n"						\
+"	mtcrf	0xFF,0\n"						\
+/* Load the target address, toc and static chain reg from the function  \
+   descriptor returned by fixup.  */					\
+"	ld	0,0(3)\n"						\
+"	ld	2,8(3)\n"						\
+"	mtctr	0\n"							\
+"	ld	11,16(3)\n"						\
+"	ld	3,48(1)\n"						\
+/* Unwind the stack frame, and jump.  */				\
+"	addi	1,1,128\n"						\
+"	bctr\n"								\
+".LT_" #tramp_name ":\n"						\
+"	.long 0\n"							\
+"	.byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"		\
+"	.long .LT_" #tramp_name "-" BODY_PREFIX #tramp_name "\n"	\
+"	.short .LT_" #tramp_name "_name_end-.LT_" #tramp_name "_name_start\n" \
+".LT_" #tramp_name "_name_start:\n"					\
+"	.ascii \"" #tramp_name "\"\n"					\
+".LT_" #tramp_name "_name_end:\n"					\
+"	.align 2\n"							\
+"	" END_2(tramp_name) "\n"					\
+"	.previous");
+
+#ifndef PROF
+#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
+  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
+  TRAMPOLINE_TEMPLATE (_dl_profile_resolve, profile_fixup);
+#else
+#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
+  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
+  void _dl_runtime_resolve (void);			\
+  strong_alias (_dl_runtime_resolve, _dl_profile_resolve);
+#endif
 
 #ifdef HAVE_INLINED_SYSCALLS
 /* We do not need _dl_starting_up.  */
@@ -122,16 +208,16 @@ elf_machine_dynamic (void)
    `_dl_start' is the real entry point; its return value is the user
    program's entry point.  */
 #define RTLD_START \
-  asm (".pushsection \".text\"\n"					\
+  asm (".section \".text\"\n"						\
 "	.align	2\n"							\
 "	.type	" BODY_PREFIX "_start,@function\n"			\
-"	.pushsection \".opd\",\"aw\"\n"					\
+"	.section \".opd\",\"aw\"\n"					\
 "	.align	3\n"							\
 "	.globl	_start\n"						\
 "	" ENTRY_2(_start) "\n"						\
 "_start:\n"								\
 "	" OPD_ENT(_start) "\n"						\
-"	.popsection\n"							\
+"	.previous\n"							\
 BODY_PREFIX "_start:\n"							\
 /* We start with the following on the stack, from top:			\
    argc (4 bytes);							\
@@ -157,11 +243,11 @@ BODY_PREFIX "_start:\n"							\
 "	.align 2\n"							\
 "	" END_2(_start) "\n"						\
 "	.globl	_dl_start_user\n"					\
-"	.pushsection \".opd\",\"aw\"\n"					\
+"	.section \".opd\",\"aw\"\n"					\
 "_dl_start_user:\n"							\
 "	" OPD_ENT(_dl_start_user) "\n"					\
-"	.popsection\n"							\
-"	.pushsection	\".toc\",\"aw\"\n"				\
+"	.previous\n"							\
+"	.section	\".toc\",\"aw\"\n"				\
 DL_STARTING_UP_DEF							\
 ".LC__rtld_global:\n"							\
 "	.tc _rtld_global[TC],_rtld_global\n"				\
@@ -171,7 +257,7 @@ DL_STARTING_UP_DEF							\
 "	.tc _dl_argv_internal[TC],_dl_argv_internal\n"			\
 ".LC__dl_fini:\n"							\
 "	.tc _dl_fini[TC],_dl_fini\n"					\
-"	.popsection\n"							\
+"	.previous\n"							\
 "	.type	" BODY_PREFIX "_dl_start_user,@function\n"		\
 "	" ENTRY_2(_dl_start_user) "\n"					\
 /* Now, we do our main work of calling initialisation procedures.	\
@@ -245,7 +331,7 @@ BODY_PREFIX "_dl_start_user:\n"						\
 ".LT__dl_start_user_name_end:\n"					\
 "	.align 2\n"							\
 "	" END_2(_dl_start_user) "\n"					\
-"	.popsection");
+"	.previous");
 
 /* Nonzero iff TYPE should not be allowed to resolve to one of
    the main executable's symbols, as for a COPY reloc.  */
@@ -334,8 +420,7 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 
 	  resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve
 					   : _dl_runtime_resolve);
-	  if (profile && GLRO(dl_profile) != NULL
-	      && _dl_name_match_p (GLRO(dl_profile), map))
+	  if (profile && _dl_name_match_p (GLRO(dl_profile), map))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = map;
@@ -460,11 +545,6 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
   return value + reloc->r_addend;
 }
 
-
-/* Names of the architecture-specific auditing callback functions.  */
-#define ARCH_LA_PLTENTER ppc64_gnu_pltenter
-#define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
-
 #endif /* dl_machine_h */
 
 #ifdef RESOLVE_MAP
@@ -487,7 +567,7 @@ extern void _dl_reloc_overflow (struct link_map *map,
                                 const Elf64_Sym *refsym)
                                 attribute_hidden;
 
-auto inline void __attribute__ ((always_inline))
+static inline void
 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
 			   void *const reloc_addr_arg)
 {
@@ -497,7 +577,7 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
 
 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
 /* This computes the value used by TPREL* relocs.  */
-auto inline Elf64_Addr __attribute__ ((always_inline, const))
+static Elf64_Addr __attribute__ ((const))
 elf_machine_tprel (struct link_map *map,
 		   struct link_map *sym_map,
 		   const Elf64_Sym *sym,
@@ -518,7 +598,7 @@ elf_machine_tprel (struct link_map *map,
 
 /* Perform the relocation specified by RELOC and SYM (which is fully
    resolved).  MAP is the object containing the reloc.  */
-auto inline void __attribute__ ((always_inline))
+static inline void
 elf_machine_rela (struct link_map *map,
 		  const Elf64_Rela *reloc,
 		  const Elf64_Sym *sym,
@@ -803,12 +883,11 @@ elf_machine_rela (struct link_map *map,
   MODIFIED_CODE_NOQUEUE (reloc_addr);
 }
 
-auto inline void __attribute__ ((always_inline))
+static inline void
 elf_machine_lazy_rel (struct link_map *map,
 		      Elf64_Addr l_addr, const Elf64_Rela *reloc)
 {
   /* elf_machine_runtime_setup handles this.  */
 }
 
-
 #endif /* RESOLVE */