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

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