Blame elf/tst-glibc-hwcaps-prepend-cache.c

Packit Service 4fe48f
/* Test that --glibc-hwcaps-prepend works, using dlopen and /etc/ld.so.cache.
Packit Service 4fe48f
   Copyright (C) 2020 Free Software Foundation, Inc.
Packit Service 4fe48f
   This file is part of the GNU C Library.
Packit Service 4fe48f
Packit Service 4fe48f
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 4fe48f
   modify it under the terms of the GNU Lesser General Public
Packit Service 4fe48f
   License as published by the Free Software Foundation; either
Packit Service 4fe48f
   version 2.1 of the License, or (at your option) any later version.
Packit Service 4fe48f
Packit Service 4fe48f
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 4fe48f
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4fe48f
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4fe48f
   Lesser General Public License for more details.
Packit Service 4fe48f
Packit Service 4fe48f
   You should have received a copy of the GNU Lesser General Public
Packit Service 4fe48f
   License along with the GNU C Library; if not, see
Packit Service 4fe48f
   <https://www.gnu.org/licenses/>.  */
Packit Service 4fe48f
Packit Service 4fe48f
#include <dlfcn.h>
Packit Service 4fe48f
#include <stddef.h>
Packit Service 4fe48f
#include <stdio.h>
Packit Service 4fe48f
#include <stdlib.h>
Packit Service 4fe48f
#include <string.h>
Packit Service 4fe48f
#include <support/check.h>
Packit Service 4fe48f
#include <support/support.h>
Packit Service 4fe48f
#include <support/xdlfcn.h>
Packit Service 4fe48f
#include <support/xunistd.h>
Packit Service 4fe48f
Packit Service 4fe48f
/* Invoke /sbin/ldconfig with some error checking.  */
Packit Service 4fe48f
static void
Packit Service 4fe48f
run_ldconfig (void)
Packit Service 4fe48f
{
Packit Service 4fe48f
  char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir);
Packit Service 4fe48f
  TEST_COMPARE (system (command), 0);
Packit Service 4fe48f
  free (command);
