dlopen.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. dlopen.c - DLL support code
  3. Copyright (c) 2002 - 2005, 2015 dbjh
  4. This 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. This 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 this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #ifdef DJGPP
  20. #include <sys/dxe.h>
  21. #elif defined __unix__ || defined __APPLE__ // Mac OS X actually; __unix__ is also
  22. #include <dlfcn.h> // defined on Cygwin (and DJGPP)
  23. #elif defined _WIN32
  24. #ifdef _MSC_VER
  25. #pragma warning(push)
  26. #pragma warning(disable: 4255) // 'function' : no function prototype given: converting '()' to '(void)'
  27. #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
  28. #pragma warning(disable: 4820) // 'bytes' bytes padding added after construct 'member_name'
  29. #endif
  30. #include <windows.h>
  31. #ifdef _MSC_VER
  32. #pragma warning(pop)
  33. #endif
  34. #elif defined __BEOS__
  35. #include <image.h>
  36. #include <Errors.h>
  37. #endif
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include "dlopen.h"
  41. #ifdef DJGPP
  42. #include "dxedll_pub.h"
  43. #include "map.h"
  44. #define INITIAL_HANDLE 1
  45. static st_map_t *dxe_map;
  46. extern int errno;
  47. void
  48. uninit_func (void)
  49. {
  50. fputs ("ERROR: An uninitialized member of the import/export structure was called.\n"
  51. " Update dlopen.c/open_module()\n", stderr);
  52. exit (1);
  53. }
  54. #endif
  55. void *
  56. open_module (char *module_name)
  57. {
  58. void *handle;
  59. #ifdef DJGPP
  60. static int new_handle = INITIAL_HANDLE;
  61. int n, m;
  62. st_symbol_t *sym = _dxe_load (module_name);
  63. /*
  64. _dxe_load() doesn't really return a handle. It returns a pointer to the one
  65. symbol a DXE module can export.
  66. */
  67. if (sym == 0)
  68. {
  69. fprintf (stderr, "ERROR: Could not load DXE module: %s\n", module_name);
  70. exit (1);
  71. }
  72. if (sym->size != sizeof (st_symbol_t))
  73. {
  74. fprintf (stderr, "ERROR: Incompatible DXE module: %s\n", module_name);
  75. exit (1);
  76. }
  77. // initialize the import/export structure
  78. /*
  79. Catch calls to uninitialized members in case a new function was added to
  80. st_symbol_t, but forgotten to initialize here.
  81. */
  82. m = sizeof (st_symbol_t) / sizeof (void (*) (void));
  83. for (n = 0; n < m && ((void (**) (void)) sym)[n] != 0; n++) // Don't overwrite values initialized by DXE
  84. ;
  85. for (; n < m; n++)
  86. ((void (**) (void)) sym)[n] = uninit_func;
  87. // initialize functions
  88. sym->open = open;
  89. sym->vfprintf = vfprintf;
  90. sym->vsprintf = vsprintf;
  91. sym->vsnprintf = vsnprintf;
  92. sym->puts = puts;
  93. sym->fputs = fputs;
  94. sym->vsscanf = vsscanf;
  95. sym->fopen = fopen;
  96. sym->fdopen = fdopen;
  97. sym->popen = popen;
  98. sym->fclose = fclose;
  99. sym->pclose = pclose;
  100. sym->fseek = fseek;
  101. sym->ftell = ftell;
  102. sym->rewind = rewind;
  103. sym->fread = fread;
  104. sym->fwrite = fwrite;
  105. sym->fgetc = fgetc;
  106. sym->fgets = fgets;
  107. sym->feof = feof;
  108. sym->fputc = fputc;
  109. sym->fflush = fflush;
  110. sym->ferror = ferror;
  111. sym->rename = rename;
  112. sym->remove = remove;
  113. sym->clearerr = clearerr;
  114. sym->free = free;
  115. sym->malloc = malloc;
  116. sym->calloc = calloc;
  117. sym->realloc = realloc;
  118. sym->exit = exit;
  119. sym->strtol = strtol;
  120. sym->getenv = getenv;
  121. sym->srand = srand;
  122. sym->rand = rand;
  123. sym->atoi = atoi;
  124. sym->memcmp = memcmp;
  125. sym->memcpy = memcpy;
  126. sym->memset = memset;
  127. sym->memchr = memchr;
  128. sym->strcmp = strcmp;
  129. sym->strcpy = strcpy;
  130. sym->strncpy = strncpy;
  131. sym->strcat = strcat;
  132. sym->strncat = strncat;
  133. sym->stpcpy = stpcpy;
  134. sym->strcasecmp = strcasecmp;
  135. sym->strncasecmp = strncasecmp;
  136. sym->strchr = strchr;
  137. sym->strrchr = strrchr;
  138. sym->strpbrk = strpbrk;
  139. sym->strspn = strspn;
  140. sym->strcspn = strcspn;
  141. sym->strlen = strlen;
  142. sym->strstr = strstr;
  143. sym->strdup = strdup;
  144. sym->strtok = strtok;
  145. sym->strerror = strerror;
  146. sym->tolower = tolower;
  147. sym->toupper = toupper;
  148. sym->isupper = isupper;
  149. sym->opendir = opendir;
  150. sym->readdir = readdir;
  151. sym->closedir = closedir;
  152. sym->access = access;
  153. sym->read = read;
  154. sym->write = write;
  155. sym->close = close;
  156. sym->lseek = lseek;
  157. sym->readlink = readlink;
  158. sym->rmdir = rmdir;
  159. sym->isatty = isatty;
  160. sym->chdir = chdir;
  161. sym->getcwd = getcwd;
  162. sym->getuid = getuid;
  163. sym->sync = sync;
  164. sym->truncate = truncate;
  165. sym->stat = stat;
  166. sym->chmod = chmod;
  167. sym->mkdir = mkdir;
  168. sym->time = time;
  169. sym->difftime = difftime;
  170. sym->delay = delay;
  171. sym->__dpmi_int = __dpmi_int;
  172. // initialize variables
  173. sym->__dj_stdin = __dj_stdin;
  174. sym->__dj_stdout = __dj_stdout;
  175. sym->__dj_stderr = __dj_stderr;
  176. sym->__dj_ctype_flags = __dj_ctype_flags;
  177. sym->__dj_ctype_tolower = __dj_ctype_tolower;
  178. sym->__dj_ctype_toupper = __dj_ctype_toupper;
  179. sym->errno = errno;
  180. // initialize the DXE module
  181. sym->dxe_init ();
  182. if (new_handle == INITIAL_HANDLE)
  183. dxe_map = map_create (10);
  184. dxe_map = map_put (dxe_map, (void *) new_handle, sym);
  185. handle = (void *) new_handle++;
  186. #elif defined __unix__ || defined __APPLE__ // Mac OS X actually
  187. /*
  188. We use dlcompat on Mac OS X simply because it's there. I (dbjh) don't want
  189. to add extra code only because "using the native api's is the supported
  190. method of loading dynamically on Mac OS X" (Peter O'Gorman, maintainer of
  191. dlcompat). Besides, dlcompat has been tested while any new code we add, not.
  192. RTLD_NOW is ignored by dlcompat (7-12-2003).
  193. */
  194. if ((handle = dlopen (module_name, RTLD_LAZY)) == NULL)
  195. {
  196. fputs ("ERROR: ", stderr);
  197. fputs (dlerror (), stderr);
  198. fputc ('\n', stderr);
  199. exit (1);
  200. }
  201. #elif defined _WIN32
  202. if ((handle = LoadLibrary (module_name)) == NULL)
  203. {
  204. LPTSTR strptr;
  205. fputs ("ERROR: ", stderr);
  206. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
  207. FORMAT_MESSAGE_FROM_SYSTEM |
  208. FORMAT_MESSAGE_IGNORE_INSERTS,
  209. NULL, GetLastError (),
  210. MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
  211. (LPTSTR) &strptr, 0, NULL);
  212. // Note the construct with strptr.
  213. fputs (strptr, stderr);
  214. LocalFree (strptr);
  215. exit (1);
  216. }
  217. #elif defined __BEOS__
  218. if ((int) (handle = (void *) load_add_on (module_name)) < B_NO_ERROR)
  219. {
  220. fprintf (stderr, "ERROR: Could not load add-on image: %s\n", module_name);
  221. exit (1);
  222. }
  223. #endif
  224. return handle;
  225. }
  226. void *
  227. get_symbol (void *handle, char *symbol_name)
  228. {
  229. void *symptr;
  230. #ifdef DJGPP
  231. st_symbol_t *sym = map_get (dxe_map, handle);
  232. if (sym == NULL)
  233. {
  234. fprintf (stderr, "ERROR: Invalid handle: %x\n", (int) handle);
  235. exit (1);
  236. }
  237. symptr = sym->dxe_symbol (symbol_name);
  238. if (symptr == NULL)
  239. {
  240. fprintf (stderr, "ERROR: Could not find symbol: %s\n", symbol_name);
  241. exit (1);
  242. }
  243. #elif defined __unix__ || defined __APPLE__ // Mac OS X actually, see
  244. char *strptr; // comment in open_module()
  245. symptr = dlsym (handle, symbol_name);
  246. if ((strptr = dlerror ()) != NULL) // this is "the correct way"
  247. { // according to the info page
  248. fputs ("ERROR: ", stderr);
  249. fputs (strptr, stderr);
  250. fputc ('\n', stderr);
  251. exit (1);
  252. }
  253. #elif defined _WIN32
  254. u_func_ptr_t sym;
  255. sym.func_ptr = (void (*) (void)) GetProcAddress ((HINSTANCE) handle, symbol_name);
  256. symptr = sym.void_ptr;
  257. if (symptr == NULL)
  258. {
  259. LPTSTR strptr;
  260. fputs ("ERROR: ", stderr);
  261. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
  262. FORMAT_MESSAGE_FROM_SYSTEM |
  263. FORMAT_MESSAGE_IGNORE_INSERTS,
  264. NULL, GetLastError (),
  265. MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
  266. (LPTSTR) &strptr, 0, NULL);
  267. fputs (strptr, stderr);
  268. LocalFree (strptr);
  269. exit (1);
  270. }
  271. #elif defined __BEOS__
  272. int status = get_image_symbol ((int) handle, symbol_name,
  273. B_SYMBOL_TYPE_ANY, &symptr); // B_SYMBOL_TYPE_TEXT/B_SYMBOL_TYPE_DATA
  274. if (status != B_OK)
  275. {
  276. fprintf (stderr, "ERROR: Could not find symbol: %s\n", symbol_name);
  277. exit (1);
  278. }
  279. #endif
  280. return symptr;
  281. }
  282. void *
  283. has_symbol (void *handle, char *symbol_name)
  284. {
  285. void *symptr;
  286. #ifdef DJGPP
  287. st_symbol_t *sym = map_get (dxe_map, handle);
  288. if (sym == NULL)
  289. {
  290. fprintf (stderr, "ERROR: Invalid handle: %x\n", (int) handle);
  291. exit (1);
  292. }
  293. symptr = sym->dxe_symbol (symbol_name);
  294. if (symptr == NULL)
  295. symptr = (void *) -1;
  296. #elif defined __unix__ || defined __APPLE__ // Mac OS X actually, see
  297. char *strptr; // comment in open_module()
  298. symptr = dlsym (handle, symbol_name);
  299. if ((strptr = dlerror ()) != NULL) // this is "the correct way"
  300. symptr = (void *) -1; // according to the info page
  301. #elif defined _WIN32
  302. u_func_ptr_t sym;
  303. sym.func_ptr = (void (*) (void)) GetProcAddress ((HINSTANCE) handle, symbol_name);
  304. symptr = sym.void_ptr;
  305. if (symptr == NULL)
  306. symptr = (void *) -1;
  307. #elif defined __BEOS__
  308. int status = get_image_symbol ((int) handle, symbol_name,
  309. B_SYMBOL_TYPE_ANY, &symptr); // B_SYMBOL_TYPE_TEXT/B_SYMBOL_TYPE_DATA
  310. if (status != B_OK)
  311. symptr = (void *) -1;
  312. #endif
  313. return symptr;
  314. }