dlvsym.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* Look up a versioned symbol in a shared object loaded by `dlopen'.
  2. Copyright (C) 1995-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <dlfcn.h>
  16. #include <ldsodefs.h>
  17. #include <shlib-compat.h>
  18. #include <stddef.h>
  19. struct dlvsym_args
  20. {
  21. /* The arguments to dlvsym_doit. */
  22. void *handle;
  23. const char *name;
  24. const char *version;
  25. void *who;
  26. /* The return values of dlvsym_doit. */
  27. void *sym;
  28. };
  29. static void
  30. dlvsym_doit (void *a)
  31. {
  32. struct dlvsym_args *args = (struct dlvsym_args *) a;
  33. args->sym = _dl_vsym (args->handle, args->name, args->version, args->who);
  34. }
  35. static void *
  36. dlvsym_implementation (void *handle, const char *name, const char *version,
  37. void *dl_caller)
  38. {
  39. struct dlvsym_args args;
  40. args.who = dl_caller;
  41. args.handle = handle;
  42. args.name = name;
  43. args.version = version;
  44. /* Protect against concurrent loads and unloads. */
  45. __rtld_lock_lock_recursive (GL(dl_load_lock));
  46. void *result = (_dlerror_run (dlvsym_doit, &args) ? NULL : args.sym);
  47. __rtld_lock_unlock_recursive (GL(dl_load_lock));
  48. return result;
  49. }
  50. #ifdef SHARED
  51. void *
  52. ___dlvsym (void *handle, const char *name, const char *version)
  53. {
  54. if (GLRO (dl_dlfcn_hook) != NULL)
  55. return GLRO (dl_dlfcn_hook)->dlvsym (handle, name, version,
  56. RETURN_ADDRESS (0));
  57. else
  58. return dlvsym_implementation (handle, name, version, RETURN_ADDRESS (0));
  59. }
  60. versioned_symbol (libc, ___dlvsym, dlvsym, GLIBC_2_34);
  61. # if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_1, GLIBC_2_34)
  62. compat_symbol (libdl, ___dlvsym, dlvsym, GLIBC_2_1);
  63. # endif
  64. #else /* !SHARED */
  65. /* Also used with _dlfcn_hook. */
  66. void *
  67. __dlvsym (void *handle, const char *name, const char *version, void *dl_caller)
  68. {
  69. return dlvsym_implementation (handle, name, version, dl_caller);
  70. }
  71. void *
  72. ___dlvsym (void *handle, const char *name, const char *version)
  73. {
  74. return __dlvsym (handle, name, version, RETURN_ADDRESS (0));
  75. }
  76. weak_alias (___dlvsym, dlvsym)
  77. #endif /* !SHARED */