dynlib.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. dynlib.c
  9. Abstract:
  10. This module implements support for loading dynamic libraries at runtime.
  11. Author:
  12. Evan Green 17-Oct-2013
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <dlfcn.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // ------------------------------------------------------ Data Type Definitions
  27. //
  28. //
  29. // ----------------------------------------------- Internal Function Prototypes
  30. //
  31. //
  32. // -------------------------------------------------------------------- Globals
  33. //
  34. //
  35. // Store the last status of a dynamic library open operation.
  36. //
  37. KSTATUS ClDynamicLibraryStatus = STATUS_SUCCESS;
  38. //
  39. // ------------------------------------------------------------------ Functions
  40. //
  41. LIBC_API
  42. void *
  43. dlopen (
  44. const char *Library,
  45. int Flags
  46. )
  47. /*++
  48. Routine Description:
  49. This routine opens and loads a dynamic library object with the given name.
  50. Only one instance of a given binary will be loaded per process.
  51. Arguments:
  52. Library - Supplies a pointer to the null terminated string of the library
  53. to open. Supply NULL to open a handle to a global symbol table.
  54. Flags - Supplies a bitfield of flags governing the behavior of the library.
  55. See RTLD_* definitions.
  56. Return Value:
  57. Returns an opaque handle to the library that can be used in calls to dlsym.
  58. NULL on failure, and more information can be retrieved via the dlerror
  59. function.
  60. --*/
  61. {
  62. HANDLE Handle;
  63. KSTATUS Status;
  64. ASSERT((RTLD_GLOBAL == IMAGE_LOAD_FLAG_GLOBAL) &&
  65. (RTLD_NOW == IMAGE_LOAD_FLAG_BIND_NOW));
  66. Status = OsLoadLibrary((PSTR)Library, Flags, &Handle);
  67. if (!KSUCCESS(Status)) {
  68. ClDynamicLibraryStatus = Status;
  69. return NULL;
  70. }
  71. assert(Handle != INVALID_HANDLE);
  72. return Handle;
  73. }
  74. LIBC_API
  75. int
  76. dlclose (
  77. void *Handle
  78. )
  79. /*++
  80. Routine Description:
  81. This routine closes a previously opened dynamic library. This may or may
  82. not result in the library being unloaded, depending on what else has
  83. references out on it. Either way, callers should assume the handle is
  84. not valid for any future calls to the dlsym function.
  85. Arguments:
  86. Handle - Supplies the opaque handle returned when the library was opened.
  87. Return Value:
  88. 0 on success.
  89. Non-zero on failure, and dlerror will be set to contain more information.
  90. --*/
  91. {
  92. if (Handle == NULL) {
  93. ClDynamicLibraryStatus = STATUS_INVALID_HANDLE;
  94. return -1;
  95. }
  96. OsFreeLibrary(Handle);
  97. return 0;
  98. }
  99. LIBC_API
  100. char *
  101. dlerror (
  102. void
  103. )
  104. /*++
  105. Routine Description:
  106. This routine returns a null terminated string (with no trailing newline)
  107. that describes the last error that occurred during dynamic linking
  108. processing. If no errors have occurred since the last invocation, NULL is
  109. returned. Invoking this routine a second time immediately following a prior
  110. invocation will return NULL. This routine is neither thread-safe nor
  111. reentrant.
  112. Arguments:
  113. None.
  114. Return Value:
  115. Returns a pointer to a string describing the last error on success. The
  116. caller is not responsible for freeing this memory.
  117. NULL if nothing went wrong since the last invocation.
  118. --*/
  119. {
  120. INT ErrorNumber;
  121. KSTATUS Status;
  122. Status = ClDynamicLibraryStatus;
  123. ClDynamicLibraryStatus = STATUS_SUCCESS;
  124. if (KSUCCESS(Status)) {
  125. return NULL;
  126. }
  127. ErrorNumber = ClConvertKstatusToErrorNumber(Status);
  128. return strerror(ErrorNumber);
  129. }
  130. LIBC_API
  131. void *
  132. __dlsym (
  133. void *Handle,
  134. const char *SymbolName,
  135. void *CallerAddress
  136. )
  137. /*++
  138. Routine Description:
  139. This routine returns the address of a symbol defined within an object made
  140. accessible through a call to dlopen. This is an internal routine that
  141. should not be called directly by users.
  142. Arguments:
  143. Handle - Supplies a pointer to the opaque handle returned by the dlopen
  144. routine.
  145. SymbolName - Supplies a pointer to a null-terminated string containing the
  146. name of the symbol whose address should be retrieved.
  147. CallerAddress - Supplies an address within the dynamic object of the
  148. calling executable. This routine will use this address to determine
  149. which object to start from and skip if RTLD_NEXT is provided as the
  150. handle.
  151. Return Value:
  152. Returns the address of the symbol on success.
  153. NULL if the handle was not valid or the symbol could not be found. More
  154. information can be retrieved via the dlerror function.
  155. --*/
  156. {
  157. PVOID Address;
  158. HANDLE Skip;
  159. KSTATUS Status;
  160. Skip = NULL;
  161. //
  162. // The C Library handle definitions better line up with the OS base's.
  163. //
  164. ASSERT(RTLD_DEFAULT == NULL);
  165. if (Handle == RTLD_NEXT) {
  166. Handle = OsGetImageForAddress(CallerAddress);
  167. if (Handle == INVALID_HANDLE) {
  168. ClDynamicLibraryStatus = STATUS_NOT_FOUND;
  169. return NULL;
  170. }
  171. Skip = Handle;
  172. }
  173. Status = OsGetSymbolAddress(Handle, (PSTR)SymbolName, Skip, &Address);
  174. if (!KSUCCESS(Status)) {
  175. ClDynamicLibraryStatus = Status;
  176. return NULL;
  177. }
  178. return Address;
  179. }
  180. LIBC_API
  181. int
  182. dladdr (
  183. void *Address,
  184. Dl_info *Information
  185. )
  186. /*++
  187. Routine Description:
  188. This routine resolves an address into the symbol and dynamic library
  189. information.
  190. Arguments:
  191. Address - Supplies the address being resolved.
  192. Information - Supplies a pointer that recevies that dynamic library
  193. information for the given address.
  194. Return Value:
  195. Non-zero on success.
  196. 0 on failure, but dlerror will not be set to contain more information.
  197. --*/
  198. {
  199. KSTATUS Status;
  200. //
  201. // The OS_IMAGE_SYMBOL structure should line up with the Dl_info structure.
  202. //
  203. ASSERT((FIELD_OFFSET(OS_IMAGE_SYMBOL, ImagePath) ==
  204. FIELD_OFFSET(Dl_info, dli_fname)) &&
  205. (FIELD_OFFSET(OS_IMAGE_SYMBOL, ImageBase) ==
  206. FIELD_OFFSET(Dl_info, dli_fbase)) &&
  207. (FIELD_OFFSET(OS_IMAGE_SYMBOL, SymbolName) ==
  208. FIELD_OFFSET(Dl_info, dli_sname)) &&
  209. (FIELD_OFFSET(OS_IMAGE_SYMBOL, SymbolAddress) ==
  210. FIELD_OFFSET(Dl_info, dli_saddr)));
  211. Status = OsGetImageSymbolForAddress(Address,
  212. (POS_IMAGE_SYMBOL)Information);
  213. if (!KSUCCESS(Status)) {
  214. return 0;
  215. }
  216. return 1;
  217. }
  218. //
  219. // --------------------------------------------------------- Internal Functions
  220. //