Packit Service 4fe48f
}
Packit Service 4fe48f
Packit Service 4fe48f
/* The library under test.  */
Packit Service 4fe48f
#define SONAME "libmarkermod1.so"
Packit Service 4fe48f
Packit Service 4fe48f
static int
Packit Service 4fe48f
do_test (void)
Packit Service 4fe48f
{
Packit Service 4fe48f
  if (dlopen (SONAME, RTLD_NOW) != NULL)
Packit Service 4fe48f
    FAIL_EXIT1 (SONAME " is already on the search path");
Packit Service 4fe48f
Packit Service 4fe48f
  /* Install the default implementation of libmarkermod1.so.  */
Packit Service 4fe48f
  xmkdirp ("/etc", 0777);
Packit Service 4fe48f
  support_write_file_string ("/etc/ld.so.conf", "/glibc-test/lib\n");
Packit Service 4fe48f
  xmkdirp ("/glibc-test/lib/glibc-hwcaps/prepend2", 0777);
Packit Service 4fe48f
  xmkdirp ("/glibc-test/lib/glibc-hwcaps/prepend3", 0777);
Packit Service 4fe48f
  {
Packit Service 4fe48f
    char *src = xasprintf ("%s/elf/libmarkermod1-1.so", support_objdir_root);
Packit Service 4fe48f
    support_copy_file (src, "/glibc-test/lib/" SONAME);
Packit Service 4fe48f
    free (src);
Packit Service 4fe48f
  }
Packit Service 4fe48f
  run_ldconfig ();
Packit Service 4fe48f
  {
Packit Service 4fe48f
    /* The default implementation can now be loaded.  */
Packit Service 4fe48f
    void *handle = xdlopen (SONAME, RTLD_NOW);
Packit Service 4fe48f
    int (*marker1) (void) = xdlsym (handle, "marker1");
Packit Service 4fe48f
    TEST_COMPARE (marker1 (), 1);
Packit Service 4fe48f
    xdlclose (handle);
Packit Service 4fe48f
  }
Packit Service 4fe48f
Packit Service 4fe48f
  /* Add the first override to the directory that is searched last.  */
Packit Service 4fe48f
  {
Packit Service 4fe48f
    char *src = xasprintf ("%s/elf/libmarkermod1-2.so", support_objdir_root);
Packit Service 4fe48f
    support_copy_file (src, "/glibc-test/lib/glibc-hwcaps/prepend2/"
Packit Service 4fe48f
                       SONAME);
Packit Service 4fe48f
    free (src);
Packit Service 4fe48f
  }
Packit Service 4fe48f
  {
Packit Service 4fe48f
    /* This is still the first implementation.  The cache has not been
Packit Service 4fe48f
       updated.  */
Packit Service 4fe48f
    void *handle = xdlopen (SONAME, RTLD_NOW);
Packit Service 4fe48f
    int (*marker1) (void) = xdlsym (handle, "marker1");
Packit Service 4fe48f
    TEST_COMPARE (marker1 (), 1);
Packit Service 4fe48f
    xdlclose (handle);
Packit Service 4fe48f
  }
Packit Service 4fe48f
  run_ldconfig ();
Packit Service 4fe48f
  {
Packit Service 4fe48f
    /* After running ldconfig, it is the second implementation.  */
Packit Service 4fe48f
    void *handle = xdlopen (SONAME, RTLD_NOW);
Packit Service 4fe48f
    int (*marker1) (void) = xdlsym (handle, "marker1");
Packit Service 4fe48f
    TEST_COMPARE (marker1 (), 2);
Packit Service 4fe48f
    xdlclose (handle);
Packit Service 4fe48f
  }
Packit Service 4fe48f
Packit Service 4fe48f
  /* Add the second override to the directory that is searched first.  */
Packit Service 4fe48f
  {
Packit Service 4fe48f
    char *src = xasprintf ("%s/elf/libmarkermod1-3.so", support_objdir_root);
Packit Service 4fe48f
    support_copy_file (src, "/glibc-test/lib/glibc-hwcaps/prepend3/"
Packit Service 4fe48f
                       SONAME);
Packit Service 4fe48f
    free (src);
Packit Service 4fe48f
  }
Packit Service 4fe48f
  {
Packit Service 4fe48f
    /* This is still the second implementation.  */
Packit Service 4fe48f
    void *handle = xdlopen (SONAME, RTLD_NOW);
Packit Service 4fe48f
    int (*marker1) (void) = xdlsym (handle, "marker1");
Packit Service 4fe48f
    TEST_COMPARE (marker1 (), 2);
Packit Service 4fe48f
    xdlclose (handle);
Packit Service 4fe48f
  }
Packit Service 4fe48f
  run_ldconfig ();
Packit Service 4fe48f
  {
Packit Service 4fe48f
    /* After running ldconfig, it is the third implementation.  */
Packit Service 4fe48f
    void *handle = xdlopen (SONAME, RTLD_NOW);
Packit Service 4fe48f
    int (*marker1) (void) = xdlsym (handle, "marker1");
Packit Service 4fe48f
    TEST_COMPARE (marker1 (), 3);
Packit Service 4fe48f
    xdlclose (handle);
Packit Service 4fe48f
  }
Packit Service 4fe48f
Packit Service 4fe48f
  /* Remove the second override again, without running ldconfig.
Packit Service 4fe48f
     Ideally, this would revert to implementation 2.  However, in the
Packit Service 4fe48f
     current implementation, the cache returns exactly one file name
Packit Service 4fe48f
     which does not exist after unlinking, so the dlopen fails.  */
Packit Service 4fe48f
  xunlink ("/glibc-test/lib/glibc-hwcaps/prepend3/" SONAME);
Packit Service 4fe48f
  TEST_VERIFY (dlopen (SONAME, RTLD_NOW) == NULL);
Packit Service 4fe48f
  run_ldconfig ();
Packit Service 4fe48f
  {
Packit Service 4fe48f
    /* After running ldconfig, the second implementation is available
Packit Service 4fe48f
       once more.  */
Packit Service 4fe48f
    void *handle = xdlopen (SONAME, RTLD_NOW);
Packit Service 4fe48f
    int (*marker1) (void) = xdlsym (handle, "marker1");
Packit Service 4fe48f
    TEST_COMPARE (marker1 (), 2);
Packit Service 4fe48f
    xdlclose (handle);
Packit Service 4fe48f
  }
Packit Service 4fe48f
Packit Service 4fe48f
  return 0;
Packit Service 4fe48f
}
Packit Service 4fe48f
Packit Service 4fe48f
static void
Packit Service 4fe48f
prepare (int argc, char **argv)
Packit Service 4fe48f
{
Packit Service 4fe48f
  const char *no_restart = "no-restart";
Packit Service 4fe48f
  if (argc == 2 && strcmp (argv[1], no_restart) == 0)
Packit Service 4fe48f
    return;
Packit Service 4fe48f
  /* Re-execute the test with an explicit loader invocation.  */
Packit Service 4fe48f
  execl (support_objdir_elf_ldso,
Packit Service 4fe48f
         support_objdir_elf_ldso,
Packit Service 4fe48f
         "--glibc-hwcaps-prepend", "prepend3:prepend2",
Packit Service 4fe48f
         argv[0], no_restart,
Packit Service 4fe48f
         NULL);
Packit Service 4fe48f
  printf ("error: execv of %s failed: %m\n", argv[0]);
Packit Service 4fe48f
  _exit (1);
Packit Service 4fe48f
}
Packit Service 4fe48f
Packit Service 4fe48f
#define PREPARE prepare
Packit Service 4fe48f
#include <support/test-driver.c>