* sysdeps/generic/ldsodefs.h (struct rtld_global): Move all [USE_TLS]
members to the end, so a libpthread compiled with !USE_TLS will still find other members properly. * sysdeps/i386/i486/bits/string.h (__strcpy_g): Add dummy output operand for DEST memory. Fix dummy input operand to use SRC. Reported by Davin McCall <davmac@ozonline.com.au>. * sysdeps/generic/libc-tls.c (__libc_setup_tls): Account for TCB alignment when initializing the DTV entry. * elf/dl-load.c (_dl_map_object_from_fd): If we hit a TLS segment when TLS has not been set up, try to set it up if we can. * elf/tst-tls4.c: Revert last change. * elf/tst-tls5.c: Likewise. * elf/tst-tls6.c: Likewise. * elf/tst-tls7.c: Likewise. * elf/tst-tls8.c: Likewise. * elf/tst-tls9.c: Likewise. * sysdeps/generic/dl-tls.c [SHARED] (_dl_tls_setup): New function. * sysdeps/generic/ldsodefs.h: Declare it. * elf/Versions (ld: GLIBC_PRIVATE): Add it. * sysdeps/generic/libc-tls.c (init_slotinfo): New static inline function, broken out of __libc_setup_tls. (init_static_tls): Likewise. (__libc_setup_tls): Call them. (_dl_tls_setup): New function, uses new subroutines. * elf/dl-close.c (free_slotinfo): Make argument pointer to pointer. Clear the pointer when returning true. (libc_freeres_fn) [SHARED]: If GL(dl_initial_dtv) is null, free the first element of the slotinfo list too. * sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Define only if [SHARED]. * sysdeps/generic/ldsodefs.h (_dl_next_tls_modid): Declare as hidden. (_dl_determine_tlsoffset): Likewise. * elf/rtld.c (_dl_initial_error_catch_tsd): Renamed from startup_error_tsd, made global. (dl_main): Update initialization. * elf/dl-tsd.c: Likewise. * sysdeps/generic/ldsodefs.h: Declare it.
This commit is contained in:
parent
68dc80ca28
commit
216455bc28
48
ChangeLog
48
ChangeLog
@ -1,3 +1,51 @@
|
||||
2002-12-04 Roland McGrath <roland@redhat.com>
|
||||
|
||||
* sysdeps/generic/ldsodefs.h (struct rtld_global): Move all [USE_TLS]
|
||||
members to the end, so a libpthread compiled with !USE_TLS will still
|
||||
find other members properly.
|
||||
|
||||
* sysdeps/i386/i486/bits/string.h (__strcpy_g): Add dummy output
|
||||
operand for DEST memory. Fix dummy input operand to use SRC.
|
||||
Reported by Davin McCall <davmac@ozonline.com.au>.
|
||||
|
||||
* sysdeps/generic/libc-tls.c (__libc_setup_tls): Account for TCB
|
||||
alignment when initializing the DTV entry.
|
||||
|
||||
* elf/dl-load.c (_dl_map_object_from_fd): If we hit a TLS segment
|
||||
when TLS has not been set up, try to set it up if we can.
|
||||
* elf/tst-tls4.c: Revert last change.
|
||||
* elf/tst-tls5.c: Likewise.
|
||||
* elf/tst-tls6.c: Likewise.
|
||||
* elf/tst-tls7.c: Likewise.
|
||||
* elf/tst-tls8.c: Likewise.
|
||||
* elf/tst-tls9.c: Likewise.
|
||||
|
||||
* sysdeps/generic/dl-tls.c [SHARED] (_dl_tls_setup): New function.
|
||||
* sysdeps/generic/ldsodefs.h: Declare it.
|
||||
* elf/Versions (ld: GLIBC_PRIVATE): Add it.
|
||||
* sysdeps/generic/libc-tls.c (init_slotinfo): New static inline
|
||||
function, broken out of __libc_setup_tls.
|
||||
(init_static_tls): Likewise.
|
||||
(__libc_setup_tls): Call them.
|
||||
(_dl_tls_setup): New function, uses new subroutines.
|
||||
|
||||
* elf/dl-close.c (free_slotinfo): Make argument pointer to pointer.
|
||||
Clear the pointer when returning true.
|
||||
(libc_freeres_fn) [SHARED]: If GL(dl_initial_dtv) is null, free the
|
||||
first element of the slotinfo list too.
|
||||
|
||||
* sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Define only if
|
||||
[SHARED].
|
||||
|
||||
* sysdeps/generic/ldsodefs.h (_dl_next_tls_modid): Declare as hidden.
|
||||
(_dl_determine_tlsoffset): Likewise.
|
||||
|
||||
* elf/rtld.c (_dl_initial_error_catch_tsd): Renamed from
|
||||
startup_error_tsd, made global.
|
||||
(dl_main): Update initialization.
|
||||
* elf/dl-tsd.c: Likewise.
|
||||
* sysdeps/generic/ldsodefs.h: Declare it.
|
||||
|
||||
2002-12-03 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* manual/texinfo.tex: Update from latest upstream version.
|
||||
|
@ -51,6 +51,6 @@ ld {
|
||||
_dl_unload_cache;
|
||||
_rtld_global; _dl_tls_symaddr; _dl_allocate_tls; _dl_deallocate_tls;
|
||||
_dl_get_tls_static_info; _dl_allocate_tls_init;
|
||||
_dl_get_origin;
|
||||
_dl_get_origin; _dl_tls_setup;
|
||||
}
|
||||
}
|
||||
|
@ -429,28 +429,28 @@ libc_hidden_def (_dl_close)
|
||||
|
||||
#ifdef USE_TLS
|
||||
static bool
|
||||
free_slotinfo (struct dtv_slotinfo_list *elemp)
|
||||
free_slotinfo (struct dtv_slotinfo_list **elemp)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
if (elemp == NULL)
|
||||
if (*elemp == NULL)
|
||||
/* Nothing here, all is removed (or there never was anything). */
|
||||
return true;
|
||||
|
||||
if (!free_slotinfo (elemp->next))
|
||||
if (!free_slotinfo (&(*elemp)->next))
|
||||
/* We cannot free the entry. */
|
||||
return false;
|
||||
|
||||
/* The least we could do is remove next element (if there was any). */
|
||||
elemp->next = NULL;
|
||||
/* That cleared our next pointer for us. */
|
||||
|
||||
for (cnt = 0; cnt < elemp->len; ++cnt)
|
||||
if (elemp->slotinfo[cnt].map != NULL)
|
||||
for (cnt = 0; cnt < (*elemp)->len; ++cnt)
|
||||
if ((*elemp)->slotinfo[cnt].map != NULL)
|
||||
/* Still used. */
|
||||
return false;
|
||||
|
||||
/* We can remove the list element. */
|
||||
free (elemp);
|
||||
free (*elemp);
|
||||
*elemp = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -479,12 +479,17 @@ libc_freeres_fn (free_mem)
|
||||
if (USE___THREAD || GL(dl_tls_dtv_slotinfo_list) != NULL)
|
||||
{
|
||||
/* Free the memory allocated for the dtv slotinfo array. We can do
|
||||
this only if all modules which used this memory are unloaded.
|
||||
Also, the first element of the list does not have to be
|
||||
deallocated. It was allocated in the dynamic linker (i.e., with
|
||||
a different malloc). */
|
||||
if (free_slotinfo (GL(dl_tls_dtv_slotinfo_list)->next))
|
||||
GL(dl_tls_dtv_slotinfo_list)->next = NULL;
|
||||
this only if all modules which used this memory are unloaded. */
|
||||
# ifdef SHARED
|
||||
if (GL(dl_initial_dtv) == NULL)
|
||||
/* There was no initial TLS setup, it was set up later when
|
||||
it used the normal malloc. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
|
||||
# endif
|
||||
/* The first element of the list does not have to be deallocated.
|
||||
It was allocated in the dynamic linker (i.e., with a different
|
||||
malloc), and in the static library it's in .bss space. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -946,32 +946,64 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
|
||||
/* Nothing to do for an empty segment. */
|
||||
break;
|
||||
|
||||
l->l_tls_blocksize = ph->p_memsz;
|
||||
l->l_tls_align = ph->p_align;
|
||||
l->l_tls_initimage_size = ph->p_filesz;
|
||||
/* Since we don't know the load address yet only store the
|
||||
offset. We will adjust it later. */
|
||||
l->l_tls_initimage = (void *) ph->p_vaddr;
|
||||
|
||||
/* If not loading the initial set of shared libraries,
|
||||
check whether we should permit loading a TLS segment. */
|
||||
if (
|
||||
# ifdef SHARED
|
||||
__builtin_expect (l->l_type == lt_library, 1) ||
|
||||
# endif
|
||||
if (__builtin_expect (l->l_type == lt_library, 1)
|
||||
/* If GL(dl_tls_max_dtv_idx) == 0, then rtld.c did not
|
||||
set up TLS data structures, so don't use them now. */
|
||||
__builtin_expect (GL(dl_tls_max_dtv_idx), 1) != 0)
|
||||
|| __builtin_expect (GL(dl_tls_max_dtv_idx), 1) != 0)
|
||||
{
|
||||
l->l_tls_blocksize = ph->p_memsz;
|
||||
l->l_tls_align = ph->p_align;
|
||||
l->l_tls_initimage_size = ph->p_filesz;
|
||||
/* Since we don't know the load address yet only store the
|
||||
offset. We will adjust it later. */
|
||||
l->l_tls_initimage = (void *) ph->p_vaddr;
|
||||
|
||||
/* Assign the next available module ID. */
|
||||
l->l_tls_modid = _dl_next_tls_modid ();
|
||||
break;
|
||||
}
|
||||
|
||||
# ifdef SHARED
|
||||
if (l->l_prev == NULL)
|
||||
/* We are loading the executable itself when the dynamic linker
|
||||
was executed directly. The setup will happen later. */
|
||||
break;
|
||||
|
||||
/* In a static binary there is no way to tell if we dynamically
|
||||
loaded libpthread. */
|
||||
if (GL(dl_error_catch_tsd) == &_dl_initial_error_catch_tsd)
|
||||
# endif
|
||||
{
|
||||
/* We have not yet loaded libpthread.
|
||||
We can do the TLS setup right now! */
|
||||
|
||||
void *tcb;
|
||||
|
||||
/* The first call allocates TLS bookkeeping data structures.
|
||||
Then we allocate the TCB for the initial thread. */
|
||||
if (__builtin_expect (_dl_tls_setup (), 0)
|
||||
|| __builtin_expect ((tcb = _dl_allocate_tls (NULL)) == NULL,
|
||||
0))
|
||||
{
|
||||
errval = ENOMEM;
|
||||
errstring = N_("\
|
||||
cannot allocate TLS data structures for initial thread");
|
||||
goto call_lose;
|
||||
}
|
||||
|
||||
/* Now we install the TCB in the thread register. */
|
||||
if (__builtin_expect (TLS_INIT_TP (tcb, 0), 0) != -1)
|
||||
{
|
||||
/* Now we are all good. */
|
||||
l->l_tls_modid = ++GL(dl_tls_max_dtv_idx);
|
||||
break;
|
||||
}
|
||||
|
||||
/* The kernel is too old or somesuch. */
|
||||
_dl_deallocate_tls (tcb, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Uh-oh, the binary expects TLS support but we cannot
|
||||
|
@ -27,8 +27,8 @@
|
||||
/* _dl_error_catch_tsd points to this for the single-threaded case.
|
||||
It's reset by the thread library for multithreaded programs
|
||||
if we're not using __thread. */
|
||||
static void ** __attribute__ ((const))
|
||||
startup_error_tsd (void)
|
||||
void ** __attribute__ ((const))
|
||||
_dl_initial_error_catch_tsd (void)
|
||||
{
|
||||
# if USE___THREAD
|
||||
static __thread void *data;
|
||||
@ -38,7 +38,7 @@ startup_error_tsd (void)
|
||||
return &data;
|
||||
}
|
||||
void **(*_dl_error_catch_tsd) (void) __attribute__ ((const))
|
||||
= &startup_error_tsd;
|
||||
= &_dl_initial_error_catch_tsd;
|
||||
|
||||
# elif USE___THREAD
|
||||
|
||||
|
10
elf/rtld.c
10
elf/rtld.c
@ -563,8 +563,8 @@ match_version (const char *string, struct link_map *map)
|
||||
#ifdef _LIBC_REENTRANT
|
||||
/* _dl_error_catch_tsd points to this for the single-threaded case.
|
||||
It's reset by the thread library for multithreaded programs. */
|
||||
static void ** __attribute__ ((const))
|
||||
startup_error_tsd (void)
|
||||
void ** __attribute__ ((const))
|
||||
_dl_initial_error_catch_tsd (void)
|
||||
{
|
||||
static void *data;
|
||||
return &data;
|
||||
@ -602,7 +602,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
|
||||
#ifdef _LIBC_REENTRANT
|
||||
/* Explicit initialization since the reloc would just be more work. */
|
||||
GL(dl_error_catch_tsd) = &startup_error_tsd;
|
||||
GL(dl_error_catch_tsd) = &_dl_initial_error_catch_tsd;
|
||||
#endif
|
||||
|
||||
/* Process the environment variable which control the behaviour. */
|
||||
@ -1180,9 +1180,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
slotinfo[++i].map = l;
|
||||
assert (i == GL(dl_tls_max_dtv_idx));
|
||||
|
||||
/* Compute the TLS offsets for the various blocks. We call this
|
||||
function even if none of the modules available at startup time
|
||||
uses TLS to initialize some variables. */
|
||||
/* Compute the TLS offsets for the various blocks. */
|
||||
_dl_determine_tlsoffset ();
|
||||
|
||||
/* Construct the static TLS block and the dtv for the initial
|
||||
|
@ -4,14 +4,6 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
/* This gives the executable a TLS segment so that even if the libc.so
|
||||
it loads has none (i.e. --with-tls --without-__thread), ld.so will
|
||||
permit loading of objects with TLS segments. */
|
||||
COMMON_INT_DEF(loser);
|
||||
#endif
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
|
@ -4,15 +4,6 @@
|
||||
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
/* This gives the executable a TLS segment so that even if the libc.so
|
||||
it loads has none (i.e. --with-tls --without-__thread), ld.so will
|
||||
permit loading of objects with TLS segments. */
|
||||
COMMON_INT_DEF(loser);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
|
@ -5,15 +5,6 @@
|
||||
#include <link.h>
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
/* This gives the executable a TLS segment so that even if the libc.so
|
||||
it loads has none (i.e. --with-tls --without-__thread), ld.so will
|
||||
permit loading of objects with TLS segments. */
|
||||
COMMON_INT_DEF(loser);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
|
@ -5,15 +5,6 @@
|
||||
#include <link.h>
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
/* This gives the executable a TLS segment so that even if the libc.so
|
||||
it loads has none (i.e. --with-tls --without-__thread), ld.so will
|
||||
permit loading of objects with TLS segments. */
|
||||
COMMON_INT_DEF(loser);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
|
@ -5,15 +5,6 @@
|
||||
#include <link.h>
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
/* This gives the executable a TLS segment so that even if the libc.so
|
||||
it loads has none (i.e. --with-tls --without-__thread), ld.so will
|
||||
permit loading of objects with TLS segments. */
|
||||
COMMON_INT_DEF(loser);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
|
@ -5,16 +5,6 @@
|
||||
#include <link.h>
|
||||
#include <tls.h>
|
||||
|
||||
#ifdef USE_TLS
|
||||
# include "tls-macros.h"
|
||||
|
||||
/* This gives the executable a TLS segment so that even if the libc.so
|
||||
it loads has none (i.e. --with-tls --without-__thread), ld.so will
|
||||
permit loading of objects with TLS segments. */
|
||||
COMMON_INT_DEF(loser);
|
||||
#endif
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
static int
|
||||
do_test (void)
|
||||
|
@ -110,6 +110,7 @@ _dl_next_tls_modid (void)
|
||||
return result;
|
||||
}
|
||||
|
||||
# ifdef SHARED
|
||||
|
||||
void
|
||||
internal_function
|
||||
@ -204,6 +205,41 @@ _dl_determine_tlsoffset (void)
|
||||
}
|
||||
|
||||
|
||||
/* This is called only when the data structure setup was skipped at startup,
|
||||
when there was no need for it then. Now we have dynamically loaded
|
||||
something needing TLS, or libpthread needs it. */
|
||||
int
|
||||
internal_function
|
||||
_dl_tls_setup (void)
|
||||
{
|
||||
assert (GL(dl_tls_dtv_slotinfo_list) == NULL);
|
||||
assert (GL(dl_tls_max_dtv_idx) == 0);
|
||||
|
||||
const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS;
|
||||
|
||||
GL(dl_tls_dtv_slotinfo_list) =
|
||||
malloc (sizeof (struct dtv_slotinfo_list)
|
||||
+ nelem * sizeof (struct dtv_slotinfo));
|
||||
if (GL(dl_tls_dtv_slotinfo_list) == NULL)
|
||||
return -1;
|
||||
|
||||
memset (GL(dl_tls_dtv_slotinfo_list)->slotinfo, '\0',
|
||||
nelem * sizeof (struct dtv_slotinfo));
|
||||
GL(dl_tls_dtv_slotinfo_list)->len = nelem;
|
||||
GL(dl_tls_dtv_slotinfo_list)->next = NULL;
|
||||
|
||||
/* Number of elements in the static TLS block. It can't be zero
|
||||
because of various assumptions. The one element is null. */
|
||||
GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1;
|
||||
|
||||
/* This initializes more variables for us. */
|
||||
_dl_determine_tlsoffset ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
rtld_hidden_def (_dl_tls_setup)
|
||||
# endif
|
||||
|
||||
static void *
|
||||
internal_function
|
||||
allocate_dtv (void *result)
|
||||
|
@ -74,6 +74,35 @@ size_t _dl_tls_generation;
|
||||
TLS_INIT_HELPER
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
init_slotinfo (void)
|
||||
{
|
||||
/* Create the slotinfo list. */
|
||||
static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
|
||||
- (char *) &static_slotinfo.si.slotinfo[0])
|
||||
/ sizeof static_slotinfo.si.slotinfo[0]);
|
||||
// static_slotinfo.si.next = NULL; already zero
|
||||
|
||||
/* The slotinfo list. Will be extended by the code doing dynamic
|
||||
linking. */
|
||||
GL(dl_tls_max_dtv_idx) = 1;
|
||||
GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_static_tls (size_t memsz, size_t align)
|
||||
{
|
||||
/* That is the size of the TLS memory for this object. The initialized
|
||||
value of _dl_tls_static_size is provided by dl-open.c to request some
|
||||
surplus that permits dynamic loading of modules with IE-model TLS. */
|
||||
GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
|
||||
TLS_TCB_ALIGN);
|
||||
GL(dl_tls_static_used) = memsz;
|
||||
/* The alignment requirement for the static TLS block. */
|
||||
GL(dl_tls_static_align) = align;
|
||||
/* Number of elements in the static TLS block. */
|
||||
GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
|
||||
}
|
||||
|
||||
void
|
||||
__libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
@ -117,8 +146,8 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
to request some surplus that permits dynamic loading of modules with
|
||||
IE-model TLS. */
|
||||
# if TLS_TCB_AT_TP
|
||||
tlsblock = __sbrk (roundup (memsz, tcbalign) + tcbsize + max_align
|
||||
+ GL(dl_tls_static_size));
|
||||
tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
|
||||
tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
|
||||
# elif TLS_DTV_AT_TP
|
||||
tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align
|
||||
+ GL(dl_tls_static_size));
|
||||
@ -138,10 +167,13 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
|
||||
/* Initialize the TLS block. */
|
||||
# if TLS_TCB_AT_TP
|
||||
static_dtv[2].pointer = tlsblock;
|
||||
static_dtv[2].pointer = ((char *) tlsblock + tcb_offset
|
||||
- roundup (memsz, align));
|
||||
static_map.l_tls_offset = roundup (memsz, align);
|
||||
# elif TLS_DTV_AT_TP
|
||||
tcb_offset = roundup (tcbsize, align);
|
||||
static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
|
||||
static_map.l_tls_offset = tcb_offset;
|
||||
# else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
@ -152,8 +184,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
|
||||
/* Initialize the thread pointer. */
|
||||
# if TLS_TCB_AT_TP
|
||||
tcb_offset = roundup (memsz, tcbalign);
|
||||
|
||||
INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
|
||||
|
||||
TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
|
||||
@ -171,39 +201,38 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
|
||||
static_map.l_tls_blocksize = memsz;
|
||||
static_map.l_tls_initimage = initimage;
|
||||
static_map.l_tls_initimage_size = filesz;
|
||||
static_map.l_tls_offset = tcb_offset;
|
||||
static_map.l_type = lt_executable;
|
||||
static_map.l_tls_modid = 1;
|
||||
|
||||
/* Create the slotinfo list. */
|
||||
static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
|
||||
- (char *) &static_slotinfo.si.slotinfo[0])
|
||||
/ sizeof static_slotinfo.si.slotinfo[0]);
|
||||
// static_slotinfo.si.next = NULL; already zero
|
||||
|
||||
static_slotinfo.si.slotinfo[1].gen = 0;
|
||||
init_slotinfo ();
|
||||
// static_slotinfo.si.slotinfo[1].gen = 0; already zero
|
||||
static_slotinfo.si.slotinfo[1].map = &static_map;
|
||||
|
||||
/* The slotinfo list. Will be extended by the code doing dynamic
|
||||
linking. */
|
||||
GL(dl_tls_max_dtv_idx) = 1;
|
||||
GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
|
||||
|
||||
memsz = roundup (memsz, align ?: 1);
|
||||
|
||||
# if TLS_TCB_AT_TP
|
||||
memsz += tcbsize;
|
||||
# endif
|
||||
|
||||
/* That is the size of the TLS memory for this object. The initialized
|
||||
value of _dl_tls_static_size is provided by dl-open.c to request some
|
||||
surplus that permits dynamic loading of modules with IE-model TLS. */
|
||||
GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
|
||||
TLS_TCB_ALIGN);
|
||||
GL(dl_tls_static_used) = memsz;
|
||||
/* The alignment requirement for the static TLS block. */
|
||||
GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align);
|
||||
/* Number of elements in the static TLS block. */
|
||||
GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
|
||||
init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
|
||||
}
|
||||
|
||||
/* This is called only when the data structure setup was skipped at startup,
|
||||
when there was no need for it then. Now we have dynamically loaded
|
||||
something needing TLS, or libpthread needs it. */
|
||||
int
|
||||
internal_function
|
||||
_dl_tls_setup (void)
|
||||
{
|
||||
init_slotinfo ();
|
||||
init_static_tls (
|
||||
# if TLS_TCB_AT_TP
|
||||
TLS_TCB_SIZE,
|
||||
# else
|
||||
0,
|
||||
# endif
|
||||
TLS_TCB_ALIGN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -636,9 +636,10 @@ __strcpy_g (char *__dest, __const char *__src)
|
||||
"leal 1(%1),%1\n\t"
|
||||
"testb %b2,%b2\n\t"
|
||||
"jne 1b"
|
||||
: "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy)
|
||||
: "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy),
|
||||
"=m" ( *(struct { char __x[0xfffffff]; } *)__dest)
|
||||
: "0" (__src), "1" (__tmp),
|
||||
"m" ( *(struct { char __x[0xfffffff]; } *)__dest)
|
||||
"m" ( *(struct { char __x[0xfffffff]; } *)__src)
|
||||
: "cc");
|
||||
return __dest;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user