diff options
Diffstat (limited to 'sysdeps/powerpc')
-rw-r--r-- | sysdeps/powerpc/powerpc64/crti.S | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/dl-irel.h | 4 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/dl-machine.h | 100 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/setjmp-common.S | 7 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc64/sysdep.h | 54 |
5 files changed, 138 insertions, 29 deletions
diff --git a/sysdeps/powerpc/powerpc64/crti.S b/sysdeps/powerpc/powerpc64/crti.S index 116199da6b..7eff7fd97c 100644 --- a/sysdeps/powerpc/powerpc64/crti.S +++ b/sysdeps/powerpc/powerpc64/crti.S @@ -64,6 +64,7 @@ ENTRY_2(_init) .align ALIGNARG (2) BODY_LABEL (_init): + LOCALENTRY(_init) mflr 0 std 0, 16(r1) stdu r1, -112(r1) @@ -81,6 +82,7 @@ BODY_LABEL (_init): ENTRY_2(_fini) .align ALIGNARG (2) BODY_LABEL (_fini): + LOCALENTRY(_fini) mflr 0 std 0, 16(r1) stdu r1, -112(r1) diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h index d85c6148ac..a500aa6f4c 100644 --- a/sysdeps/powerpc/powerpc64/dl-irel.h +++ b/sysdeps/powerpc/powerpc64/dl-irel.h @@ -50,7 +50,11 @@ elf_irela (const Elf64_Rela *reloc) { Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; Elf64_Addr value = elf_ifunc_invoke(reloc->r_addend); +#if _CALL_ELF != 2 *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value; +#else + *reloc_addr = value; +#endif } else __libc_fatal ("unexpected reloc type in static binary"); diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index a623be5f0b..f222bb07d7 100644 --- a/sysdeps/powerpc/powerpc64/dl-machine.h +++ b/sysdeps/powerpc/powerpc64/dl-machine.h @@ -31,6 +31,7 @@ in l_info array. */ #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM) +#if _CALL_ELF != 2 /* A PowerPC64 function descriptor. The .plt (procedure linkage table) and .opd (official procedure descriptor) sections are arrays of these. */ @@ -40,6 +41,7 @@ typedef struct Elf64_Addr fd_toc; Elf64_Addr fd_aux; } Elf64_FuncDesc; +#endif #define ELF_MULT_MACHINES_SUPPORTED @@ -47,6 +49,18 @@ typedef struct static inline int elf_machine_matches_host (const Elf64_Ehdr *ehdr) { + /* Verify that the binary matches our ABI version. */ + if ((ehdr->e_flags & EF_PPC64_ABI) != 0) + { +#if _CALL_ELF != 2 + if ((ehdr->e_flags & EF_PPC64_ABI) != 1) + return 0; +#else + if ((ehdr->e_flags & EF_PPC64_ABI) != 2) + return 0; +#endif + } + return ehdr->e_machine == EM_PPC64; } @@ -124,6 +138,7 @@ elf_machine_dynamic (void) " .align 2\n" \ " " ENTRY_2(_start) "\n" \ BODY_PREFIX "_start:\n" \ +" " LOCALENTRY(_start) "\n" \ /* We start with the following on the stack, from top: \ argc (4 bytes); \ arguments for program (terminated by NULL); \ @@ -165,6 +180,7 @@ DL_STARTING_UP_DEF \ Changing these is strongly discouraged (not least because argc is \ passed by value!). */ \ BODY_PREFIX "_dl_start_user:\n" \ +" " LOCALENTRY(_dl_start_user) "\n" \ /* the address of _start in r30. */ \ " mr 30,3\n" \ /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \ @@ -256,8 +272,22 @@ BODY_PREFIX "_dl_start_user:\n" \ relocations behave "normally", ie. always use the real address like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */ +#if _CALL_ELF != 2 #define elf_machine_type_class(type) \ (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) +#else +/* And now that you have read that large comment, you can disregard it + all for ELFv2. ELFv2 does need the special SHN_UNDEF treatment. */ +#define IS_PPC64_TLS_RELOC(R) \ + (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \ + || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA)) + +#define elf_machine_type_class(type) \ + ((((type) == R_PPC64_JMP_SLOT \ + || (type) == R_PPC64_ADDR24 \ + || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) +#endif /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ #define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT @@ -266,8 +296,19 @@ BODY_PREFIX "_dl_start_user:\n" \ #define ELF_MACHINE_NO_REL 1 /* Stuff for the PLT. */ +#if _CALL_ELF != 2 #define PLT_INITIAL_ENTRY_WORDS 3 +#define PLT_ENTRY_WORDS 3 +#define GLINK_INITIAL_ENTRY_WORDS 8 +/* The first 32k entries of glink can set an index and branch using two + instructions; past that point, glink uses three instructions. */ +#define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3) +#else +#define PLT_INITIAL_ENTRY_WORDS 2 +#define PLT_ENTRY_WORDS 1 #define GLINK_INITIAL_ENTRY_WORDS 8 +#define GLINK_ENTRY_WORDS(I) 1 +#endif #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory") #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory") @@ -312,38 +353,45 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile) if (lazy) { - /* The function descriptor of the appropriate trampoline - routine is used to set the 1st and 2nd doubleword of the - plt_reserve. */ - Elf64_FuncDesc *resolve_fd; Elf64_Word glink_offset; - /* the plt_reserve area is the 1st 3 doublewords of the PLT */ - Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt; Elf64_Word offset; + Elf64_Addr dlrr; - resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve - : _dl_runtime_resolve); + dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve + : _dl_runtime_resolve); if (profile && GLRO(dl_profile) != NULL && _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; - +#if _CALL_ELF != 2 /* We need to stuff the address/TOC of _dl_runtime_resolve into doublewords 0 and 1 of plt_reserve. Then we need to stuff the map address into doubleword 2 of plt_reserve. This allows the GLINK0 code to transfer control to the correct trampoline which will transfer control to fixup in dl-machine.c. */ - plt_reserve->fd_func = resolve_fd->fd_func; - plt_reserve->fd_toc = resolve_fd->fd_toc; - plt_reserve->fd_aux = (Elf64_Addr) map; + { + /* The plt_reserve area is the 1st 3 doublewords of the PLT. */ + Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt; + Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr; + plt_reserve->fd_func = resolve_fd->fd_func; + plt_reserve->fd_toc = resolve_fd->fd_toc; + plt_reserve->fd_aux = (Elf64_Addr) map; #ifdef RTLD_BOOTSTRAP - /* When we're bootstrapping, the opd entry will not have - been relocated yet. */ - plt_reserve->fd_func += l_addr; - plt_reserve->fd_toc += l_addr; + /* When we're bootstrapping, the opd entry will not have + been relocated yet. */ + plt_reserve->fd_func += l_addr; + plt_reserve->fd_toc += l_addr; +#endif + } +#else + /* When we don't have function descriptors, the first doubleword + of the PLT holds the address of _dl_runtime_resolve, and the + second doubleword holds the map address. */ + plt[0] = dlrr; + plt[1] = (Elf64_Addr) map; #endif /* Set up the lazy PLT entries. */ @@ -354,14 +402,8 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile) { plt[offset] = (Elf64_Xword) &glink[glink_offset]; - offset += 3; - /* The first 32k entries of glink can set an index and - branch using two instructions; Past that point, - glink uses three instructions. */ - if (i < 0x8000) - glink_offset += 2; - else - glink_offset += 3; + offset += PLT_ENTRY_WORDS; + glink_offset += GLINK_ENTRY_WORDS (i); } /* Now, we've modified data. We need to write the changes from @@ -389,6 +431,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map, const Elf64_Rela *reloc, Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) { +#if _CALL_ELF != 2 Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; Elf64_Addr offset = 0; @@ -426,6 +469,9 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map, plt->fd_func = rel->fd_func + offset; PPC_DCBST (&plt->fd_func); PPC_ISYNC; +#else + *reloc_addr = finaladdr; +#endif return finaladdr; } @@ -433,6 +479,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map, static inline void __attribute__ ((always_inline)) elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) { +#if _CALL_ELF != 2 Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; @@ -443,6 +490,9 @@ elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) PPC_DCBST (&plt->fd_aux); PPC_DCBST (&plt->fd_toc); PPC_SYNC; +#else + *reloc_addr = finaladdr; +#endif } /* Return the final value of a plt relocation. */ @@ -512,6 +562,7 @@ auto inline Elf64_Addr __attribute__ ((always_inline)) resolve_ifunc (Elf64_Addr value, const struct link_map *map, const struct link_map *sym_map) { +#if _CALL_ELF != 2 #ifndef RESOLVE_CONFLICT_FIND_MAP /* The function we are calling may not yet have its opd entry relocated. */ Elf64_FuncDesc opd; @@ -529,6 +580,7 @@ resolve_ifunc (Elf64_Addr value, value = (Elf64_Addr) &opd; } #endif +#endif return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap)); } diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S index 1829b9ab65..db4b3497c7 100644 --- a/sysdeps/powerpc/powerpc64/setjmp-common.S +++ b/sysdeps/powerpc/powerpc64/setjmp-common.S @@ -55,9 +55,10 @@ END (setjmp) HAVE_CLEANUP_JMP_BUF is defined. */ ENTRY (__GI__setjmp) std r2,40(r1) /* Save the callers TOC in the save area. */ - cfi_endproc -END_2 (__GI__setjmp) -/* Fall thru. */ + CALL_MCOUNT 1 + li r4,0 /* Set second argument to 0. */ + b JUMPTARGET (GLUE(__sigsetjmp,_ent)) +END (__GI__setjmp) #endif ENTRY (_setjmp) diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h index cc89b3ce80..779fd90265 100644 --- a/sysdeps/powerpc/powerpc64/sysdep.h +++ b/sysdeps/powerpc/powerpc64/sysdep.h @@ -74,6 +74,8 @@ #endif .endm +#if _CALL_ELF != 2 + /* Macro to prepare for calling via a function pointer. */ .macro PPC64_LOAD_FUNCPTR PTR ld r12,0(\PTR) @@ -115,13 +117,37 @@ name##: OPD_ENT (name); \ .size name,.-BODY_LABEL(name); \ .size BODY_LABEL(name),.-BODY_LABEL(name); #endif +#define LOCALENTRY(name) + +#else /* _CALL_ELF */ + +/* Macro to prepare for calling via a function pointer. */ + .macro PPC64_LOAD_FUNCPTR PTR + mr r12,\PTR + mtctr r12 + .endm + +#define DOT_LABEL(X) X +#define BODY_LABEL(X) X +#define ENTRY_2(name) \ + .globl name; \ + .type name,@function; +#define END_2(name) \ + .size name,.-name; +#define LOCALENTRY(name) \ +1: addis r2,r12,.TOC.-1b@ha; \ + addi r2,r2,.TOC.-1b@l; \ + .localentry name,.-name; + +#endif /* _CALL_ELF */ #define ENTRY(name) \ .section ".text"; \ ENTRY_2(name) \ .align ALIGNARG(2); \ BODY_LABEL(name): \ - cfi_startproc; + cfi_startproc; \ + LOCALENTRY(name) #define EALIGN_W_0 /* No words to insert. */ #define EALIGN_W_1 nop @@ -140,7 +166,8 @@ BODY_LABEL(name): \ .align ALIGNARG(alignt); \ EALIGN_W_##words; \ BODY_LABEL(name): \ - cfi_startproc; + cfi_startproc; \ + LOCALENTRY(name) /* Local labels stripped out by the linker. */ #undef L @@ -295,6 +322,8 @@ LT_LABELSUFFIX(name,_name_end): ; \ #else /* !__ASSEMBLER__ */ +#if _CALL_ELF != 2 + #define PPC64_LOAD_FUNCPTR(ptr) \ "ld 12,0(" #ptr ");\n" \ "ld 2,8(" #ptr ");\n" \ @@ -335,5 +364,26 @@ LT_LABELSUFFIX(name,_name_end): ; \ ".size " #name ",.-" BODY_PREFIX #name ";\n" \ ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" #endif +#define LOCALENTRY(name) + +#else /* _CALL_ELF */ + +#define PPC64_LOAD_FUNCPTR(ptr) \ + "mr 12," #ptr ";\n" \ + "mtctr 12;" + +#define DOT_PREFIX "" +#define BODY_PREFIX "" +#define ENTRY_2(name) \ + ".type " #name ",@function;\n" \ + ".globl " #name ";" +#define END_2(name) \ + ".size " #name ",.-" #name ";" +#define LOCALENTRY(name) \ + "1: addis 2,12,.TOC.-1b@ha;\n" \ + "addi 2,2,.TOC.-1b@l;\n" \ + ".localentry " #name ",.-" #name ";" + +#endif /* _CALL_ELF */ #endif /* __ASSEMBLER__ */ |