Blame elf/tst-libc_dlvsym.h

Packit 6c4009
/* Compare dlvsym and __libc_dlvsym results.  Common code.
Packit 6c4009
   Copyright (C) 2017 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* compare_vsyms is the main entry point for these tests.
Packit 6c4009
Packit 6c4009
   Indirectly, It calls __libc_dlvsym (from libc.so; internal
Packit 6c4009
   interface) and dlvsym (from libdl.so; public interface) to compare
Packit 6c4009
   the results for a selected set of symbols in libc.so which
Packit 6c4009
   typically have more than one symbol version.  The two functions are
Packit 6c4009
   implemented by somewhat different code, and this test checks that
Packit 6c4009
   their results are the same.
Packit 6c4009
Packit 6c4009
   The versions are generated to range from GLIBC_2.0 to GLIBC_2.Y,
Packit 6c4009
   with Y being the current __GLIBC_MINOR__ version plus two.  In
Packit 6c4009
   addition, there is a list of special symbol versions of the form
Packit 6c4009
   GLIBC_2.Y.Z, which were used for some releases.
Packit 6c4009
Packit 6c4009
   Comparing the two dlvsym results at versions which do not actually
Packit 6c4009
   exist does not test much, but it will not contribute to false test
Packit 6c4009
   failures, either.  */
Packit 6c4009
Packit 6c4009
#include <array_length.h>
Packit 6c4009
#include <gnu/lib-names.h>
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <support/check.h>
Packit 6c4009
#include <support/xdlfcn.h>
Packit 6c4009
Packit 6c4009
/* Run consistency check for versioned symbol NAME@VERSION.  NB: We
Packit 6c4009
   may execute in a shared object, so exit on error for proper error
Packit 6c4009
   reporting.  */
Packit 6c4009
static void
Packit 6c4009
compare_vsyms_0 (void *libc_handle, const char *name, const char *version,
Packit 6c4009
                 bool *pfound)
Packit 6c4009
{
Packit 6c4009
  void *dlvsym_address = dlvsym (libc_handle, name, version);
Packit 6c4009
  void *libc_dlvsym_address
Packit 6c4009
    = __libc_dlvsym (libc_handle, name, version);
Packit 6c4009
  if (dlvsym_address != libc_dlvsym_address)
Packit 6c4009
    FAIL_EXIT1 ("%s@%s mismatch: %p != %p",
Packit 6c4009
                name, version, dlvsym_address, libc_dlvsym_address);
Packit 6c4009
  if (dlvsym_address != NULL)
Packit 6c4009
    *pfound = true;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Run consistency check for versioned symbol NAME at multiple symbol
Packit 6c4009
   version.  */
Packit 6c4009
static void
Packit 6c4009
compare_vsyms_1 (void *libc_handle, const char *name)
Packit 6c4009
{
Packit 6c4009
  bool found = false;
Packit 6c4009
Packit 6c4009
  /* Historic versions which do not follow the usual GLIBC_2.Y
Packit 6c4009
     pattern, to increase test coverage.  Not all architectures have
Packit 6c4009
     those, but probing additional versions does not hurt.  */
Packit 6c4009
  static const char special_versions[][12] =
Packit 6c4009
    {
Packit 6c4009
      "GLIBC_2.1.1",
Packit 6c4009
      "GLIBC_2.1.2",
Packit 6c4009
      "GLIBC_2.1.3",
Packit 6c4009
      "GLIBC_2.1.4",
Packit 6c4009
      "GLIBC_2.2.1",
Packit 6c4009
      "GLIBC_2.2.2",
Packit 6c4009
      "GLIBC_2.2.3",
Packit 6c4009
      "GLIBC_2.2.4",
Packit 6c4009
      "GLIBC_2.2.5",
Packit 6c4009
      "GLIBC_2.2.6",
Packit 6c4009
      "GLIBC_2.3.2",
Packit 6c4009
      "GLIBC_2.3.3",
Packit 6c4009
      "GLIBC_2.3.4",
Packit 6c4009
    };
Packit 6c4009
  for (int i = 0; i < array_length (special_versions); ++i)
Packit 6c4009
    compare_vsyms_0 (libc_handle, name, special_versions[i], &found);
Packit 6c4009
Packit 6c4009
  /* Iterate to an out-of-range version, to cover some unused symbols
Packit 6c4009
     as well.  */
Packit 6c4009
  for (int minor_version = 0; minor_version <= __GLIBC_MINOR__ + 2;
Packit 6c4009
       ++minor_version)
Packit 6c4009
    {
Packit 6c4009
      char version[30];
Packit 6c4009
      snprintf (version, sizeof (version), "GLIBC_%d.%d",
Packit 6c4009
                __GLIBC__, minor_version);
Packit 6c4009
      compare_vsyms_0 (libc_handle, name, version, &found);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (!found)
Packit 6c4009
    FAIL_EXIT1 ("symbol %s not found at any version", name);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Run consistency checks for various symbols which usually have
Packit 6c4009
   multiple versions.  */
Packit 6c4009
static void
Packit 6c4009
compare_vsyms (void)
Packit 6c4009
{
Packit 6c4009
  /* The minor version loop in compare_vsyms_1 needs updating in case
Packit 6c4009
     we ever switch to glibc 3.0.  */
Packit 6c4009
  if (__GLIBC__ != 2)
Packit 6c4009
    FAIL_EXIT1 ("unexpected glibc major version: %d", __GLIBC__);
Packit 6c4009
Packit 6c4009
  /* __libc_dlvsym does not recognize the special RTLD_* handles, so
Packit 6c4009
     obtain an explicit handle for libc.so.  */
Packit 6c4009
  void *libc_handle = xdlopen (LIBC_SO, RTLD_LAZY | RTLD_NOLOAD);
Packit 6c4009
Packit 6c4009
  compare_vsyms_1 (libc_handle, "_sys_errlist");
Packit 6c4009
  compare_vsyms_1 (libc_handle, "_sys_siglist");
Packit 6c4009
  compare_vsyms_1 (libc_handle, "quick_exit");
Packit 6c4009
Packit 6c4009
  xdlclose (libc_handle);
Packit 6c4009
}