(root)/
glibc-2.38/
elf/
tst-dlsym-error.c
       1  /* Test error reporting for dlsym, dlvsym failures.
       2     Copyright (C) 2016-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <dlfcn.h>
      20  #include <gnu/lib-names.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  
      25  /* Used to disambiguate symbol names.  */
      26  static int counter;
      27  
      28  static void
      29  test_one (void *handle, const char *name, void *(func) (void *, const char *),
      30            const char *suffix)
      31  {
      32    ++counter;
      33    char symbol[32];
      34    snprintf (symbol, sizeof (symbol), "no_such_symbol_%d", counter);
      35    char *expected_message;
      36    if (asprintf (&expected_message, ": undefined symbol: %s%s",
      37                  symbol, suffix) < 0)
      38      {
      39        printf ("error: asprintf: %m\n");
      40        abort ();
      41      }
      42  
      43    void *addr = func (handle, symbol);
      44    if (addr != NULL)
      45      {
      46        printf ("error: %s: found symbol \"no_such_symbol\"\n", name);
      47        abort ();
      48      }
      49    const char *message = dlerror ();
      50    if (message == NULL)
      51      {
      52        printf ("error: %s: missing error message\n", name);
      53        abort ();
      54      }
      55    const char *message_without_path = strchrnul (message, ':');
      56    if (strcmp (message_without_path, expected_message) != 0)
      57      {
      58        printf ("error: %s: unexpected error message: %s\n", name, message);
      59        abort ();
      60      }
      61    free (expected_message);
      62  
      63    message = dlerror ();
      64    if (message != NULL)
      65      {
      66        printf ("error: %s: unexpected error message: %s\n", name, message);
      67        abort ();
      68      }
      69  }
      70  
      71  static void
      72  test_handles (const char *name, void *(func) (void *, const char *),
      73                const char *suffix)
      74  {
      75    test_one (RTLD_DEFAULT, name, func, suffix);
      76    test_one (RTLD_NEXT, name, func, suffix);
      77  
      78    void *handle = dlopen (LIBC_SO, RTLD_LAZY);
      79    if (handle == NULL)
      80      {
      81        printf ("error: cannot dlopen %s: %s\n", LIBC_SO, dlerror ());
      82        abort ();
      83      }
      84    test_one (handle, name, func, suffix);
      85    dlclose (handle);
      86  }
      87  
      88  static void *
      89  dlvsym_no_such_version (void *handle, const char *name)
      90  {
      91    return dlvsym (handle, name, "NO_SUCH_VERSION");
      92  }
      93  
      94  static void *
      95  dlvsym_glibc_private (void *handle, const char *name)
      96  {
      97    return dlvsym (handle, name, "GLIBC_PRIVATE");
      98  }
      99  
     100  static int
     101  do_test (void)
     102  {
     103    test_handles ("dlsym", dlsym, "");
     104    test_handles ("dlvsym", dlvsym_no_such_version,
     105                  ", version NO_SUCH_VERSION");
     106    test_handles ("dlvsym", dlvsym_glibc_private,
     107                  ", version GLIBC_PRIVATE");
     108  
     109    return 0;
     110  }
     111  
     112  
     113  #include <support/test-driver.c>