Blame elf/tst-tls-ie-dlmopen.c

Packit Service d1bc19
/* Test dlopen of modules with initial-exec TLS after dlmopen.
Packit Service d1bc19
   Copyright (C) 2016-2020 Free Software Foundation, Inc.
Packit Service d1bc19
   This file is part of the GNU C Library.
Packit Service d1bc19
Packit Service d1bc19
   The GNU C Library is free software; you can redistribute it and/or
Packit Service d1bc19
   modify it under the terms of the GNU Lesser General Public
Packit Service d1bc19
   License as published by the Free Software Foundation; either
Packit Service d1bc19
   version 2.1 of the License, or (at your option) any later version.
Packit Service d1bc19
Packit Service d1bc19
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service d1bc19
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service d1bc19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service d1bc19
   Lesser General Public License for more details.
Packit Service d1bc19
Packit Service d1bc19
   You should have received a copy of the GNU Lesser General Public
Packit Service d1bc19
   License along with the GNU C Library; if not, see
Packit Service d1bc19
   <https://www.gnu.org/licenses/>.  */
Packit Service d1bc19
Packit Service d1bc19
/* This test tries to check that surplus static TLS is not used up for
Packit Service d1bc19
   dynamic TLS optimizations and 4*144 = 576 bytes of static TLS is
Packit Service d1bc19
   still available for dlopening modules with initial-exec TLS after 3
Packit Service d1bc19
   new dlmopen namespaces are created.  It depends on rtld.nns=4 and
Packit Service d1bc19
   rtld.optional_static_tls=512 tunable settings.  */
Packit Service d1bc19
Packit Service d1bc19
#include <errno.h>
Packit Service d1bc19
#include <pthread.h>
Packit Service d1bc19
#include <stdio.h>
Packit Service d1bc19
#include <stdlib.h>
Packit Service d1bc19
#include <string.h>
Packit Service d1bc19
Packit Service d1bc19
static int do_test (void);
Packit Service d1bc19
#include <support/xthread.h>
Packit Service d1bc19
#include <support/xdlfcn.h>
Packit Service d1bc19
#include <support/check.h>
Packit Service d1bc19
#include <support/test-driver.c>
Packit Service d1bc19
Packit Service d1bc19
/* Have some big TLS in the main exe: should not use surplus TLS.  */
Packit Service d1bc19
__thread char maintls[1000];
Packit Service d1bc19
Packit Service d1bc19
static pthread_barrier_t barrier;
Packit Service d1bc19
Packit Service d1bc19
/* Forces multi-threaded behaviour.  */
Packit Service d1bc19
static void *
Packit Service d1bc19
blocked_thread_func (void *closure)
Packit Service d1bc19
{
Packit Service d1bc19
  xpthread_barrier_wait (&barrier);
Packit Service d1bc19
  /* TLS load and access tests run here in the main thread.  */
Packit Service d1bc19
  xpthread_barrier_wait (&barrier);
Packit Service d1bc19
  return NULL;
Packit Service d1bc19
}
Packit Service d1bc19
Packit Service d1bc19
static void *
Packit Service d1bc19
load_and_access (Lmid_t lmid, const char *mod, const char *func)
Packit Service d1bc19
{
Packit Service d1bc19
  /* Load module with TLS.  */
Packit Service d1bc19
  void *p = xdlmopen (lmid, mod, RTLD_NOW);
Packit Service d1bc19
  /* Access the TLS variable to ensure it is allocated.  */
Packit Service d1bc19
  void (*f) (void) = (void (*) (void))xdlsym (p, func);
Packit Service d1bc19
  f ();
Packit Service d1bc19
  return p;
Packit Service d1bc19
}
Packit Service d1bc19
Packit Service d1bc19
static int
Packit Service d1bc19
do_test (void)
Packit Service d1bc19
{
Packit Service d1bc19
  void *mods[5];
Packit Service d1bc19
Packit Service d1bc19
  {
Packit Service d1bc19
    int ret = pthread_barrier_init (&barrier, NULL, 2);
Packit Service d1bc19
    if (ret != 0)
Packit Service d1bc19
      {
Packit Service d1bc19
        errno = ret;
Packit Service d1bc19
        printf ("error: pthread_barrier_init: %m\n");
Packit Service d1bc19
        exit (1);
Packit Service d1bc19
      }
Packit Service d1bc19
  }
Packit Service d1bc19
Packit Service d1bc19
  pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL);
Packit Service d1bc19
  xpthread_barrier_wait (&barrier);
Packit Service d1bc19
Packit Service d1bc19
  printf ("maintls[%zu]:\t %p .. %p\n",
Packit Service d1bc19
	   sizeof maintls, maintls, maintls + sizeof maintls);
Packit Service d1bc19
  memset (maintls, 1, sizeof maintls);
Packit Service d1bc19
Packit Service d1bc19
  /* Load modules with dynamic TLS (use surplus static TLS for libc
Packit Service d1bc19
     in new namespaces and may be for TLS optimizations too).  */
Packit Service d1bc19
  mods[0] = load_and_access (LM_ID_BASE, "tst-tls-ie-mod0.so", "access0");
Packit Service d1bc19
  mods[1] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod1.so", "access1");
Packit Service d1bc19
  mods[2] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod2.so", "access2");
Packit Service d1bc19
  mods[3] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod3.so", "access3");
Packit Service d1bc19
  /* Load modules with initial-exec TLS (can only use surplus static TLS).  */
Packit Service d1bc19
  mods[4] = load_and_access (LM_ID_BASE, "tst-tls-ie-mod6.so", "access6");
Packit Service d1bc19
Packit Service d1bc19
  /* Here 576 bytes + 3 * libc use of surplus static TLS is in use so less
Packit Service d1bc19
     than 1024 bytes are available (exact number depends on TLS optimizations
Packit Service d1bc19
     and the libc TLS use).  */
Packit Service d1bc19
  printf ("The next dlmopen should fail...\n");
Packit Service d1bc19
  void *p = dlmopen (LM_ID_BASE, "tst-tls-ie-mod4.so", RTLD_NOW);
Packit Service d1bc19
  if (p != NULL)
Packit Service d1bc19
    FAIL_EXIT1 ("error: expected dlmopen to fail because there is "
Packit Service d1bc19
		"not enough surplus static TLS.\n");
Packit Service d1bc19
  printf ("...OK failed with: %s.\n", dlerror ());
Packit Service d1bc19
Packit Service d1bc19
  xpthread_barrier_wait (&barrier);
Packit Service d1bc19
  xpthread_join (blocked_thread);
Packit Service d1bc19
Packit Service d1bc19
  /* Close the modules.  */
Packit Service d1bc19
  for (int i = 0; i < 5; ++i)
Packit Service d1bc19
    xdlclose (mods[i]);
Packit Service d1bc19
Packit Service d1bc19
  return 0;
Packit Service d1bc19
}