2002-08-04 Roland McGrath <roland@redhat.com>

* sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage): New function,
	split out of _dl_allocate_tls.
	(_dl_allocate_tls_init): Likewise.
	(_dl_allocate_tls): Call those.
	* sysdeps/generic/ldsodefs.h: Declare them with attribute_hidden.
	* elf/rtld.c (dl_main): Call them separately instead of calling
	_dl_allocate_tls.  Delay _dl_allocate_tls_init until after relocation
	is finished, so that the initializer data has been relocated before we
	copy it into the main thread's TLS block.
	* sysdeps/generic/dl-tls.c (_dl_allocate_tls): Fix off-by-one error in
	loop conditions, prevented the last used module from being initialized.
This commit is contained in:
Roland McGrath 2002-08-05 01:20:52 +00:00
parent 855efb5f6f
commit 581dc54b74
1 changed files with 75 additions and 61 deletions

View File

@ -198,7 +198,7 @@ _dl_determine_tlsoffset (void)
void *
internal_function
_dl_allocate_tls (void)
_dl_allocate_tls_storage (void)
{
void *result;
dtv_t *dtv;
@ -225,10 +225,6 @@ _dl_allocate_tls (void)
dtv = (dtv_t *) malloc ((dtv_length + 2) * sizeof (dtv_t));
if (result != MAP_FAILED && dtv != NULL)
{
struct dtv_slotinfo_list *listp;
bool first_block = true;
size_t total = 0;
# if TLS_TCB_AT_TP
/* The TCB follows the TLS blocks. */
result = (char *) result + GL(dl_tls_static_size) - TLS_TCB_SIZE;
@ -242,62 +238,6 @@ _dl_allocate_tls (void)
nothing there. */
memset (dtv + 2, '\0', dtv_length * sizeof (dtv_t));
/* We have to look prepare the dtv for all currently loaded
modules using TLS. For those which are dynamically loaded we
add the values indicating deferred allocation. */
listp = GL(dl_tls_dtv_slotinfo_list);
while (1)
{
size_t cnt;
for (cnt = first_block ? 1 : 0; cnt < listp->len; ++cnt)
{
struct link_map *map;
void *dest;
/* Check for the total number of used slots. */
if (total + cnt >= GL(dl_tls_max_dtv_idx))
break;
map = listp->slotinfo[cnt].map;
if (map == NULL)
/* Unused entry. */
continue;
if (map->l_type == lt_loaded)
{
/* For dynamically loaded modules we simply store
the value indicating deferred allocation. */
dtv[1 + map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
continue;
}
assert (map->l_tls_modid == cnt);
assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
# if TLS_TCB_AT_TP
assert (map->l_tls_offset >= map->l_tls_blocksize);
dest = (char *) result - map->l_tls_offset;
# elif TLS_DTV_AT_TP
dest = (char *) result + map->l_tls_offset;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
/* We don't have to clear the BSS part of the TLS block
since mmap is used to allocate the memory which
guarantees it is initialized to zero. */
dtv[1 + cnt].pointer = memcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size);
}
total += cnt;
if (total >= GL(dl_tls_max_dtv_idx))
break;
listp = listp->next;
assert (listp != NULL);
}
/* Add the dtv to the thread data structures. */
INSTALL_DTV (result, dtv);
}
@ -311,6 +251,80 @@ _dl_allocate_tls (void)
}
INTDEF(_dl_allocate_tls)
void *
internal_function
_dl_allocate_tls_init (void *result)
{
dtv_t *dtv = GET_DTV (result);
struct dtv_slotinfo_list *listp;
bool first_block = true;
size_t total = 0;
/* We have to look prepare the dtv for all currently loaded
modules using TLS. For those which are dynamically loaded we
add the values indicating deferred allocation. */
listp = GL(dl_tls_dtv_slotinfo_list);
while (1)
{
size_t cnt;
for (cnt = first_block ? 1 : 0; cnt < listp->len; ++cnt)
{
struct link_map *map;
void *dest;
/* Check for the total number of used slots. */
if (total + cnt > GL(dl_tls_max_dtv_idx))
break;
map = listp->slotinfo[cnt].map;
if (map == NULL)
/* Unused entry. */
continue;
if (map->l_type == lt_loaded)
{
/* For dynamically loaded modules we simply store
the value indicating deferred allocation. */
dtv[map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
continue;
}
assert (map->l_tls_modid == cnt);
assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
# if TLS_TCB_AT_TP
assert (map->l_tls_offset >= map->l_tls_blocksize);
dest = (char *) result - map->l_tls_offset;
# elif TLS_DTV_AT_TP
dest = (char *) result + map->l_tls_offset;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
/* We don't have to clear the BSS part of the TLS block
since mmap is used to allocate the memory which
guarantees it is initialized to zero. */
dtv[cnt].pointer = memcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size);
}
total += cnt;
if (total > GL(dl_tls_max_dtv_idx))
break;
listp = listp->next;
assert (listp != NULL);
}
return result;
}
void *
internal_function
_dl_allocate_tls (void)
{
return _dl_allocate_tls_init (_dl_allocate_tls_storage ());
}
void
internal_function