aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--elf/dl-close.c36
-rw-r--r--elf/dl-reloc.c26
3 files changed, 45 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 40a4ceb..7d2da4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-03-15 Alan Modra <amodra@gmail.com>
+
+ * elf/dl-reloc.c (_dl_try_allocate_static_tls <TLS_DTV_AT_TP>): Handle
+ l_tls_firstbyte_offset non-zero. Save padding offset in
+ l_tls_firstbyte_offset for later use.
+ * elf/dl-close.c (_dl_close_worker <TLS_DTV_AT_TP>): Correct code
+ freeing static tls block.
+
2011-03-05 Jonathan Nieder <jrnieder@gmail.com>
* sysdeps/unix/sysv/linux/sys/param.h: Fix an #ifndef __undef_ARG_MAX
diff --git a/elf/dl-close.c b/elf/dl-close.c
index efb2b58..229e288 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -591,21 +591,37 @@ _dl_close_worker (struct link_map *map)
}
}
#elif TLS_DTV_AT_TP
- if ((size_t) imap->l_tls_offset == tls_free_end)
+ if (tls_free_start == NO_TLS_OFFSET)
+ {
+ tls_free_start = imap->l_tls_firstbyte_offset;
+ tls_free_end = (imap->l_tls_offset
+ + imap->l_tls_blocksize);
+ }
+ else if (imap->l_tls_firstbyte_offset == tls_free_end)
/* Extend the contiguous chunk being reclaimed. */
- tls_free_end -= imap->l_tls_blocksize;
+ tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize;
else if (imap->l_tls_offset + imap->l_tls_blocksize
== tls_free_start)
/* Extend the chunk backwards. */
- tls_free_start = imap->l_tls_offset;
- else
+ tls_free_start = imap->l_tls_firstbyte_offset;
+ /* This isn't contiguous with the last chunk freed.
+ One of them will be leaked unless we can free
+ one block right away. */
+ else if (imap->l_tls_offset + imap->l_tls_blocksize
+ == GL(dl_tls_static_used))
+ GL(dl_tls_static_used) = imap->l_tls_firstbyte_offset;
+ else if (tls_free_end == GL(dl_tls_static_used))
{
- /* This isn't contiguous with the last chunk freed.
- One of them will be leaked. */
- if (tls_free_end == GL(dl_tls_static_used))
- GL(dl_tls_static_used) = tls_free_start;
- tls_free_start = imap->l_tls_offset;
- tls_free_end = tls_free_start + imap->l_tls_blocksize;
+ GL(dl_tls_static_used) = tls_free_start;
+ tls_free_start = imap->l_tls_firstbyte_offset;
+ tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize;
+ }
+ else if (tls_free_end < imap->l_tls_firstbyte_offset)
+ {
+ /* We pick the later block. It has a chance to
+ be freed. */
+ tls_free_start = imap->l_tls_firstbyte_offset;
+ tls_free_end = imap->l_tls_offset + imap->l_tls_blocksize;
}
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 23cb59c..7294112 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -1,5 +1,5 @@
/* Relocate a shared object and resolve its references to other loaded objects.
- Copyright (C) 1995-2006, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1995-2006, 2008-2010, 2011 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
@@ -57,38 +57,34 @@ _dl_try_allocate_static_tls (struct link_map *map)
}
#if TLS_TCB_AT_TP
- size_t freebytes;
- size_t n;
- size_t blsize;
-
- freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used);
+ size_t freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used);
if (freebytes < TLS_TCB_SIZE)
goto fail;
freebytes -= TLS_TCB_SIZE;
- blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
+ size_t blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
if (freebytes < blsize)
goto fail;
- n = (freebytes - blsize) / map->l_tls_align;
+ size_t n = (freebytes - blsize) / map->l_tls_align;
size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
- map->l_tls_firstbyte_offset);
map->l_tls_offset = GL(dl_tls_static_used) = offset;
#elif TLS_DTV_AT_TP
- size_t used;
- size_t check;
-
- size_t offset = roundup (GL(dl_tls_static_used), map->l_tls_align);
- used = offset + map->l_tls_blocksize;
- check = used;
/* dl_tls_static_used includes the TCB at the beginning. */
+ size_t offset = (((GL(dl_tls_static_used)
+ - map->l_tls_firstbyte_offset
+ + map->l_tls_align - 1) & -map->l_tls_align)
+ + map->l_tls_firstbyte_offset);
+ size_t used = offset + map->l_tls_blocksize;
- if (check > GL(dl_tls_static_size))
+ if (used > GL(dl_tls_static_size))
goto fail;
map->l_tls_offset = offset;
+ map->l_tls_firstbyte_offset = GL(dl_tls_static_used);
GL(dl_tls_static_used) = used;
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"