1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-07 06:43:00 +03:00
2002-04-08  kaz Kojima  <kkojima@rr.iij4u.or.jp>

	* elf/elf.h: Define R_SH_TLS_xxx macros.
	* elf/rtld.c: Remove an extra parenthesis.
	* elf/tls-macros.h: Define SH version TLS_LE, TLS_IE, TLS_LD and
	TLS_GD macros.
	* sysdeps/generic/dl-tls.c: Add a missing semi-colon.
	* sysdeps/sh/dl-lookupcfg.h: New file.
	* sysdeps/sh/dl-tls.h: New file.
	* sysdeps/sh/dl-machine.h (elf_machine_type_class): Set
	ELF_RTYPE_CLASS_PLT also for the three TLS relocations.
	(elf_machine_rela): Handle R_SH_TLS_DTPMOD32, R_SH_TLS_DTPOFF32 and
	R_SH_TLS_TPOFF32 relocations.
This commit is contained in:
Ulrich Drepper
2002-04-08 21:05:48 +00:00
parent 403e0597cd
commit 3632a26020
14 changed files with 364 additions and 13 deletions

View File

@@ -1,3 +1,17 @@
2002-04-08 kaz Kojima <kkojima@rr.iij4u.or.jp>
* elf/elf.h: Define R_SH_TLS_xxx macros.
* elf/rtld.c: Remove an extra parenthesis.
* elf/tls-macros.h: Define SH version TLS_LE, TLS_IE, TLS_LD and
TLS_GD macros.
* sysdeps/generic/dl-tls.c: Add a missing semi-colon.
* sysdeps/sh/dl-lookupcfg.h: New file.
* sysdeps/sh/dl-tls.h: New file.
* sysdeps/sh/dl-machine.h (elf_machine_type_class): Set
ELF_RTYPE_CLASS_PLT also for the three TLS relocations.
(elf_machine_rela): Handle R_SH_TLS_DTPMOD32, R_SH_TLS_DTPOFF32 and
R_SH_TLS_TPOFF32 relocations.
2002-04-08 Ulrich Drepper <drepper@redhat.com> 2002-04-08 Ulrich Drepper <drepper@redhat.com>
* cppflags-iterator.mk (cpp-srcs-left): Define NOT_IN_libc instead * cppflags-iterator.mk (cpp-srcs-left): Define NOT_IN_libc instead

View File

@@ -2123,6 +2123,21 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_SH_SWITCH8 33 #define R_SH_SWITCH8 33
#define R_SH_GNU_VTINHERIT 34 #define R_SH_GNU_VTINHERIT 34
#define R_SH_GNU_VTENTRY 35 #define R_SH_GNU_VTENTRY 35
#define R_SH_TLS_GD_32 128
#define R_SH_TLS_LD_32 129
#define R_SH_TLS_LDO_32 130
#define R_SH_TLS_IE_32 131
#define R_SH_TLS_LE_32 132
#define R_SH_TLS_DTPMOD32 133
#define R_SH_TLS_DTPOFF32 134
#define R_SH_TLS_TPOFF32 135
#define R_SH_TLS_GD_MOV 136
#define R_SH_TLS_GD_CALLMOV 137
#define R_SH_TLS_LDM_MOV 138
#define R_SH_TLS_LDO_MOV 139
#define R_SH_TLS_LD_CALLMOV 140
#define R_SH_TLS_IE_MOV 141
#define R_SH_TLS_LE_MOV 142
#define R_SH_GOT32 160 #define R_SH_GOT32 160
#define R_SH_PLT32 161 #define R_SH_PLT32 161
#define R_SH_COPY 162 #define R_SH_COPY 162

View File

@@ -303,7 +303,7 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
# elif TLS_DTV_AT_TP # elif TLS_DTV_AT_TP
GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE, GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
GL(dl_rtld_map).l_tls_align); GL(dl_rtld_map).l_tls_align);
initdtv[2].pointer = (char *) tlsblock + GL(dl_rtld_map).l_tls_offset); initdtv[2].pointer = (char *) tlsblock + GL(dl_rtld_map).l_tls_offset;
# else # else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif # endif

View File

