dlfcn.cpp 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright (c) 2021, Gunnar Beutner <gunnar@beutner.name>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/DeprecatedString.h>
  7. #include <AK/Types.h>
  8. #include <bits/dlfcn_integration.h>
  9. #include <dlfcn.h>
  10. #include <string.h>
  11. // These are filled in by the dynamic loader.
  12. DlCloseFunction __dlclose;
  13. DlOpenFunction __dlopen;
  14. DlSymFunction __dlsym;
  15. DlAddrFunction __dladdr;
  16. // FIXME: use thread_local and a String once TLS works
  17. #ifdef NO_TLS
  18. char* s_dlerror_text = NULL;
  19. bool s_dlerror_retrieved = false;
  20. #else
  21. __thread char* s_dlerror_text = NULL;
  22. __thread bool s_dlerror_retrieved = false;
  23. #endif
  24. static void store_error(DeprecatedString const& error)
  25. {
  26. free(s_dlerror_text);
  27. s_dlerror_text = strdup(error.characters());
  28. s_dlerror_retrieved = false;
  29. }
  30. int dlclose(void* handle)
  31. {
  32. auto result = __dlclose(handle);
  33. if (result.is_error()) {
  34. store_error(result.error().text);
  35. return -1;
  36. }
  37. return 0;
  38. }
  39. char* dlerror()
  40. {
  41. if (s_dlerror_retrieved) {
  42. free(s_dlerror_text);
  43. s_dlerror_text = nullptr;
  44. }
  45. s_dlerror_retrieved = true;
  46. return const_cast<char*>(s_dlerror_text);
  47. }
  48. void* dlopen(char const* filename, int flags)
  49. {
  50. auto result = __dlopen(filename, flags);
  51. if (result.is_error()) {
  52. store_error(result.error().text);
  53. return nullptr;
  54. }
  55. return result.value();
  56. }
  57. void* dlsym(void* handle, char const* symbol_name)
  58. {
  59. auto result = __dlsym(handle, symbol_name);
  60. if (result.is_error()) {
  61. store_error(result.error().text);
  62. return nullptr;
  63. }
  64. return result.value();
  65. }
  66. int dladdr(void* addr, Dl_info* info)
  67. {
  68. auto result = __dladdr(addr, info);
  69. if (result.is_error()) {
  70. // FIXME: According to the man page glibc does _not_ make the error
  71. // available via dlerror(), however we do. Does this break anything?
  72. store_error(result.error().text);
  73. return 0;
  74. }
  75. return 1;
  76. }