]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Static TLS memory leak fix (DTV case)
authorAlan Modra <amodra@gmail.com>
Tue, 3 May 2011 22:35:24 +0000 (17:35 -0500)
committerryanarn <ryanarn@igoo.rchland.ibm.com>
Fri, 1 Jul 2011 12:43:18 +0000 (07:43 -0500)
ChangeLog
elf/dl-close.c
elf/dl-reloc.c
elf/dl-tls.c

index 625f9de6db6f1eb141f5d717eb4aa9f8e4e00f21..e36b8085afc355a74ccb50780528bd8efdfe14a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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.  Add debug print.
+       * elf/dl-close.c (_dl_close_worker <TLS_DTV_AT_TP>): Correct code
+       freeing static tls block.  Add debug print.
+       * elf/fl-tls.c (_dl_determine_tlsoffset): Add debug print.
+
 2011-06-30  Ryan S. Arnold  <rsa@linux.vnet.ibm.com>
 
        * nptl/sysdeps/unix/sysv/linux/aio_misc.h
index 700e765c3c3e78f89b9016a83919dc3dd8bb8177..0e60ed904c50c768181b1f20ecb233b27cf1833a 100644 (file)
@@ -582,25 +582,51 @@ _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"
 #endif
+                 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
+                   _dl_debug_printf ("\nstatic tls free: %s\n"
+                                     "  tls_free_start = %Zu, "
+                                     "tls_free_end = %Zu, "
+                                     "dl_tls_static_used = %Zu\n",
+                                     imap->l_name[0] ? imap->l_name
+                                     : rtld_progname,
+                                     tls_free_start, tls_free_end,
+                                     GL(dl_tls_static_used));
+
                }
            }
 
index 23cb59cbc89cf65c5c3f8c56b0459daf8949383f..9d07fd6eaecd9cee3d317066892181a53062ce77 100644 (file)
@@ -77,23 +77,33 @@ _dl_try_allocate_static_tls (struct link_map *map)
 
   map->l_tls_offset = GL(dl_tls_static_used) = offset;
 #elif TLS_DTV_AT_TP
+  size_t offset;
   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.  */
+  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);
+  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"
 #endif
 
+  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
+    _dl_debug_printf ("\nstatic tls: %s\n"
+                     "  l_tls_offset = %Zu, l_tls_firstbyte_offset = %Zu,"
+                     " dl_tls_static_used = %Zu\n",
+                     map->l_name[0] ? map->l_name : rtld_progname,
+                     map->l_tls_offset, map->l_tls_firstbyte_offset,
+                     GL(dl_tls_static_used));
   /* If the object is not yet relocated we cannot initialize the
      static TLS region.  Delay it.  */
   if (map->l_real->l_relocated)
index 824adc196d1ab63646c7e8ea4e3546107b7590bd..8db7c852f61f8634b6a3f4749b6492400b60be3c 100644 (file)
@@ -249,6 +249,11 @@ _dl_determine_tlsoffset (void)
 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 #endif
 
+  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
+    _dl_debug_printf ("\ninitial static tls: "
+                     "dl_tls_static_used = %Zu, dl_tls_status_size = %Zu\n",
+                     GL(dl_tls_static_used), GL(dl_tls_static_size));
+
   /* The alignment requirement for the static TLS block.  */
   GL(dl_tls_static_align) = max_align;
 }