aboutsummaryrefslogtreecommitdiff
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 */