diff options
Diffstat (limited to 'sysdeps/powerpc/powerpc32')
-rw-r--r-- | sysdeps/powerpc/powerpc32/dl-machine.c | 24 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc32/dl-machine.h | 75 |
2 files changed, 70 insertions, 29 deletions
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c index 065a1db6df..866380a940 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.c +++ b/sysdeps/powerpc/powerpc32/dl-machine.c @@ -1,5 +1,5 @@ /* Machine-dependent ELF dynamic relocation functions. PowerPC version. - Copyright (C) 1995-2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-2001,2002,2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -368,12 +368,12 @@ __elf_machine_fixup_plt(struct link_map *map, const Elf32_Rela *reloc, return finaladdr; } -static void -dl_reloc_overflow (struct link_map *map, - const char *name, - Elf32_Addr *const reloc_addr, - const Elf32_Sym *sym, - const Elf32_Sym *refsym) +void +_dl_reloc_overflow (struct link_map *map, + const char *name, + Elf32_Addr *const reloc_addr, + const Elf32_Sym *sym, + const Elf32_Sym *refsym) { char buffer[128]; char *t; @@ -423,19 +423,19 @@ __process_machine_rela (struct link_map *map, case R_PPC_ADDR24: if (__builtin_expect (finaladdr > 0x01fffffc && finaladdr < 0xfe000000, 0)) - dl_reloc_overflow (map, "R_PPC_ADDR24", reloc_addr, sym, refsym); + _dl_reloc_overflow (map, "R_PPC_ADDR24", reloc_addr, sym, refsym); *reloc_addr = (*reloc_addr & 0xfc000003) | (finaladdr & 0x3fffffc); break; case R_PPC_ADDR16: if (__builtin_expect (finaladdr > 0x7fff && finaladdr < 0xffff8000, 0)) - dl_reloc_overflow (map, "R_PPC_ADDR16", reloc_addr, sym, refsym); + _dl_reloc_overflow (map, "R_PPC_ADDR16", reloc_addr, sym, refsym); *(Elf32_Half*) reloc_addr = finaladdr; break; case R_PPC_UADDR16: if (__builtin_expect (finaladdr > 0x7fff && finaladdr < 0xffff8000, 0)) - dl_reloc_overflow (map, "R_PPC_UADDR16", reloc_addr, sym, refsym); + _dl_reloc_overflow (map, "R_PPC_UADDR16", reloc_addr, sym, refsym); ((char *) reloc_addr)[0] = finaladdr >> 8; ((char *) reloc_addr)[1] = finaladdr; break; @@ -456,7 +456,7 @@ __process_machine_rela (struct link_map *map, case R_PPC_ADDR14_BRTAKEN: case R_PPC_ADDR14_BRNTAKEN: if (__builtin_expect (finaladdr > 0x7fff && finaladdr < 0xffff8000, 0)) - dl_reloc_overflow (map, "R_PPC_ADDR14", reloc_addr, sym, refsym); + _dl_reloc_overflow (map, "R_PPC_ADDR14", reloc_addr, sym, refsym); *reloc_addr = (*reloc_addr & 0xffff0003) | (finaladdr & 0xfffc); if (rinfo != R_PPC_ADDR14) *reloc_addr = ((*reloc_addr & 0xffdfffff) @@ -468,7 +468,7 @@ __process_machine_rela (struct link_map *map, { Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr; if (delta << 6 >> 6 != delta) - dl_reloc_overflow (map, "R_PPC_REL24", reloc_addr, sym, refsym); + _dl_reloc_overflow (map, "R_PPC_REL24", reloc_addr, sym, refsym); *reloc_addr = (*reloc_addr & 0xfc000003) | (delta & 0x3fffffc); } break; diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h index 39dbbb412c..4da239d0f4 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.h +++ b/sysdeps/powerpc/powerpc32/dl-machine.h @@ -280,9 +280,8 @@ __elf_preferred_address(struct link_map *loader, size_t maplength, #define elf_machine_type_class(type) \ ((((type) == R_PPC_JMP_SLOT \ || (type) == R_PPC_REL24 \ - || (type) == R_PPC_DTPMOD32 \ - || (type) == R_PPC_DTPREL32 \ - || (type) == R_PPC_TPREL32 \ + || ((type) >= R_PPC_DTPMOD32 /* contiguous TLS */ \ + && (type) <= R_PPC_DTPREL32) \ || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY)) #else @@ -341,7 +340,14 @@ extern void __process_machine_rela (struct link_map *map, const Elf32_Sym *refsym, Elf32_Addr *const reloc_addr, Elf32_Addr finaladdr, - int rinfo); + int rinfo) attribute_hidden; + +/* Call _dl_signal_error when a resolved value overflows a relocated area. */ +extern void _dl_reloc_overflow (struct link_map *map, + const char *name, + Elf32_Addr *const reloc_addr, + const Elf32_Sym *sym, + const Elf32_Sym *refsym) attribute_hidden; /* Perform the relocation specified by RELOC and SYM (which is fully resolved). LOADADDR is the load address of the object; INFO is an array indexed @@ -402,24 +408,59 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, *reloc_addr = sym_map->l_tls_modid; # endif break; - case R_PPC_DTPREL32: - /* During relocation all TLS symbols are defined and used. - Therefore the offset is already correct. */ -# ifndef RTLD_BOOTSTRAP - *reloc_addr = TLS_DTPREL_VALUE (sym, reloc); + +# ifdef RTLD_BOOTSTRAP +# define NOT_BOOTSTRAP 0 +# else +# define NOT_BOOTSTRAP 1 # endif +# define DO_TLS_RELOC(suffix) \ + case R_PPC_DTPREL##suffix: \ + /* During relocation all TLS symbols are defined and used. \ + Therefore the offset is already correct. */ \ + if (NOT_BOOTSTRAP) \ + do_reloc##suffix ("R_PPC_DTPREL"#suffix, \ + TLS_DTPREL_VALUE (sym, reloc)); \ + break; \ + case R_PPC_TPREL##suffix: \ + if (!NOT_BOOTSTRAP || sym_map) \ + { \ + if (NOT_BOOTSTRAP) \ + CHECK_STATIC_TLS (map, sym_map); \ + do_reloc##suffix ("R_PPC_TPREL"#suffix, \ + TLS_TPREL_VALUE (sym_map, sym, reloc)); \ + } \ break; - case R_PPC_TPREL32: -# ifndef RTLD_BOOTSTRAP - if (sym_map) + + inline void do_reloc32 (const char *r_name, Elf32_Addr value) { - CHECK_STATIC_TLS (map, sym_map); -# endif - *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc); -# ifndef RTLD_BOOTSTRAP + *reloc_addr = value; } + DO_TLS_RELOC (32) +# ifndef RTLD_BOOTSTRAP /* PIC code like ld.so doesn't use these. */ + inline void do_reloc16 (const char *r_name, Elf32_Addr value) + { + if (__builtin_expect (value > 0x7fff && value < 0xffff8000, 0)) + _dl_reloc_overflow (map, "R_PPC_ADDR16", reloc_addr, sym, refsym); + *(Elf32_Half *) reloc_addr = value; + } + inline void do_reloc16_LO (const char *r_name, Elf32_Addr value) + { + *(Elf32_Half *) reloc_addr = value; + } + inline void do_reloc16_HI (const char *r_name, Elf32_Addr value) + { + *(Elf32_Half *) reloc_addr = value >> 16; + } + inline void do_reloc16_HA (const char *r_name, Elf32_Addr value) + { + *(Elf32_Half *) reloc_addr = (value + 0x8000) >> 16; + } + DO_TLS_RELOC (16) + DO_TLS_RELOC (16_LO) + DO_TLS_RELOC (16_HI) + DO_TLS_RELOC (16_HA) # endif - break; #endif /* USE_TLS etc. */ #ifdef RESOLVE_CONFLICT_FIND_MAP |