@@ -95,6 +95,84 @@
__l; }) __l; })
# endif # endif
#elif defined __sh__
# define TLS_LE(x) \
({ int *__l; void *__tp; \
asm ("stc gbr,%1\n\t" \
"mov.l 1f,%0\n\t" \
"bra 2f\n\t" \
" add %1,%0\n\t" \
".align 2\n\t" \
"1: .long " #x "@tpoff\n\t" \
"2:" \
: "=r" (__l), "=r" (__tp)); \
__l; })
# define TLS_IE(x) \
({ int *__l; void *__tp; \
asm ("mova 0f,r0\n\t" \
"mov.l 0f,r12\n\t" \
"add r0,r12\n\t" \
"mov.l 1f,r0\n\t" \
"stc gbr,%1\n\t" \
"mov.l @(r0,r12),%0\n\t" \
"bra 2f\n\t" \
" add %1,%0\n\t" \
".align 2\n\t" \
"0: .long _GLOBAL_OFFSET_TABLE_\n\t" \
"1: .long " #x "@gottpoff\n\t" \
"2:" \
: "=r" (__l), "=r" (__tp) : : "r0", "r12"); \
__l; })
# define TLS_LD(x) \
({ int *__l; \
asm ("mova 0f,r0\n\t" \
"mov.l 0f,r12\n\t" \
"add r0,r12\n\t" \
"mov.l 1f,r4\n\t" \
"add r12,r4\n\t" \
"mova 2f,r0\n\t" \
"mov.l 2f,r1\n\t" \
"add r0,r1\n\t" \
"jsr @r1\n\t" \
" nop\n\t" \
"mov.l 3f,%0\n\t" \
"bra 4f\n\t" \
" add r0,%0\n\t" \
".align 2\n\t" \
"0: .long _GLOBAL_OFFSET_TABLE_\n\t" \
"1: .long " #x "@tlsldm\n\t" \
"2: .long __tls_get_addr@plt\n\t" \
"3: .long " #x "@dtpoff\n\t" \
"4:" \
: "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r12", "pr", "t"); \
__l; })
# define TLS_GD(x) \
({ int *__l; \
asm ("mova 0f,r0\n\t" \
"mov.l 0f,r12\n\t" \
"add r0,r12\n\t" \
"mov.l 1f,r4\n\t" \
"add r12,r4\n\t" \
"mova 2f,r0\n\t" \
"mov.l 2f,r1\n\t" \
"add r0,r1\n\t" \
"jsr @r1\n\t" \
" nop\n\t" \
"bra 3f\n\t" \
" mov r0,%0\n\t" \
".align 2\n\t" \
"0: .long _GLOBAL_OFFSET_TABLE_\n\t" \
"1: .long " #x "@tlsgd\n\t" \
"2: .long __tls_get_addr@plt\n\t" \
"3:" \
: "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r12", "pr", "t"); \
__l; })
#else #else
# error "No support for this architecture so far." # error "No support for this architecture so far."
#endif #endif

View File

@@ -1,3 +1,10 @@
2002-04-08 Jakub Jelinek <jakub@redhat.com>
* manager.c (__pthread_manager_event): Use self instead of arg
for INIT_THREAD_SELF.
* sysdeps/i386/useldt.h (INIT_THREAD_SELF): Use sizeof (struct
_pthread_descr_struct) instead of sizeof (*descr).
2002-04-05 Ulrich Drepper <drepper@redhat.com> 2002-04-05 Ulrich Drepper <drepper@redhat.com>
* sysdeps/ia64/pt-machine.h: Protect against multiple inclusion. * sysdeps/ia64/pt-machine.h: Protect against multiple inclusion.

View File

@@ -244,15 +244,16 @@ __pthread_manager(void *arg)
int __pthread_manager_event(void *arg) int __pthread_manager_event(void *arg)
{ {
pthread_descr self = arg;
/* If we have special thread_self processing, initialize it. */ /* If we have special thread_self processing, initialize it. */
#ifdef INIT_THREAD_SELF #ifdef INIT_THREAD_SELF
INIT_THREAD_SELF(arg, 1); INIT_THREAD_SELF(self, 1);
#endif #endif
/* Get the lock the manager will free once all is correctly set up. */ /* Get the lock the manager will free once all is correctly set up. */
__pthread_lock (THREAD_GETMEM(((pthread_descr) arg), p_lock), NULL); __pthread_lock (THREAD_GETMEM(self, p_lock), NULL);
/* Free it immediately. */ /* Free it immediately. */
__pthread_unlock (THREAD_GETMEM(((pthread_descr) arg), p_lock)); __pthread_unlock (THREAD_GETMEM(self, p_lock));
return __pthread_manager(arg); return __pthread_manager(arg);
} }

View File

