diff options
-rw-r--r-- | elf/dl-reloc.c | 6 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 3 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc32/dl-machine.c | 48 | ||||
-rw-r--r-- | sysdeps/powerpc/powerpc32/dl-machine.h | 87 |
4 files changed, 80 insertions, 64 deletions
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index ad6c00c..e8e56c8 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -41,8 +41,8 @@ the static TLS area already allocated for each running thread. If this object's TLS segment is too big to fit, we fail. If it fits, we set MAP->l_tls_offset and return. */ -static void __attribute_noinline__ -allocate_static_tls (struct link_map *map) +void __attribute_noinline__ +_dl_allocate_static_tls (struct link_map *map) { size_t offset, used, check; @@ -209,7 +209,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], #define CHECK_STATIC_TLS(map, sym_map) \ do { \ if (__builtin_expect ((sym_map)->l_tls_offset == 0, 0)) \ - allocate_static_tls (sym_map); \ + _dl_allocate_static_tls (sym_map); \ } while (0) #include "dynamic-link.h" diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 8be15b1..12151ce 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -795,6 +795,9 @@ rtld_hidden_proto (_dl_allocate_tls) extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp) internal_function; +extern void _dl_allocate_static_tls (struct link_map *map) + internal_function attribute_hidden; + /* These are internal entry points to the two halves of _dl_allocate_tls, only used within rtld.c itself at startup time. */ extern void *_dl_allocate_tls_storage (void) diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c index 866380a..2e071c8 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.c +++ b/sysdeps/powerpc/powerpc32/dl-machine.c @@ -397,6 +397,7 @@ _dl_reloc_overflow (struct link_map *map, void __process_machine_rela (struct link_map *map, const Elf32_Rela *reloc, + struct link_map *sym_map, const Elf32_Sym *sym, const Elf32_Sym *refsym, Elf32_Addr *const reloc_addr, @@ -541,6 +542,53 @@ __process_machine_rela (struct link_map *map, } break; +#ifdef USE_TLS +#define CHECK_STATIC_TLS(map, sym_map) \ + do { \ + if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0)) \ + _dl_allocate_static_tls (sym_map); \ + } while (0) +# 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 (sym_map != NULL) \ + do_reloc##suffix ("R_PPC_DTPREL"#suffix, \ + TLS_DTPREL_VALUE (sym, reloc)); \ + break; \ + case R_PPC_TPREL##suffix: \ + if (sym_map != NULL) \ + { \ + CHECK_STATIC_TLS (map, sym_map); \ + do_reloc##suffix ("R_PPC_TPREL"#suffix, \ + TLS_TPREL_VALUE (sym_map, sym, reloc)); \ + } \ + break; + + inline void do_reloc16 (const char *r_name, Elf32_Addr value) + { + if (__builtin_expect (value > 0x7fff && value < 0xffff8000, 0)) + _dl_reloc_overflow (map, r_name, 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 + default: _dl_reloc_bad_type (map, rinfo, 0); return; diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h index 2f35275..e26c2d5 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.h +++ b/sysdeps/powerpc/powerpc32/dl-machine.h @@ -336,6 +336,7 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc, has been determined. */ extern void __process_machine_rela (struct link_map *map, const Elf32_Rela *reloc, + struct link_map *sym_map, const Elf32_Sym *sym, const Elf32_Sym *refsym, Elf32_Addr *const reloc_addr, @@ -361,9 +362,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, const Elf32_Sym *const refsym = sym; Elf32_Addr value; const int r_type = ELF32_R_TYPE (reloc->r_info); -#if defined USE_TLS && !defined RTLD_BOOTSTRAP - struct link_map *sym_map; -#endif + struct link_map *sym_map = NULL; #ifndef RESOLVE_CONFLICT_FIND_MAP if (r_type == R_PPC_RELATIVE) @@ -411,71 +410,37 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, *reloc_addr = value; break; -#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) - case R_PPC_DTPMOD32: -# ifdef RTLD_BOOTSTRAP - /* During startup the dynamic linker is always index 1. */ - *reloc_addr = 1; -# else - /* Get the information from the link map returned by the - RESOLVE_MAP function. */ - if (sym_map != NULL) - *reloc_addr = sym_map->l_tls_modid; -# endif - break; - +#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \ + && !defined RESOLVE_CONFLICT_FIND_MAP # 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; - inline void do_reloc32 (const char *r_name, Elf32_Addr value) + case R_PPC_DTPMOD32: + if (!NOT_BOOTSTRAP) + /* During startup the dynamic linker is always index 1. */ + *reloc_addr = 1; + else if (sym_map != NULL) + /* Get the information from the link map returned by the + RESOLVE_MAP function. */ + *reloc_addr = sym_map->l_tls_modid; + break; + case R_PPC_DTPREL32: + /* During relocation all TLS symbols are defined and used. + Therefore the offset is already correct. */ + if (NOT_BOOTSTRAP && sym_map != NULL) + *reloc_addr = TLS_DTPREL_VALUE (sym, reloc); + break; + case R_PPC_TPREL32: + if (!NOT_BOOTSTRAP || sym_map != NULL) { - *reloc_addr = value; + if (NOT_BOOTSTRAP) + CHECK_STATIC_TLS (map, sym_map); + *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc); } - 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 @@ -485,7 +450,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, #endif default: - __process_machine_rela (map, reloc, sym, refsym, + __process_machine_rela (map, reloc, sym_map, sym, refsym, reloc_addr, value, r_type); } } |