dlerror.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* Return error detail for failing <dlfcn.h> functions.
  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 <libintl.h>
  17. #include <stdbool.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <libc-lock.h>
  22. #include <ldsodefs.h>
  23. #include <libc-symbols.h>
  24. #include <assert.h>
  25. #include <dlerror.h>
  26. char *
  27. __dlerror (void)
  28. {
  29. # ifdef SHARED
  30. if (GLRO (dl_dlfcn_hook) != NULL)
  31. return GLRO (dl_dlfcn_hook)->dlerror ();
  32. # endif
  33. struct dl_action_result *result = __libc_dlerror_result;
  34. /* No libdl function has been called. No error is possible. */
  35. if (result == NULL)
  36. return NULL;
  37. /* For an early malloc failure, clear the error flag and return the
  38. error message. This marks the error as delivered. */
  39. if (result == dl_action_result_malloc_failed)
  40. {
  41. __libc_dlerror_result = NULL;
  42. return (char *) "out of memory";
  43. }
  44. /* Placeholder object. This can be observed in a recursive call,
  45. e.g. from an ELF constructor. */
  46. if (result->errstring == NULL)
  47. return NULL;
  48. /* If we have already reported the error, we can free the result and
  49. return NULL. See __libc_dlerror_result_free. */
  50. if (result->returned)
  51. {
  52. __libc_dlerror_result = NULL;
  53. dl_action_result_errstring_free (result);
  54. free (result);
  55. return NULL;
  56. }
  57. assert (result->errstring != NULL);
  58. /* Create the combined error message. */
  59. char *buf;
  60. int n;
  61. if (result->errcode == 0)
  62. n = __asprintf (&buf, "%s%s%s",
  63. result->objname,
  64. result->objname[0] == '\0' ? "" : ": ",
  65. _(result->errstring));
  66. else
  67. {
  68. __set_errno (result->errcode);
  69. n = __asprintf (&buf, "%s%s%s: %m",
  70. result->objname,
  71. result->objname[0] == '\0' ? "" : ": ",
  72. _(result->errstring));
  73. /* Set errno again in case asprintf clobbered it. */
  74. __set_errno (result->errcode);
  75. }
  76. /* Mark the error as delivered. */
  77. result->returned = true;
  78. if (n >= 0)
  79. {
  80. /* Replace the error string with the newly allocated one. */
  81. dl_action_result_errstring_free (result);
  82. result->errstring = buf;
  83. result->errstring_source = dl_action_result_errstring_local;
  84. return buf;
  85. }
  86. else
  87. /* We could not create the combined error message, so use the
  88. existing string as a fallback. */
  89. return result->errstring;
  90. }
  91. versioned_symbol (libc, __dlerror, dlerror, GLIBC_2_34);
  92. #if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_0, GLIBC_2_34)
  93. compat_symbol (libdl, __dlerror, dlerror, GLIBC_2_0);
  94. #endif
  95. int
  96. _dlerror_run (void (*operate) (void *), void *args)
  97. {
  98. struct dl_action_result *result = __libc_dlerror_result;
  99. if (result != NULL)
  100. {
  101. if (result == dl_action_result_malloc_failed)
  102. {
  103. /* Clear the previous error. */
  104. __libc_dlerror_result = NULL;
  105. result = NULL;
  106. }
  107. else
  108. {
  109. /* There is an existing object. Free its error string, but
  110. keep the object. */
  111. dl_action_result_errstring_free (result);
  112. /* Mark the object as not containing an error. This ensures
  113. that call to dlerror from, for example, an ELF
  114. constructor will not notice this result object. */
  115. result->errstring = NULL;
  116. }
  117. }
  118. const char *objname;
  119. const char *errstring;
  120. bool malloced;
  121. int errcode = GLRO (dl_catch_error) (&objname, &errstring, &malloced,
  122. operate, args);
  123. /* ELF constructors or destructors may have indirectly altered the
  124. value of __libc_dlerror_result, therefore reload it. */
  125. result = __libc_dlerror_result;
  126. if (errstring == NULL)
  127. {
  128. /* There is no error. We no longer need the result object if it
  129. does not contain an error. However, a recursive call may
  130. have added an error even if this call did not cause it. Keep
  131. the other error. */
  132. if (result != NULL && result->errstring == NULL)
  133. {
  134. __libc_dlerror_result = NULL;
  135. free (result);
  136. }
  137. return 0;
  138. }
  139. else
  140. {
  141. /* A new error occurred. Check if a result object has to be
  142. allocated. */
  143. if (result == NULL || result == dl_action_result_malloc_failed)
  144. {
  145. /* Allocating storage for the error message after the fact
  146. is not ideal. But this avoids an infinite recursion in
  147. case malloc itself calls libdl functions (without
  148. triggering errors). */
  149. result = malloc (sizeof (*result));
  150. if (result == NULL)
  151. {
  152. /* Assume that the dlfcn failure was due to a malloc
  153. failure, too. */
  154. if (malloced)
  155. dl_error_free ((char *) errstring);
  156. __libc_dlerror_result = dl_action_result_malloc_failed;
  157. return 1;
  158. }
  159. __libc_dlerror_result = result;
  160. }
  161. else
  162. /* Deallocate the existing error message from a recursive
  163. call, but reuse the result object. */
  164. dl_action_result_errstring_free (result);
  165. result->errcode = errcode;
  166. result->objname = objname;
  167. result->errstring = (char *) errstring;
  168. result->returned = false;
  169. /* In case of an error, the malloced flag indicates whether the
  170. error string is constant or not. */
  171. if (malloced)
  172. result->errstring_source = dl_action_result_errstring_rtld;
  173. else
  174. result->errstring_source = dl_action_result_errstring_constant;
  175. return 1;
  176. }
  177. }