@@ -64,7 +64,8 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t);
#define INIT_THREAD_SELF(descr, nr) \ #define INIT_THREAD_SELF(descr, nr) \
{ \ { \
struct modify_ldt_ldt_s ldt_entry = \ struct modify_ldt_ldt_s ldt_entry = \
{ nr, (unsigned long int) descr, sizeof (*descr), 1, 0, 0, 0, 0, 1, 0 }; \ { nr, (unsigned long int) descr, sizeof (struct _pthread_descr_struct), \
1, 0, 0, 0, 0, 1, 0 }; \
if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \
abort (); \ abort (); \
__asm__ __volatile__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ __asm__ __volatile__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \

View File

@@ -45,6 +45,11 @@ testandset (int *spinlock)
return (ret == 0); return (ret == 0);
} }
/* We want the OS to assign stack addresses. */
#define FLOATING_STACKS 1
/* Maximum size of the stack if the rlimit is unlimited. */
#define ARCH_STACK_MAX_SIZE 32*1024*1024
/* Get some notion of the current stack. Need not be exactly the top /* Get some notion of the current stack. Need not be exactly the top
of the stack, just something somewhere in the current frame. */ of the stack, just something somewhere in the current frame. */
@@ -61,4 +66,10 @@ struct _pthread_descr_struct;
#define INIT_THREAD_SELF(descr, nr) \ #define INIT_THREAD_SELF(descr, nr) \
({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));})
/* Access to data in the thread descriptor is easy. */
#define THREAD_GETMEM(descr, member) THREAD_SELF->member
#define THREAD_GETMEM_NC(descr, member) THREAD_SELF->member
#define THREAD_SETMEM(descr, member, value) THREAD_SELF->member = (value)
#define THREAD_SETMEM_NC(descr, member, value) THREAD_SELF->member = (value)
#endif /* pt-machine.h */ #endif /* pt-machine.h */

View File

@@ -0,0 +1,111 @@
/* Definition for thread-local data handling. linuxthreads/SH version.
Copyright (C) 2002 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
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _TLS_H
#define _TLS_H
#include <stddef.h>
#include <pt-machine.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
void *pointer;
} dtv_t;
typedef struct
{
void *tcb; /* Pointer to the TCB. Not necessary the
thread descriptor used by libpthread. */
dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
} tcbhead_t;
/* We can support TLS only if the floating-stack support is available. */
#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT
/* Get system call information. */
# include <sysdep.h>
/* Signal that TLS support is available. */
# define USE_TLS 1
/* Get the thread descriptor definition. */
# include <linuxthreads/descr.h>
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
/* Alignment requirements for the initial TCB. */
# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
/* Alignment requirements for the TCB. */
# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
/* The TLS blocks start right after the TCB. */
# define TLS_DTV_AT_TP 1
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(descr, dtvp) \
((tcbhead_t *) descr)->dtv = dtvp + 1
/* Install new dtv for current thread. */
# define INSTALL_NEW_DTV(dtv) \
({ struct _pthread_descr_struct *__descr; \
THREAD_SETMEM (__descr, p_header.data.dtvp, dtv); })
/* Return dtv of given thread descriptor. */
# define GET_DTV(descr) \
(((tcbhead_t *) descr)->dtv)
/* Code to initially initialize the thread pointer. This might need
special attention since 'errno' is not yet available and if the
operation can cause a failure 'errno' must not be touched. */
# define TLS_INIT_TP(descr) \
do { \
void *_descr = (descr); \
int result; \
tcbhead_t *head = _descr; \
\
head->tcb = _descr; \
/* For now the thread descriptor is at the same address. */ \
head->self = _descr; \
\
asm ("ldc %0,gbr" : : "r" (_descr)); \
} while (0)
/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
({ struct _pthread_descr_struct *__descr; \
THREAD_GETMEM (__descr, p_header.data.dtvp); })
#endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */
#endif /* tls.h */

View File

