Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
3.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Shared library loading and symbol lookup.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "pch_tier0.h"
  8. #include "tier0/dynfunction.h"
  9. #if defined(WIN32)
  10. typedef HMODULE LibraryHandle;
  11. #define LoadLibraryHandle(libname) LoadLibrary(libname)
  12. #define CloseLibraryHandle(handle) FreeLibrary(handle)
  13. #define LookupInLibraryHandle(handle, fn) GetProcAddress(handle, fn)
  14. #elif defined(POSIX)
  15. #include <dlfcn.h>
  16. typedef void *LibraryHandle;
  17. #define LoadLibraryHandle(libname) dlopen(libname, RTLD_NOW)
  18. #define CloseLibraryHandle(handle) dlclose(handle)
  19. #define LookupInLibraryHandle(handle, fn) dlsym(handle, fn)
  20. #else
  21. #error Please define your platform.
  22. #endif
  23. #if 1
  24. static inline void dbgdynfn(const char *fmt, ...) {}
  25. #else
  26. #define dbgdynfn printf
  27. #endif
  28. // NOTE: This has to be the last file included!
  29. #include "tier0/memdbgon.h"
  30. class CSharedLibraryCache
  31. {
  32. public:
  33. static CSharedLibraryCache &GetCache()
  34. {
  35. static CSharedLibraryCache Singleton;
  36. return Singleton;
  37. }
  38. struct CSharedLibraryItem
  39. {
  40. CSharedLibraryItem(LibraryHandle handle, const char *name)
  41. {
  42. m_handle = handle;
  43. m_name = new char[strlen(name) + 1];
  44. m_next = NULL;
  45. strcpy(m_name, name);
  46. }
  47. ~CSharedLibraryItem()
  48. {
  49. dbgdynfn("CDynamicFunction: Closing library '%s' (%p)\n", m_name, (void *) m_handle);
  50. CloseLibraryHandle(m_handle);
  51. delete[] m_name;
  52. delete m_next;
  53. }
  54. char *m_name;
  55. CSharedLibraryItem *m_next;
  56. LibraryHandle m_handle;
  57. };
  58. CSharedLibraryCache() : m_pList(NULL) {}
  59. ~CSharedLibraryCache() { CloseAllLibraries(); }
  60. LibraryHandle GetHandle(const char *name)
  61. {
  62. CSharedLibraryItem *item = GetCacheItem(name);
  63. if (item == NULL)
  64. {
  65. LibraryHandle lib = LoadLibraryHandle(name);
  66. dbgdynfn("CDynamicFunction: Loading library '%s' (%p)\n", name, (void *) lib);
  67. if (lib == NULL)
  68. return NULL;
  69. item = new CSharedLibraryItem(lib, name);
  70. item->m_next = m_pList;
  71. m_pList = item;
  72. }
  73. return item->m_handle;
  74. }
  75. void CloseLibrary(const char *name)
  76. {
  77. CSharedLibraryItem *item = GetCacheItem(name);
  78. if (item)
  79. {
  80. assert(item == m_pList);
  81. m_pList = item->m_next;
  82. item->m_next = NULL;
  83. delete item;
  84. }
  85. }
  86. void CloseAllLibraries()
  87. {
  88. delete m_pList;
  89. }
  90. private:
  91. CSharedLibraryItem *GetCacheItem(const char *name)
  92. {
  93. CSharedLibraryItem *prev = NULL;
  94. CSharedLibraryItem *item = m_pList;
  95. while (item)
  96. {
  97. if (strcmp(item->m_name, name) == 0)
  98. {
  99. // move this item to the front of the list, since there will
  100. // probably be a big pile of these lookups in a row
  101. // and then none ever again.
  102. if (prev != NULL)
  103. {
  104. prev->m_next = item->m_next;
  105. item->m_next = m_pList;
  106. m_pList = item;
  107. }
  108. return item;
  109. }
  110. prev = item;
  111. item = item->m_next;
  112. }
  113. return NULL; // not found.
  114. }
  115. CSharedLibraryItem *m_pList;
  116. };
  117. void *VoidFnPtrLookup_Tier0(const char *libname, const char *fn, void *fallback)
  118. {
  119. LibraryHandle lib = CSharedLibraryCache::GetCache().GetHandle(libname);
  120. void *retval = NULL;
  121. if (lib != NULL)
  122. {
  123. retval = LookupInLibraryHandle(lib, fn);
  124. dbgdynfn("CDynamicFunction: Lookup of '%s' in '%s': %p\n", fn, libname, retval);
  125. }
  126. if (retval == NULL)
  127. retval = fallback;
  128. return retval;
  129. }