aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc')
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.c24
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.h75
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