2 # Based on this upstream commit:
4 # commit d8dd00805b8f3a011735d7a407097fb1c408d867
5 # Author: H.J. Lu <hjl.tools@gmail.com>
6 # Date: Fri Nov 28 07:54:07 2014 -0800
8 # Resize DTV if the current DTV isn't big enough
10 # This patch changes _dl_allocate_tls_init to resize DTV if the current DTV
11 # isn't big enough. Tested on X86-64, x32 and ia32.
14 # * elf/dl-tls.c: Include <atomic.h>.
15 # (oom): Remove #ifdef SHARED/#endif.
16 # (_dl_static_dtv, _dl_initial_dtv): Moved before ...
17 # (_dl_resize_dtv): This. Extracted from _dl_update_slotinfo.
18 # (_dl_allocate_tls_init): Resize DTV if the current DTV isn't
20 # (_dl_update_slotinfo): Call _dl_resize_dtv to resize DTV.
21 # * nptl/Makefile (tests): Add tst-stack4.
22 # (modules-names): Add tst-stack4mod.
23 # ($(objpfx)tst-stack4): New.
24 # (tst-stack4mod.sos): Likewise.
25 # ($(objpfx)tst-stack4.out): Likewise.
26 # ($(tst-stack4mod.sos)): Likewise.
28 # * nptl/tst-stack4.c: New file.
29 # * nptl/tst-stack4mod.c: Likewise.
31 diff -urN glibc-2.12-2-gc4ccff1/elf/dl-tls.c glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c
32 --- glibc-2.12-2-gc4ccff1/elf/dl-tls.c 2015-02-18 14:15:28.078461873 -0500
33 +++ glibc-2.12-2-gc4ccff1.mod/elf/dl-tls.c 2015-02-18 14:38:37.630374771 -0500
37 #include <sys/param.h>
45 /* Out-of-memory handler. */
48 __attribute__ ((__noreturn__))
51 _dl_fatal_printf ("cannot allocate memory for thread-local data: ABORT\n");
62 +_dl_resize_dtv (dtv_t *dtv)
64 + /* Resize the dtv. */
66 + /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
67 + other threads concurrently. -- We don't have the required atomic
68 + infrastructure to load dl_tls_max_dtv_idx atomically, but on all the
69 + architectures we care about it should load atomically. If this had
70 + an atomic_load_acquire we would still be missing the releases for
72 + size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
73 + size_t oldsize = dtv[-1].counter;
76 + if (dtv == GL(dl_initial_dtv))
78 + /* This is the initial dtv that was either statically allocated in
79 + __libc_setup_tls or allocated during rtld startup using the
80 + dl-minimal.c malloc instead of the real malloc. We can't free
81 + it, we have to abandon the old storage. */
83 + newp = malloc ((2 + newsize) * sizeof (dtv_t));
86 + memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
91 + newp = realloc (&dtv[-1],
92 + (2 + newsize) * sizeof (dtv_t));
97 + newp[0].counter = newsize;
99 + /* Clear the newly allocated part. */
100 + memset (newp + 2 + oldsize, '\0',
101 + (newsize - oldsize) * sizeof (dtv_t));
103 + /* Return the generation counter. */
114 + /* Check if the current dtv is big enough. */
115 + if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
117 + /* Resize the dtv. */
118 + dtv = _dl_resize_dtv (dtv);
120 + /* Install this new dtv in the thread data structures. */
121 + INSTALL_DTV (result, &dtv[-1]);
124 /* We have to prepare the dtv for all currently loaded modules using
125 TLS. For those which are dynamically loaded we add the values
126 indicating deferred allocation. */
127 @@ -637,41 +692,10 @@
128 assert (total + cnt == modid);
129 if (dtv[-1].counter < modid)
131 - /* Reallocate the dtv. */
133 - size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
134 - size_t oldsize = dtv[-1].counter;
136 - assert (map->l_tls_modid <= newsize);
138 - if (dtv == GL(dl_initial_dtv))
140 - /* This is the initial dtv that was allocated
141 - during rtld startup using the dl-minimal.c
142 - malloc instead of the real malloc. We can't
143 - free it, we have to abandon the old storage. */
145 - newp = malloc ((2 + newsize) * sizeof (dtv_t));
148 - memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
152 - newp = realloc (&dtv[-1],
153 - (2 + newsize) * sizeof (dtv_t));
158 - newp[0].counter = newsize;
160 - /* Clear the newly allocated part. */
161 - memset (newp + 2 + oldsize, '\0',
162 - (newsize - oldsize) * sizeof (dtv_t));
163 + /* Resize the dtv. */
164 + dtv = _dl_resize_dtv (dtv);
166 - /* Point dtv to the generation counter. */
168 + assert (modid <= dtv[-1].counter);
170 /* Install this new dtv in the thread data
172 diff -urN glibc-2.12-2-gc4ccff1/nptl/Makefile glibc-2.12-2-gc4ccff1.mod/nptl/Makefile
173 --- glibc-2.12-2-gc4ccff1/nptl/Makefile 2015-02-18 14:15:28.073462028 -0500
174 +++ glibc-2.12-2-gc4ccff1.mod/nptl/Makefile 2015-02-18 14:15:49.817786667 -0500
176 tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
177 tst-exit1 tst-exit2 tst-exit3 \
178 tst-stdio1 tst-stdio2 \
179 - tst-stack1 tst-stack2 tst-stack3 \
180 + tst-stack1 tst-stack2 tst-stack3 tst-stack4 \
186 modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
187 tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
188 - tst-tls5modd tst-tls5mode tst-tls5modf \
189 + tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
190 tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
191 extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
192 test-extras += $(modules-names)
194 $(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@
195 generated += tst-stack3-mem tst-stack3.mtrace
197 +$(objpfx)tst-stack4: $(libdl) $(shared-thread-library)
198 +tst-stack4mod.sos=$(shell for i in 0 1 2 3 4 5 6 7 8 9 10 \
199 + 11 12 13 14 15 16 17 18 19; do \
200 + for j in 0 1 2 3 4 5 6 7 8 9 10 \
201 + 11 12 13 14 15 16 17 18 19; do \
202 + echo $(objpfx)tst-stack4mod-$$i-$$j.so; \
204 +$(objpfx)tst-stack4.out: $(tst-stack4mod.sos)
205 +$(tst-stack4mod.sos): $(objpfx)tst-stack4mod.so
208 + rm -f $(tst-stack4mod.sos)
210 $(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
211 $(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
213 diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c
214 --- glibc-2.12-2-gc4ccff1/nptl/tst-stack4.c 1969-12-31 19:00:00.000000000 -0500
215 +++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4.c 2015-02-18 14:15:49.817786667 -0500
217 +/* Test DTV size oveflow when pthread_create reuses old DTV and TLS is
218 + used by dlopened shared object.
219 + Copyright (C) 2014 Free Software Foundation, Inc.
220 + This file is part of the GNU C Library.
222 + The GNU C Library is free software; you can redistribute it and/or
223 + modify it under the terms of the GNU Lesser General Public
224 + License as published by the Free Software Foundation; either
225 + version 2.1 of the License, or (at your option) any later version.
227 + The GNU C Library is distributed in the hope that it will be useful,
228 + but WITHOUT ANY WARRANTY; without even the implied warranty of
229 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
230 + Lesser General Public License for more details.
232 + You should have received a copy of the GNU Lesser General Public
233 + License along with the GNU C Library; if not, see
234 + <http://www.gnu.org/licenses/>. */
240 +#include <pthread.h>
242 +/* The choices of thread count, and file counts are arbitary.
243 + The point is simply to run enough threads that an exiting
244 + thread has it's stack reused by another thread at the same
245 + time as new libraries have been loaded. */
246 +#define DSO_SHARED_FILES 20
247 +#define DSO_OPEN_THREADS 20
248 +#define DSO_EXEC_THREADS 2
250 +/* Used to make sure that only one thread is calling dlopen and dlclose
252 +pthread_mutex_t g_lock;
254 +typedef void (*function) (void);
257 +dso_invoke(void *dso_fun)
259 + function *fun_vec = (function *) dso_fun;
262 + for (dso = 0; dso < DSO_SHARED_FILES; dso++)
263 + (*fun_vec[dso]) ();
265 + pthread_exit (NULL);
269 +dso_process (void * p)
271 + void *handle[DSO_SHARED_FILES];
272 + function fun_vec[DSO_SHARED_FILES];
273 + char dso_path[DSO_SHARED_FILES][100];
275 + uintptr_t t = (uintptr_t) p;
277 + /* Open DSOs and get a function. */
278 + for (dso = 0; dso < DSO_SHARED_FILES; dso++)
280 + sprintf (dso_path[dso], "tst-stack4mod-%i-%i.so", t, dso);
282 + pthread_mutex_lock (&g_lock);
284 + handle[dso] = dlopen (dso_path[dso], RTLD_NOW);
285 + assert (handle[dso]);
287 + fun_vec[dso] = (function) dlsym (handle[dso], "function");
288 + assert (fun_vec[dso]);
290 + pthread_mutex_unlock (&g_lock);
293 + /* Spawn workers. */
294 + pthread_t thread[DSO_EXEC_THREADS];
296 + uintptr_t result = 0;
297 + for (i = 0; i < DSO_EXEC_THREADS; i++)
299 + pthread_mutex_lock (&g_lock);
300 + ret = pthread_create (&thread[i], NULL, dso_invoke, (void *) fun_vec);
303 + printf ("pthread_create failed: %d\n", ret);
306 + pthread_mutex_unlock (&g_lock);
310 + for (i = 0; i < DSO_EXEC_THREADS; i++)
312 + ret = pthread_join (thread[i], NULL);
315 + printf ("pthread_join failed: %d\n", ret);
320 + /* Close all DSOs. */
321 + for (dso = 0; dso < DSO_SHARED_FILES; dso++)
323 + pthread_mutex_lock (&g_lock);
324 + dlclose (handle[dso]);
325 + pthread_mutex_unlock (&g_lock);
329 + pthread_exit ((void *) result);
335 + pthread_t thread[DSO_OPEN_THREADS];
340 + pthread_mutex_init (&g_lock, NULL);
342 + /* 100 is arbitrary here and is known to trigger PR 13862. */
343 + for (j = 0; j < 100; j++)
345 + for (i = 0; i < DSO_OPEN_THREADS; i++)
347 + ret = pthread_create (&thread[i], NULL, dso_process,
348 + (void *) (uintptr_t) i);
351 + printf ("pthread_create failed: %d\n", ret);
359 + for (i = 0; i < DSO_OPEN_THREADS; i++)
361 + ret = pthread_join (thread[i], NULL);
364 + printf ("pthread_join failed: %d\n", ret);
373 +#define TEST_FUNCTION do_test ()
375 +#include "../test-skeleton.c"
376 diff -urN glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c
377 --- glibc-2.12-2-gc4ccff1/nptl/tst-stack4mod.c 1969-12-31 19:00:00.000000000 -0500
378 +++ glibc-2.12-2-gc4ccff1.mod/nptl/tst-stack4mod.c 2015-02-18 14:15:49.817786667 -0500
380 +/* This tests DTV usage with TLS in dlopened shared object.
381 + Copyright (C) 2014 Free Software Foundation, Inc.
382 + This file is part of the GNU C Library.
384 + The GNU C Library is free software; you can redistribute it and/or
385 + modify it under the terms of the GNU Lesser General Public
386 + License as published by the Free Software Foundation; either
387 + version 2.1 of the License, or (at your option) any later version.
389 + The GNU C Library is distributed in the hope that it will be useful,
390 + but WITHOUT ANY WARRANTY; without even the implied warranty of
391 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
392 + Lesser General Public License for more details.
394 + You should have received a copy of the GNU Lesser General Public
395 + License along with the GNU C Library; if not, see
396 + <http://www.gnu.org/licenses/>. */
398 +/* 256 is arbitrary here and is known to trigger PR 13862. */
399 +__thread int var[256] attribute_hidden = {0};
405 + for (i = 0; i < sizeof (var) / sizeof (int); i++)