diff options
Diffstat (limited to 'sysdeps/powerpc/powerpc64/dl-machine.h')
-rw-r--r-- | sysdeps/powerpc/powerpc64/dl-machine.h | 121 |
1 files changed, 100 insertions, 21 deletions
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index cec271b..3fcf77d 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 */ |