@@ -174,7 +174,7 @@ _dl_determine_tlsoffset (void)
slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo; slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
if (slotinfo[1].map != NULL) if (slotinfo[1].map != NULL)
{ {
size_t prev_size size_t prev_size;
offset = roundup (offset, slotinfo[1].map->l_tls_align); offset = roundup (offset, slotinfo[1].map->l_tls_align);
slotinfo[1].map->l_tls_offset = offset; slotinfo[1].map->l_tls_offset = offset;

View File

@@ -401,7 +401,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
# ifdef RTLD_BOOTSTRAP # ifdef RTLD_BOOTSTRAP
*reloc_addr = GL(dl_rtld_map).l_tls_offset - sym->st_value; *reloc_addr = GL(dl_rtld_map).l_tls_offset - sym->st_value;
# else # else
/* We know the offset of object the symbol is contained is. /* We know the offset of object the symbol is contained in.
It is a positive value which will be subtracted from the It is a positive value which will be subtracted from the
thread pointer. To get the variable position in the TLS thread pointer. To get the variable position in the TLS
block we subtract the offset from that of the TLS block. */ block we subtract the offset from that of the TLS block. */

28
sysdeps/sh/dl-lookupcfg.h Normal file
View File

@@ -0,0 +1,28 @@
/* Configuration of lookup functions. SH version.
Copyright (C) 2000, 2002 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
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <tls.h>
/* Some platforms need more information from the symbol lookup function
than just the address. For SH we need it when we support TLS. */
#ifdef USE_TLS
# define DL_LOOKUP_RETURNS_MAP
#else
# undef DL_LOOKUP_RETURNS_MAP
#endif

View File

@@ -396,13 +396,22 @@ _dl_start_user:\n\
.previous\n\ .previous\n\
"); ");
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
PLT entries should not be allowed to define the value. TLS variable, so undefined references should not be allowed to
define the value.
ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
of the main executable's symbols, as for a COPY reloc. */ of the main executable's symbols, as for a COPY reloc. */
#ifdef USE_TLS
# define elf_machine_type_class(type) \
((((type) == R_SH_JMP_SLOT || (type) == R_SH_TLS_DTPMOD32 \
|| (type) == R_SH_TLS_DTPOFF32 || (type) == R_SH_TLS_TPOFF32) \
* ELF_RTYPE_CLASS_PLT) \
| (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
#else
#define elf_machine_type_class(type) \ #define elf_machine_type_class(type) \
((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
| (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
#endif
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
#define ELF_MACHINE_JMP_SLOT R_SH_JMP_SLOT #define ELF_MACHINE_JMP_SLOT R_SH_JMP_SLOT
@@ -497,13 +506,21 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
else else
{ {
const Elf32_Sym *const refsym = sym; const Elf32_Sym *const refsym = sym;
#if defined USE_TLS && !defined RTLD_BOOTSTRAP
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info)); value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
if (sym) #else
value = RESOLVE (&sym, version, r_type);
# ifndef RTLD_BOOTSTRAP
if (sym != NULL)
# endif
value += sym->st_value; value += sym->st_value;
#endif
value += reloc->r_addend; value += reloc->r_addend;
switch (ELF32_R_TYPE (reloc->r_info)) switch (r_type)
{ {
case R_SH_COPY: case R_SH_COPY:
if (sym == NULL) if (sym == NULL)
@@ -529,6 +546,44 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
/* These addresses are always aligned. */ /* These addresses are always aligned. */
*reloc_addr = value; *reloc_addr = value;
break; break;
#ifdef USE_TLS
/* XXX Remove TLS relocations which are not needed. */
case R_SH_TLS_DTPMOD32:
# ifdef RTLD_BOOTSTRAP
/* During startup the dynamic linker is always the module
with index 1.
XXX If this relocation is necessary move before RESOLVE
call. */
*reloc_addr = 1;
# else
/* Get the information from the link map returned by the
resolv function. */
if (sym_map != NULL)
*reloc_addr = sym_map->l_tls_modid;
# endif
break;
case R_SH_TLS_DTPOFF32:
# ifndef RTLD_BOOTSTRAP
/* During relocation all TLS symbols are defined and used.
Therefore the offset is already correct. */
if (sym != NULL)
*reloc_addr = sym->st_value;
# endif
break;
case R_SH_TLS_TPOFF32:
/* The offset is positive, afterward from the thread pointer. */
# ifdef RTLD_BOOTSTRAP
*reloc_addr = GL(dl_rtld_map).l_tls_offset + sym->st_value;
# else
/* We know the offset of object the symbol is contained in.
It is a positive value which will be added to the thread
pointer. To get the variable position in the TLS block
we add the offset from that of the TLS block. */
if (sym_map != NULL && sym != NULL)
*reloc_addr = sym_map->l_tls_offset + sym->st_value;
# endif
break;
#endif /* use TLS */
case R_SH_DIR32: case R_SH_DIR32:
{ {
#ifndef RTLD_BOOTSTRAP #ifndef RTLD_BOOTSTRAP
@@ -557,7 +612,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
COPY_UNALIGNED_WORD (value, *reloc_addr, (int) reloc_addr & 3); COPY_UNALIGNED_WORD (value, *reloc_addr, (int) reloc_addr & 3);
break; break;
default: default:
_dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 0); _dl_reloc_bad_type (map, r_type, 0);
break; break;
} }
} }

30
sysdeps/sh/dl-tls.h Normal file
View File

@@ -0,0 +1,30 @@
/* Thread-local storage handling in the ELF dynamic linker. SH version.
Copyright (C) 2002 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
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Type used for the representation of TLS information in the GOT. */
typedef struct
{
unsigned long int ti_module;
unsigned long int ti_offset;
} tls_index;
extern void *__tls_get_addr (tls_index *ti)
__attribute__ ((__regparm__ (1)));