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

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