Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: mozilla/nsprpub/pr/src/linking/prlink.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/nsprpub/pr/src/io/prstdio.c ('k') | mozilla/nsprpub/pr/src/malloc/prmalloc.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "primpl.h"
7
8 #include <string.h>
9
10 #ifdef XP_BEOS
11 #include <image.h>
12 #endif
13
14 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
15 #include <Carbon/Carbon.h>
16 #include <CoreFoundation/CoreFoundation.h>
17 #endif
18
19 #ifdef XP_UNIX
20 #ifdef USE_DLFCN
21 #include <dlfcn.h>
22 /* Define these on systems that don't have them. */
23 #ifndef RTLD_NOW
24 #define RTLD_NOW 0
25 #endif
26 #ifndef RTLD_LAZY
27 #define RTLD_LAZY RTLD_NOW
28 #endif
29 #ifndef RTLD_GLOBAL
30 #define RTLD_GLOBAL 0
31 #endif
32 #ifndef RTLD_LOCAL
33 #define RTLD_LOCAL 0
34 #endif
35 #ifdef AIX
36 #include <sys/ldr.h>
37 #ifndef L_IGNOREUNLOAD /* AIX 4.3.3 does not have L_IGNOREUNLOAD. */
38 #define L_IGNOREUNLOAD 0x10000000
39 #endif
40 #endif
41 #ifdef OSF1
42 #include <loader.h>
43 #include <rld_interface.h>
44 #endif
45 #elif defined(USE_HPSHL)
46 #include <dl.h>
47 #elif defined(USE_MACH_DYLD)
48 #include <mach-o/dyld.h>
49 #endif
50 #endif /* XP_UNIX */
51
52 #define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY
53
54 /*
55 * On these platforms, symbols have a leading '_'.
56 */
57 #if (defined(DARWIN) && defined(USE_MACH_DYLD)) \
58 || defined(XP_OS2) \
59 || ((defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__))
60 #define NEED_LEADING_UNDERSCORE
61 #endif
62
63 #define PR_LD_PATHW 0x8000 /* for PR_LibSpec_PathnameU */
64
65 /************************************************************************/
66
67 struct PRLibrary {
68 char* name; /* Our own copy of the name string */
69 PRLibrary* next;
70 int refCount;
71 const PRStaticLinkTable* staticTable;
72
73 #ifdef XP_PC
74 #ifdef XP_OS2
75 HMODULE dlh;
76 #else
77 HINSTANCE dlh;
78 #endif
79 #endif
80
81 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
82 CFragConnectionID connection;
83 CFBundleRef bundle;
84 Ptr main;
85 CFMutableDictionaryRef wrappers;
86 const struct mach_header* image;
87 #endif
88
89 #ifdef XP_UNIX
90 #if defined(USE_HPSHL)
91 shl_t dlh;
92 #elif defined(USE_MACH_DYLD)
93 NSModule dlh;
94 #else
95 void* dlh;
96 #endif
97 #endif
98
99 #ifdef XP_BEOS
100 void* dlh;
101 void* stub_dlh;
102 #endif
103 };
104
105 static PRLibrary *pr_loadmap;
106 static PRLibrary *pr_exe_loadmap;
107 static PRMonitor *pr_linker_lock;
108 static char* _pr_currentLibPath = NULL;
109
110 static PRLibrary *pr_LoadLibraryByPathname(const char *name, PRIntn flags);
111
112 /************************************************************************/
113
114 #if !defined(USE_DLFCN) && !defined(HAVE_STRERROR)
115 #define ERR_STR_BUF_LENGTH 20
116 #endif
117
118 static void DLLErrorInternal(PRIntn oserr)
119 /*
120 ** This whole function, and most of the code in this file, are run
121 ** with a big hairy lock wrapped around it. Not the best of situations,
122 ** but will eventually come up with the right answer.
123 */
124 {
125 const char *error = NULL;
126 #ifdef USE_DLFCN
127 error = dlerror(); /* $$$ That'll be wrong some of the time - AOF */
128 #elif defined(HAVE_STRERROR)
129 error = strerror(oserr); /* this should be okay */
130 #else
131 char errStrBuf[ERR_STR_BUF_LENGTH];
132 PR_snprintf(errStrBuf, sizeof(errStrBuf), "error %d", oserr);
133 error = errStrBuf;
134 #endif
135 if (NULL != error)
136 PR_SetErrorText(strlen(error), error);
137 } /* DLLErrorInternal */
138
139 void _PR_InitLinker(void)
140 {
141 PRLibrary *lm = NULL;
142 #if defined(XP_UNIX)
143 void *h;
144 #endif
145
146 if (!pr_linker_lock) {
147 pr_linker_lock = PR_NewNamedMonitor("linker-lock");
148 }
149 PR_EnterMonitor(pr_linker_lock);
150
151 #if defined(XP_PC)
152 lm = PR_NEWZAP(PRLibrary);
153 lm->name = strdup("Executable");
154 #if defined(XP_OS2)
155 lm->dlh = NULLHANDLE;
156 #else
157 /* A module handle for the executable. */
158 lm->dlh = GetModuleHandle(NULL);
159 #endif /* ! XP_OS2 */
160
161 lm->refCount = 1;
162 lm->staticTable = NULL;
163 pr_exe_loadmap = lm;
164 pr_loadmap = lm;
165
166 #elif defined(XP_UNIX)
167 #ifdef HAVE_DLL
168 #if defined(USE_DLFCN) && !defined(NO_DLOPEN_NULL)
169 h = dlopen(0, RTLD_LAZY);
170 if (!h) {
171 char *error;
172
173 DLLErrorInternal(_MD_ERRNO());
174 error = (char*)PR_MALLOC(PR_GetErrorTextLength());
175 (void) PR_GetErrorText(error);
176 fprintf(stderr, "failed to initialize shared libraries [%s]\n",
177 error);
178 PR_DELETE(error);
179 abort();/* XXX */
180 }
181 #elif defined(USE_HPSHL)
182 h = NULL;
183 /* don't abort with this NULL */
184 #elif defined(USE_MACH_DYLD) || defined(NO_DLOPEN_NULL)
185 h = NULL; /* XXXX toshok */ /* XXXX vlad */
186 #else
187 #error no dll strategy
188 #endif /* USE_DLFCN */
189
190 lm = PR_NEWZAP(PRLibrary);
191 if (lm) {
192 lm->name = strdup("a.out");
193 lm->refCount = 1;
194 lm->dlh = h;
195 lm->staticTable = NULL;
196 }
197 pr_exe_loadmap = lm;
198 pr_loadmap = lm;
199 #endif /* HAVE_DLL */
200 #endif /* XP_UNIX */
201
202 if (lm) {
203 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
204 ("Loaded library %s (init)", lm->name));
205 }
206
207 PR_ExitMonitor(pr_linker_lock);
208 }
209
210 /*
211 * _PR_ShutdownLinker does not unload the dlls loaded by the application
212 * via calls to PR_LoadLibrary. Any dlls that still remain on the
213 * pr_loadmap list when NSPR shuts down are application programming errors.
214 * The only exception is pr_exe_loadmap, which was added to the list by
215 * NSPR and hence should be cleaned up by NSPR.
216 */
217 void _PR_ShutdownLinker(void)
218 {
219 /* FIXME: pr_exe_loadmap should be destroyed. */
220
221 PR_DestroyMonitor(pr_linker_lock);
222 pr_linker_lock = NULL;
223
224 if (_pr_currentLibPath) {
225 free(_pr_currentLibPath);
226 _pr_currentLibPath = NULL;
227 }
228 }
229
230 /******************************************************************************/
231
232 PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path)
233 {
234 PRStatus rv = PR_SUCCESS;
235
236 if (!_pr_initialized) _PR_ImplicitInitialization();
237 PR_EnterMonitor(pr_linker_lock);
238 if (_pr_currentLibPath) {
239 free(_pr_currentLibPath);
240 }
241 if (path) {
242 _pr_currentLibPath = strdup(path);
243 if (!_pr_currentLibPath) {
244 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
245 rv = PR_FAILURE;
246 }
247 } else {
248 _pr_currentLibPath = 0;
249 }
250 PR_ExitMonitor(pr_linker_lock);
251 return rv;
252 }
253
254 /*
255 ** Return the library path for finding shared libraries.
256 */
257 PR_IMPLEMENT(char *)
258 PR_GetLibraryPath(void)
259 {
260 char *ev;
261 char *copy = NULL; /* a copy of _pr_currentLibPath */
262
263 if (!_pr_initialized) _PR_ImplicitInitialization();
264 PR_EnterMonitor(pr_linker_lock);
265 if (_pr_currentLibPath != NULL) {
266 goto exit;
267 }
268
269 /* initialize pr_currentLibPath */
270
271 #ifdef XP_PC
272 ev = getenv("LD_LIBRARY_PATH");
273 if (!ev) {
274 ev = ".;\\lib";
275 }
276 ev = strdup(ev);
277 #endif
278
279 #if defined(XP_UNIX) || defined(XP_BEOS)
280 #if defined(USE_DLFCN) || defined(USE_MACH_DYLD) || defined(XP_BEOS)
281 {
282 char *p=NULL;
283 int len;
284
285 #ifdef XP_BEOS
286 ev = getenv("LIBRARY_PATH");
287 if (!ev) {
288 ev = "%A/lib:/boot/home/config/lib:/boot/beos/system/lib";
289 }
290 #else
291 ev = getenv("LD_LIBRARY_PATH");
292 if (!ev) {
293 ev = "/usr/lib:/lib";
294 }
295 #endif
296 len = strlen(ev) + 1; /* +1 for the null */
297
298 p = (char*) malloc(len);
299 if (p) {
300 strcpy(p, ev);
301 } /* if (p) */
302 ev = p;
303 PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev));
304
305 }
306 #else
307 /* AFAIK there isn't a library path with the HP SHL interface --Rob */
308 ev = strdup("");
309 #endif
310 #endif
311
312 /*
313 * If ev is NULL, we have run out of memory
314 */
315 _pr_currentLibPath = ev;
316
317 exit:
318 if (_pr_currentLibPath) {
319 copy = strdup(_pr_currentLibPath);
320 }
321 PR_ExitMonitor(pr_linker_lock);
322 if (!copy) {
323 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
324 }
325 return copy;
326 }
327
328 /*
329 ** Build library name from path, lib and extensions
330 */
331 PR_IMPLEMENT(char*)
332 PR_GetLibraryName(const char *path, const char *lib)
333 {
334 char *fullname;
335
336 #ifdef XP_PC
337 if (strstr(lib, PR_DLL_SUFFIX) == NULL)
338 {
339 if (path) {
340 fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
341 } else {
342 fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX);
343 }
344 } else {
345 if (path) {
346 fullname = PR_smprintf("%s\\%s", path, lib);
347 } else {
348 fullname = PR_smprintf("%s", lib);
349 }
350 }
351 #endif /* XP_PC */
352 #if defined(XP_UNIX) || defined(XP_BEOS)
353 if (strstr(lib, PR_DLL_SUFFIX) == NULL)
354 {
355 if (path) {
356 fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX);
357 } else {
358 fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX);
359 }
360 } else {
361 if (path) {
362 fullname = PR_smprintf("%s/%s", path, lib);
363 } else {
364 fullname = PR_smprintf("%s", lib);
365 }
366 }
367 #endif /* XP_UNIX || XP_BEOS */
368 return fullname;
369 }
370
371 /*
372 ** Free the memory allocated, for the caller, by PR_GetLibraryName
373 */
374 PR_IMPLEMENT(void)
375 PR_FreeLibraryName(char *mem)
376 {
377 PR_smprintf_free(mem);
378 }
379
380 static PRLibrary*
381 pr_UnlockedFindLibrary(const char *name)
382 {
383 PRLibrary* lm = pr_loadmap;
384 const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR);
385 np = np ? np + 1 : name;
386 while (lm) {
387 const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
388 cp = cp ? cp + 1 : lm->name;
389 #ifdef WIN32
390 /* Windows DLL names are case insensitive... */
391 if (strcmpi(np, cp) == 0)
392 #elif defined(XP_OS2)
393 if (stricmp(np, cp) == 0)
394 #else
395 if (strcmp(np, cp) == 0)
396 #endif
397 {
398 /* found */
399 lm->refCount++;
400 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
401 ("%s incr => %d (find lib)",
402 lm->name, lm->refCount));
403 return lm;
404 }
405 lm = lm->next;
406 }
407 return NULL;
408 }
409
410 PR_IMPLEMENT(PRLibrary*)
411 PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags)
412 {
413 if (flags == 0) {
414 flags = _PR_DEFAULT_LD_FLAGS;
415 }
416 switch (libSpec.type) {
417 case PR_LibSpec_Pathname:
418 return pr_LoadLibraryByPathname(libSpec.value.pathname, flags);
419 #ifdef WIN32
420 case PR_LibSpec_PathnameU:
421 /*
422 * cast to |char *| and set PR_LD_PATHW flag so that
423 * it can be cast back to PRUnichar* in the callee.
424 */
425 return pr_LoadLibraryByPathname((const char*)
426 libSpec.value.pathname_u,
427 flags | PR_LD_PATHW);
428 #endif
429 default:
430 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
431 return NULL;
432 }
433 }
434
435 PR_IMPLEMENT(PRLibrary*)
436 PR_LoadLibrary(const char *name)
437 {
438 PRLibSpec libSpec;
439
440 libSpec.type = PR_LibSpec_Pathname;
441 libSpec.value.pathname = name;
442 return PR_LoadLibraryWithFlags(libSpec, 0);
443 }
444
445 #if defined(USE_MACH_DYLD)
446 static NSModule
447 pr_LoadMachDyldModule(const char *name)
448 {
449 NSObjectFileImage ofi;
450 NSModule h = NULL;
451 if (NSCreateObjectFileImageFromFile(name, &ofi)
452 == NSObjectFileImageSuccess) {
453 h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE
454 | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
455 if (h == NULL) {
456 NSLinkEditErrors linkEditError;
457 int errorNum;
458 const char *fileName;
459 const char *errorString;
460 NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString);
461 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
462 ("LoadMachDyldModule error %d:%d for file %s:\n%s",
463 linkEditError, errorNum, fileName, errorString));
464 }
465 if (NSDestroyObjectFileImage(ofi) == FALSE) {
466 if (h) {
467 (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE);
468 h = NULL;
469 }
470 }
471 }
472 return h;
473 }
474 #endif
475
476 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
477
478 /*
479 ** macLibraryLoadProc is a function definition for a Mac shared library
480 ** loading method. The "name" param is the same full or partial pathname
481 ** that was passed to pr_LoadLibraryByPathName. The function must fill
482 ** in the fields of "lm" which apply to its library type. Returns
483 ** PR_SUCCESS if successful.
484 */
485
486 typedef PRStatus (*macLibraryLoadProc)(const char *name, PRLibrary *lm);
487
488 #ifdef __ppc__
489
490 /*
491 ** CFM and its TVectors only exist on PowerPC. Other OS X architectures
492 ** only use Mach-O as a native binary format.
493 */
494
495 static void* TV2FP(CFMutableDictionaryRef dict, const char* name, void *tvp)
496 {
497 static uint32 glue[6] = { 0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x 7C0903A6, 0x4E800420 };
498 uint32* newGlue = NULL;
499
500 if (tvp != NULL) {
501 CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEnc odingASCII);
502 if (nameRef) {
503 CFMutableDataRef glueData = (CFMutableDataRef) CFDictionaryGetValue( dict, nameRef);
504 if (glueData == NULL) {
505 glueData = CFDataCreateMutable(NULL, sizeof(glue));
506 if (glueData != NULL) {
507 newGlue = (uint32*) CFDataGetMutableBytePtr(glueData);
508 memcpy(newGlue, glue, sizeof(glue));
509 newGlue[0] |= ((UInt32)tvp >> 16);
510 newGlue[1] |= ((UInt32)tvp & 0xFFFF);
511 MakeDataExecutable(newGlue, sizeof(glue));
512 CFDictionaryAddValue(dict, nameRef, glueData);
513 CFRelease(glueData);
514
515 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: created wrapper f or CFM function %s().", name));
516 }
517 } else {
518 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: found wrapper for CFM function %s().", name));
519
520 newGlue = (uint32*) CFDataGetMutableBytePtr(glueData);
521 }
522 CFRelease(nameRef);
523 }
524 }
525
526 return newGlue;
527 }
528
529 static PRStatus
530 pr_LoadViaCFM(const char *name, PRLibrary *lm)
531 {
532 OSErr err;
533 Str255 errName;
534 FSRef ref;
535 FSSpec fileSpec;
536 Boolean tempUnusedBool;
537
538 /*
539 * Make an FSSpec from the path name and call GetDiskFragment.
540 */
541
542 /* Use direct conversion of POSIX path to FSRef to FSSpec. */
543 err = FSPathMakeRef((const UInt8*)name, &ref, NULL);
544 if (err != noErr)
545 return PR_FAILURE;
546 err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL,
547 &fileSpec, NULL);
548 if (err != noErr)
549 return PR_FAILURE;
550
551 /* Resolve an alias if this was one */
552 err = ResolveAliasFile(&fileSpec, true, &tempUnusedBool,
553 &tempUnusedBool);
554 if (err != noErr)
555 return PR_FAILURE;
556
557 /* Finally, try to load the library */
558 err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name,
559 kLoadCFrag, &lm->connection, &lm->main, errName);
560
561 if (err == noErr && lm->connection) {
562 /*
563 * if we're a mach-o binary, need to wrap all CFM function
564 * pointers. need a hash-table of already seen function
565 * pointers, etc.
566 */
567 lm->wrappers = CFDictionaryCreateMutable(NULL, 16,
568 &kCFTypeDictionaryKeyCallBacks,
569 &kCFTypeDictionaryValueCallBacks);
570 if (lm->wrappers) {
571 lm->main = TV2FP(lm->wrappers, "main", lm->main);
572 } else
573 err = memFullErr;
574 }
575 return (err == noErr) ? PR_SUCCESS : PR_FAILURE;
576 }
577 #endif /* __ppc__ */
578
579 /*
580 ** Creates a CFBundleRef if the pathname refers to a Mac OS X bundle
581 ** directory. The caller is responsible for calling CFRelease() to
582 ** deallocate.
583 */
584
585 static PRStatus
586 pr_LoadCFBundle(const char *name, PRLibrary *lm)
587 {
588 CFURLRef bundleURL;
589 CFBundleRef bundle = NULL;
590 char pathBuf[PATH_MAX];
591 const char *resolvedPath;
592 CFStringRef pathRef;
593
594 /* Takes care of relative paths and symlinks */
595 resolvedPath = realpath(name, pathBuf);
596 if (!resolvedPath)
597 return PR_FAILURE;
598
599 pathRef = CFStringCreateWithCString(NULL, pathBuf, kCFStringEncodingUTF8);
600 if (pathRef) {
601 bundleURL = CFURLCreateWithFileSystemPath(NULL, pathRef,
602 kCFURLPOSIXPathStyle, true);
603 if (bundleURL) {
604 bundle = CFBundleCreate(NULL, bundleURL);
605 CFRelease(bundleURL);
606 }
607 CFRelease(pathRef);
608 }
609
610 lm->bundle = bundle;
611 return (bundle != NULL) ? PR_SUCCESS : PR_FAILURE;
612 }
613
614 static PRStatus
615 pr_LoadViaDyld(const char *name, PRLibrary *lm)
616 {
617 lm->dlh = pr_LoadMachDyldModule(name);
618 if (lm->dlh == NULL) {
619 lm->image = NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR
620 | NSADDIMAGE_OPTION_WITH_SEARCHING);
621 if (lm->image == NULL) {
622 NSLinkEditErrors linkEditError;
623 int errorNum;
624 const char *fileName;
625 const char *errorString;
626 NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString);
627 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
628 ("LoadMachDyldModule error %d:%d for file %s:\n%s",
629 linkEditError, errorNum, fileName, errorString));
630 }
631 }
632 return (lm->dlh != NULL || lm->image != NULL) ? PR_SUCCESS : PR_FAILURE;
633 }
634
635 #endif /* XP_MACOSX && USE_MACH_DYLD */
636
637 /*
638 ** Dynamically load a library. Only load libraries once, so scan the load
639 ** map first.
640 */
641 static PRLibrary*
642 pr_LoadLibraryByPathname(const char *name, PRIntn flags)
643 {
644 PRLibrary *lm;
645 PRLibrary* result = NULL;
646 PRInt32 oserr;
647 #ifdef WIN32
648 char utf8name_stack[MAX_PATH];
649 char *utf8name_malloc = NULL;
650 char *utf8name = utf8name_stack;
651 PRUnichar wname_stack[MAX_PATH];
652 PRUnichar *wname_malloc = NULL;
653 PRUnichar *wname = wname_stack;
654 int len;
655 #endif
656
657 if (!_pr_initialized) _PR_ImplicitInitialization();
658
659 /* See if library is already loaded */
660 PR_EnterMonitor(pr_linker_lock);
661
662 #ifdef WIN32
663 if (flags & PR_LD_PATHW) {
664 /* cast back what's cast to |char *| for the argument passing. */
665 wname = (LPWSTR) name;
666 } else {
667 int wlen = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
668 if (wlen > MAX_PATH)
669 wname = wname_malloc = PR_Malloc(wlen * sizeof(PRUnichar));
670 if (wname == NULL ||
671 !MultiByteToWideChar(CP_ACP, 0, name, -1, wname, wlen)) {
672 oserr = _MD_ERRNO();
673 goto unlock;
674 }
675 }
676 len = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
677 if (len > MAX_PATH)
678 utf8name = utf8name_malloc = PR_Malloc(len);
679 if (utf8name == NULL ||
680 !WideCharToMultiByte(CP_UTF8, 0, wname, -1,
681 utf8name, len, NULL, NULL)) {
682 oserr = _MD_ERRNO();
683 goto unlock;
684 }
685 /* the list of loaded library names are always kept in UTF-8
686 * on Win32 platforms */
687 result = pr_UnlockedFindLibrary(utf8name);
688 #else
689 result = pr_UnlockedFindLibrary(name);
690 #endif
691
692 if (result != NULL) goto unlock;
693
694 lm = PR_NEWZAP(PRLibrary);
695 if (lm == NULL) {
696 oserr = _MD_ERRNO();
697 goto unlock;
698 }
699 lm->staticTable = NULL;
700
701 #ifdef XP_OS2 /* Why isn't all this stuff in MD code?! */
702 {
703 HMODULE h;
704 UCHAR pszError[_MAX_PATH];
705 ULONG ulRc = NO_ERROR;
706
707 ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h);
708 if (ulRc != NO_ERROR) {
709 oserr = ulRc;
710 PR_DELETE(lm);
711 goto unlock;
712 }
713 lm->name = strdup(name);
714 lm->dlh = h;
715 lm->next = pr_loadmap;
716 pr_loadmap = lm;
717 }
718 #endif /* XP_OS2 */
719
720 #ifdef WIN32
721 {
722 HINSTANCE h;
723
724 h = LoadLibraryExW(wname, NULL,
725 (flags & PR_LD_ALT_SEARCH_PATH) ?
726 LOAD_WITH_ALTERED_SEARCH_PATH : 0);
727 if (h == NULL) {
728 oserr = _MD_ERRNO();
729 PR_DELETE(lm);
730 goto unlock;
731 }
732 lm->name = strdup(utf8name);
733 lm->dlh = h;
734 lm->next = pr_loadmap;
735 pr_loadmap = lm;
736 }
737 #endif /* WIN32 */
738
739 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
740 {
741 int i;
742 PRStatus status;
743
744 static const macLibraryLoadProc loadProcs[] = {
745 #ifdef __ppc__
746 pr_LoadViaDyld, pr_LoadCFBundle, pr_LoadViaCFM
747 #else /* __ppc__ */
748 pr_LoadViaDyld, pr_LoadCFBundle
749 #endif /* __ppc__ */
750 };
751
752 for (i = 0; i < sizeof(loadProcs) / sizeof(loadProcs[0]); i++) {
753 if ((status = loadProcs[i](name, lm)) == PR_SUCCESS)
754 break;
755 }
756 if (status != PR_SUCCESS) {
757 oserr = cfragNoLibraryErr;
758 PR_DELETE(lm);
759 goto unlock;
760 }
761 lm->name = strdup(name);
762 lm->next = pr_loadmap;
763 pr_loadmap = lm;
764 }
765 #endif
766
767 #if defined(XP_UNIX) && !(defined(XP_MACOSX) && defined(USE_MACH_DYLD))
768 #ifdef HAVE_DLL
769 {
770 #if defined(USE_DLFCN)
771 #ifdef NTO
772 /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */
773 int dl_flags = RTLD_GROUP;
774 #elif defined(AIX)
775 /* AIX needs RTLD_MEMBER to load an archive member. (bug 228899) */
776 int dl_flags = RTLD_MEMBER;
777 #else
778 int dl_flags = 0;
779 #endif
780 void *h = NULL;
781
782 if (flags & PR_LD_LAZY) {
783 dl_flags |= RTLD_LAZY;
784 }
785 if (flags & PR_LD_NOW) {
786 dl_flags |= RTLD_NOW;
787 }
788 if (flags & PR_LD_GLOBAL) {
789 dl_flags |= RTLD_GLOBAL;
790 }
791 if (flags & PR_LD_LOCAL) {
792 dl_flags |= RTLD_LOCAL;
793 }
794 #if defined(DARWIN)
795 /* ensure the file exists if it contains a slash character i.e. path */
796 /* DARWIN's dlopen ignores the provided path and checks for the */
797 /* plain filename in DYLD_LIBRARY_PATH */
798 if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL ||
799 PR_Access(name, PR_ACCESS_EXISTS) == PR_SUCCESS) {
800 h = dlopen(name, dl_flags);
801 }
802 #else
803 h = dlopen(name, dl_flags);
804 #endif
805 #elif defined(USE_HPSHL)
806 int shl_flags = 0;
807 shl_t h;
808
809 /*
810 * Use the DYNAMIC_PATH flag only if 'name' is a plain file
811 * name (containing no directory) to match the behavior of
812 * dlopen().
813 */
814 if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) {
815 shl_flags |= DYNAMIC_PATH;
816 }
817 if (flags & PR_LD_LAZY) {
818 shl_flags |= BIND_DEFERRED;
819 }
820 if (flags & PR_LD_NOW) {
821 shl_flags |= BIND_IMMEDIATE;
822 }
823 /* No equivalent of PR_LD_GLOBAL and PR_LD_LOCAL. */
824 h = shl_load(name, shl_flags, 0L);
825 #elif defined(USE_MACH_DYLD)
826 NSModule h = pr_LoadMachDyldModule(name);
827 #else
828 #error Configuration error
829 #endif
830 if (!h) {
831 oserr = _MD_ERRNO();
832 PR_DELETE(lm);
833 goto unlock;
834 }
835 lm->name = strdup(name);
836 lm->dlh = h;
837 lm->next = pr_loadmap;
838 pr_loadmap = lm;
839 }
840 #endif /* HAVE_DLL */
841 #endif /* XP_UNIX && !(XP_MACOSX && USE_MACH_DYLD) */
842
843 lm->refCount = 1;
844
845 #ifdef XP_BEOS
846 {
847 image_info info;
848 int32 cookie = 0;
849 image_id imageid = B_ERROR;
850 image_id stubid = B_ERROR;
851 PRLibrary *p;
852
853 for (p = pr_loadmap; p != NULL; p = p->next) {
854 /* hopefully, our caller will always use the same string
855 to refer to the same library */
856 if (strcmp(name, p->name) == 0) {
857 /* we've already loaded this library */
858 imageid = info.id;
859 lm->refCount++;
860 break;
861 }
862 }
863
864 if(imageid == B_ERROR) {
865 /* it appears the library isn't yet loaded - load it now */
866 char stubName [B_PATH_NAME_LENGTH + 1];
867
868 /* the following is a work-around to a "bug" in the beos -
869 the beos system loader allows only 32M (system-wide)
870 to be used by code loaded as "add-ons" (code loaded
871 through the 'load_add_on()' system call, which includes
872 mozilla components), but allows 256M to be used by
873 shared libraries.
874
875 unfortunately, mozilla is too large to fit into the
876 "add-on" space, so we must trick the loader into
877 loading some of the components as shared libraries. this
878 is accomplished by creating a "stub" add-on (an empty
879 shared object), and linking it with the component
880 (the actual .so file generated by the build process,
881 without any modifications). when this stub is loaded
882 by load_add_on(), the loader will automatically load the
883 component into the shared library space.
884 */
885
886 strcpy(stubName, name);
887 strcat(stubName, ".stub");
888
889 /* first, attempt to load the stub (thereby loading the
890 component as a shared library */
891 if ((stubid = load_add_on(stubName)) > B_ERROR) {
892 /* the stub was loaded successfully. */
893 imageid = B_FILE_NOT_FOUND;
894
895 cookie = 0;
896 while (get_next_image_info(0, &cookie, &info) == B_OK) {
897 const char *endOfSystemName = strrchr(info.name, '/');
898 const char *endOfPassedName = strrchr(name, '/');
899 if( 0 == endOfSystemName )
900 endOfSystemName = info.name;
901 else
902 endOfSystemName++;
903 if( 0 == endOfPassedName )
904 endOfPassedName = name;
905 else
906 endOfPassedName++;
907 if (strcmp(endOfSystemName, endOfPassedName) == 0) {
908 /* this is the actual component - remember it */
909 imageid = info.id;
910 break;
911 }
912 }
913
914 } else {
915 /* we failed to load the "stub" - try to load the
916 component directly as an add-on */
917 stubid = B_ERROR;
918 imageid = load_add_on(name);
919 }
920 }
921
922 if (imageid <= B_ERROR) {
923 oserr = imageid;
924 PR_DELETE( lm );
925 goto unlock;
926 }
927 lm->name = strdup(name);
928 lm->dlh = (void*)imageid;
929 lm->stub_dlh = (void*)stubid;
930 lm->next = pr_loadmap;
931 pr_loadmap = lm;
932 }
933 #endif
934
935 result = lm; /* success */
936 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name) );
937
938 unlock:
939 if (result == NULL) {
940 PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr);
941 DLLErrorInternal(oserr); /* sets error text */
942 }
943 #ifdef WIN32
944 if (utf8name_malloc)
945 PR_Free(utf8name_malloc);
946 if (wname_malloc)
947 PR_Free(wname_malloc);
948 #endif
949 PR_ExitMonitor(pr_linker_lock);
950 return result;
951 }
952
953 /*
954 ** Unload a shared library which was loaded via PR_LoadLibrary
955 */
956 PR_IMPLEMENT(PRStatus)
957 PR_UnloadLibrary(PRLibrary *lib)
958 {
959 int result = 0;
960 PRStatus status = PR_SUCCESS;
961
962 if ((lib == 0) || (lib->refCount <= 0)) {
963 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
964 return PR_FAILURE;
965 }
966
967 PR_EnterMonitor(pr_linker_lock);
968 if (--lib->refCount > 0) {
969 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
970 ("%s decr => %d",
971 lib->name, lib->refCount));
972 goto done;
973 }
974
975 #ifdef XP_BEOS
976 if(((image_id)lib->stub_dlh) == B_ERROR)
977 unload_add_on( (image_id) lib->dlh );
978 else
979 unload_add_on( (image_id) lib->stub_dlh);
980 #endif
981
982 #ifdef XP_UNIX
983 #ifdef HAVE_DLL
984 #ifdef USE_DLFCN
985 result = dlclose(lib->dlh);
986 #elif defined(USE_HPSHL)
987 result = shl_unload(lib->dlh);
988 #elif defined(USE_MACH_DYLD)
989 if (lib->dlh)
990 result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1;
991 #else
992 #error Configuration error
993 #endif
994 #endif /* HAVE_DLL */
995 #endif /* XP_UNIX */
996 #ifdef XP_PC
997 if (lib->dlh) {
998 FreeLibrary((HINSTANCE)(lib->dlh));
999 lib->dlh = (HINSTANCE)NULL;
1000 }
1001 #endif /* XP_PC */
1002
1003 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
1004 /* Close the connection */
1005 if (lib->connection)
1006 CloseConnection(&(lib->connection));
1007 if (lib->bundle)
1008 CFRelease(lib->bundle);
1009 if (lib->wrappers)
1010 CFRelease(lib->wrappers);
1011 /* No way to unload an image (lib->image) */
1012 #endif
1013
1014 /* unlink from library search list */
1015 if (pr_loadmap == lib)
1016 pr_loadmap = pr_loadmap->next;
1017 else if (pr_loadmap != NULL) {
1018 PRLibrary* prev = pr_loadmap;
1019 PRLibrary* next = pr_loadmap->next;
1020 while (next != NULL) {
1021 if (next == lib) {
1022 prev->next = next->next;
1023 goto freeLib;
1024 }
1025 prev = next;
1026 next = next->next;
1027 }
1028 /*
1029 * fail (the library is not on the _pr_loadmap list),
1030 * but don't wipe out an error from dlclose/shl_unload.
1031 */
1032 PR_ASSERT(!"_pr_loadmap and lib->refCount inconsistent");
1033 if (result == 0) {
1034 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
1035 status = PR_FAILURE;
1036 }
1037 }
1038 /*
1039 * We free the PRLibrary structure whether dlclose/shl_unload
1040 * succeeds or not.
1041 */
1042
1043 freeLib:
1044 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
1045 free(lib->name);
1046 lib->name = NULL;
1047 PR_DELETE(lib);
1048 if (result != 0) {
1049 PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
1050 DLLErrorInternal(_MD_ERRNO());
1051 status = PR_FAILURE;
1052 }
1053
1054 done:
1055 PR_ExitMonitor(pr_linker_lock);
1056 return status;
1057 }
1058
1059 static void*
1060 pr_FindSymbolInLib(PRLibrary *lm, const char *name)
1061 {
1062 void *f = NULL;
1063 #ifdef XP_OS2
1064 int rc;
1065 #endif
1066
1067 if (lm->staticTable != NULL) {
1068 const PRStaticLinkTable* tp;
1069 for (tp = lm->staticTable; tp->name; tp++) {
1070 if (strcmp(name, tp->name) == 0) {
1071 return (void*) tp->fp;
1072 }
1073 }
1074 /*
1075 ** If the symbol was not found in the static table then check if
1076 ** the symbol was exported in the DLL... Win16 only!!
1077 */
1078 #if !defined(WIN16) && !defined(XP_BEOS)
1079 PR_SetError(PR_FIND_SYMBOL_ERROR, 0);
1080 return (void*)NULL;
1081 #endif
1082 }
1083
1084 #ifdef XP_OS2
1085 rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
1086 #if defined(NEED_LEADING_UNDERSCORE)
1087 /*
1088 * Older plugins (not built using GCC) will have symbols that are not
1089 * underscore prefixed. We check for that here.
1090 */
1091 if (rc != NO_ERROR) {
1092 name++;
1093 DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
1094 }
1095 #endif
1096 #endif /* XP_OS2 */
1097
1098 #ifdef WIN32
1099 f = GetProcAddress(lm->dlh, name);
1100 #endif /* WIN32 */
1101
1102 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
1103 /* add this offset to skip the leading underscore in name */
1104 #define SYM_OFFSET 1
1105 if (lm->bundle) {
1106 CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII);
1107 if (nameRef) {
1108 f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef);
1109 CFRelease(nameRef);
1110 }
1111 }
1112 if (lm->connection) {
1113 Ptr symAddr;
1114 CFragSymbolClass symClass;
1115 Str255 pName;
1116
1117 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_O FFSET));
1118
1119 c2pstrcpy(pName, name + SYM_OFFSET);
1120
1121 f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
1122
1123 #ifdef __ppc__
1124 /* callers expect mach-o function pointers, so must wrap tvectors with g lue. */
1125 if (f && symClass == kTVectorCFragSymbol) {
1126 f = TV2FP(lm->wrappers, name + SYM_OFFSET, f);
1127 }
1128 #endif /* __ppc__ */
1129
1130 if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main;
1131 }
1132 if (lm->image) {
1133 NSSymbol symbol;
1134 symbol = NSLookupSymbolInImage(lm->image, name,
1135 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1136 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
1137 if (symbol != NULL)
1138 f = NSAddressOfSymbol(symbol);
1139 else
1140 f = NULL;
1141 }
1142 #undef SYM_OFFSET
1143 #endif /* XP_MACOSX && USE_MACH_DYLD */
1144
1145 #ifdef XP_BEOS
1146 if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_T EXT, &f ) ) {
1147 f = NULL;
1148 }
1149 #endif
1150
1151 #ifdef XP_UNIX
1152 #ifdef HAVE_DLL
1153 #ifdef USE_DLFCN
1154 f = dlsym(lm->dlh, name);
1155 #elif defined(USE_HPSHL)
1156 if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) {
1157 f = NULL;
1158 }
1159 #elif defined(USE_MACH_DYLD)
1160 if (lm->dlh) {
1161 NSSymbol symbol;
1162 symbol = NSLookupSymbolInModule(lm->dlh, name);
1163 if (symbol != NULL)
1164 f = NSAddressOfSymbol(symbol);
1165 else
1166 f = NULL;
1167 }
1168 #endif
1169 #endif /* HAVE_DLL */
1170 #endif /* XP_UNIX */
1171 if (f == NULL) {
1172 PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
1173 DLLErrorInternal(_MD_ERRNO());
1174 }
1175 return f;
1176 }
1177
1178 /*
1179 ** Called by class loader to resolve missing native's
1180 */
1181 PR_IMPLEMENT(void*)
1182 PR_FindSymbol(PRLibrary *lib, const char *raw_name)
1183 {
1184 void *f = NULL;
1185 #if defined(NEED_LEADING_UNDERSCORE)
1186 char *name;
1187 #else
1188 const char *name;
1189 #endif
1190 /*
1191 ** Mangle the raw symbol name in any way that is platform specific.
1192 */
1193 #if defined(NEED_LEADING_UNDERSCORE)
1194 /* Need a leading _ */
1195 name = PR_smprintf("_%s", raw_name);
1196 #elif defined(AIX)
1197 /*
1198 ** AIX with the normal linker put's a "." in front of the symbol
1199 ** name. When use "svcc" and "svld" then the "." disappears. Go
1200 ** figure.
1201 */
1202 name = raw_name;
1203 #else
1204 name = raw_name;
1205 #endif
1206
1207 PR_EnterMonitor(pr_linker_lock);
1208 PR_ASSERT(lib != NULL);
1209 f = pr_FindSymbolInLib(lib, name);
1210
1211 #if defined(NEED_LEADING_UNDERSCORE)
1212 PR_smprintf_free(name);
1213 #endif
1214
1215 PR_ExitMonitor(pr_linker_lock);
1216 return f;
1217 }
1218
1219 /*
1220 ** Return the address of the function 'raw_name' in the library 'lib'
1221 */
1222 PR_IMPLEMENT(PRFuncPtr)
1223 PR_FindFunctionSymbol(PRLibrary *lib, const char *raw_name)
1224 {
1225 return ((PRFuncPtr) PR_FindSymbol(lib, raw_name));
1226 }
1227
1228 PR_IMPLEMENT(void*)
1229 PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
1230 {
1231 void *f = NULL;
1232 #if defined(NEED_LEADING_UNDERSCORE)
1233 char *name;
1234 #else
1235 const char *name;
1236 #endif
1237 PRLibrary* lm;
1238
1239 if (!_pr_initialized) _PR_ImplicitInitialization();
1240 /*
1241 ** Mangle the raw symbol name in any way that is platform specific.
1242 */
1243 #if defined(NEED_LEADING_UNDERSCORE)
1244 /* Need a leading _ */
1245 name = PR_smprintf("_%s", raw_name);
1246 #elif defined(AIX)
1247 /*
1248 ** AIX with the normal linker put's a "." in front of the symbol
1249 ** name. When use "svcc" and "svld" then the "." disappears. Go
1250 ** figure.
1251 */
1252 name = raw_name;
1253 #else
1254 name = raw_name;
1255 #endif
1256
1257 PR_EnterMonitor(pr_linker_lock);
1258
1259 /* search all libraries */
1260 for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
1261 f = pr_FindSymbolInLib(lm, name);
1262 if (f != NULL) {
1263 *lib = lm;
1264 lm->refCount++;
1265 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
1266 ("%s incr => %d (for %s)",
1267 lm->name, lm->refCount, name));
1268 break;
1269 }
1270 }
1271 #if defined(NEED_LEADING_UNDERSCORE)
1272 PR_smprintf_free(name);
1273 #endif
1274
1275 PR_ExitMonitor(pr_linker_lock);
1276 return f;
1277 }
1278
1279 PR_IMPLEMENT(PRFuncPtr)
1280 PR_FindFunctionSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
1281 {
1282 return ((PRFuncPtr) PR_FindSymbolAndLibrary(raw_name, lib));
1283 }
1284
1285 /*
1286 ** Add a static library to the list of loaded libraries. If LoadLibrary
1287 ** is called with the name then we will pretend it was already loaded
1288 */
1289 PR_IMPLEMENT(PRLibrary*)
1290 PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt)
1291 {
1292 PRLibrary *lm=NULL;
1293 PRLibrary* result = NULL;
1294
1295 if (!_pr_initialized) _PR_ImplicitInitialization();
1296
1297 /* See if library is already loaded */
1298 PR_EnterMonitor(pr_linker_lock);
1299
1300 /* If the lbrary is already loaded, then add the static table information... */
1301 result = pr_UnlockedFindLibrary(name);
1302 if (result != NULL) {
1303 PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) );
1304 result->staticTable = slt;
1305 goto unlock;
1306 }
1307
1308 /* Add library to list...Mark it static */
1309 lm = PR_NEWZAP(PRLibrary);
1310 if (lm == NULL) goto unlock;
1311
1312 lm->name = strdup(name);
1313 lm->refCount = 1;
1314 lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0;
1315 lm->staticTable = slt;
1316 lm->next = pr_loadmap;
1317 pr_loadmap = lm;
1318
1319 result = lm; /* success */
1320 PR_ASSERT(lm->refCount == 1);
1321 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->nam e));
1322 unlock:
1323 PR_ExitMonitor(pr_linker_lock);
1324 return result;
1325 }
1326
1327 PR_IMPLEMENT(char *)
1328 PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr)
1329 {
1330 #if defined(USE_DLFCN) && defined(HAVE_DLADDR)
1331 Dl_info dli;
1332 char *result;
1333
1334 if (dladdr((void *)addr, &dli) == 0) {
1335 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1336 DLLErrorInternal(_MD_ERRNO());
1337 return NULL;
1338 }
1339 result = PR_Malloc(strlen(dli.dli_fname)+1);
1340 if (result != NULL) {
1341 strcpy(result, dli.dli_fname);
1342 }
1343 return result;
1344 #elif defined(USE_MACH_DYLD)
1345 char *result;
1346 const char *image_name;
1347 int i, count = _dyld_image_count();
1348
1349 for (i = 0; i < count; i++) {
1350 image_name = _dyld_get_image_name(i);
1351 if (strstr(image_name, name) != NULL) {
1352 result = PR_Malloc(strlen(image_name)+1);
1353 if (result != NULL) {
1354 strcpy(result, image_name);
1355 }
1356 return result;
1357 }
1358 }
1359 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1360 return NULL;
1361 #elif defined(AIX)
1362 char *result;
1363 #define LD_INFO_INCREMENT 64
1364 struct ld_info *info;
1365 unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info);
1366 struct ld_info *infop;
1367 int loadflags = L_GETINFO | L_IGNOREUNLOAD;
1368
1369 for (;;) {
1370 info = PR_Malloc(info_length);
1371 if (info == NULL) {
1372 return NULL;
1373 }
1374 /* If buffer is too small, loadquery fails with ENOMEM. */
1375 if (loadquery(loadflags, info, info_length) != -1) {
1376 break;
1377 }
1378 /*
1379 * Calling loadquery when compiled for 64-bit with the
1380 * L_IGNOREUNLOAD flag can cause an invalid argument error
1381 * on AIX 5.1. Detect this error the first time that
1382 * loadquery is called, and try calling it again without
1383 * this flag set.
1384 */
1385 if (errno == EINVAL && (loadflags & L_IGNOREUNLOAD)) {
1386 loadflags &= ~L_IGNOREUNLOAD;
1387 if (loadquery(loadflags, info, info_length) != -1) {
1388 break;
1389 }
1390 }
1391 PR_Free(info);
1392 if (errno != ENOMEM) {
1393 /* should not happen */
1394 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1395 return NULL;
1396 }
1397 /* retry with a larger buffer */
1398 info_length += LD_INFO_INCREMENT * sizeof(struct ld_info);
1399 }
1400
1401 for (infop = info;
1402 ;
1403 infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) {
1404 unsigned long start = (unsigned long)infop->ldinfo_dataorg;
1405 unsigned long end = start + infop->ldinfo_datasize;
1406 if (start <= (unsigned long)addr && end > (unsigned long)addr) {
1407 result = PR_Malloc(strlen(infop->ldinfo_filename)+1);
1408 if (result != NULL) {
1409 strcpy(result, infop->ldinfo_filename);
1410 }
1411 break;
1412 }
1413 if (!infop->ldinfo_next) {
1414 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1415 result = NULL;
1416 break;
1417 }
1418 }
1419 PR_Free(info);
1420 return result;
1421 #elif defined(OSF1)
1422 /* Contributed by Steve Streeter of HP */
1423 ldr_process_t process, ldr_my_process();
1424 ldr_module_t mod_id;
1425 ldr_module_info_t info;
1426 ldr_region_t regno;
1427 ldr_region_info_t reginfo;
1428 size_t retsize;
1429 int rv;
1430 char *result;
1431
1432 /* Get process for which dynamic modules will be listed */
1433
1434 process = ldr_my_process();
1435
1436 /* Attach to process */
1437
1438 rv = ldr_xattach(process);
1439 if (rv) {
1440 /* should not happen */
1441 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1442 return NULL;
1443 }
1444
1445 /* Print information for list of modules */
1446
1447 mod_id = LDR_NULL_MODULE;
1448
1449 for (;;) {
1450
1451 /* Get information for the next module in the module list. */
1452
1453 ldr_next_module(process, &mod_id);
1454 if (ldr_inq_module(process, mod_id, &info, sizeof(info),
1455 &retsize) != 0) {
1456 /* No more modules */
1457 break;
1458 }
1459 if (retsize < sizeof(info)) {
1460 continue;
1461 }
1462
1463 /*
1464 * Get information for each region in the module and check if any
1465 * contain the address of this function.
1466 */
1467
1468 for (regno = 0; ; regno++) {
1469 if (ldr_inq_region(process, mod_id, regno, &reginfo,
1470 sizeof(reginfo), &retsize) != 0) {
1471 /* No more regions */
1472 break;
1473 }
1474 if (((unsigned long)reginfo.lri_mapaddr <=
1475 (unsigned long)addr) &&
1476 (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) >
1477 (unsigned long)addr)) {
1478 /* Found it. */
1479 result = PR_Malloc(strlen(info.lmi_name)+1);
1480 if (result != NULL) {
1481 strcpy(result, info.lmi_name);
1482 }
1483 return result;
1484 }
1485 }
1486 }
1487 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1488 return NULL;
1489 #elif defined(HPUX) && defined(USE_HPSHL)
1490 int index;
1491 struct shl_descriptor desc;
1492 char *result;
1493
1494 for (index = 0; shl_get_r(index, &desc) == 0; index++) {
1495 if (strstr(desc.filename, name) != NULL) {
1496 result = PR_Malloc(strlen(desc.filename)+1);
1497 if (result != NULL) {
1498 strcpy(result, desc.filename);
1499 }
1500 return result;
1501 }
1502 }
1503 /*
1504 * Since the index value of a library is decremented if
1505 * a library preceding it in the shared library search
1506 * list was unloaded, it is possible that we missed some
1507 * libraries as we went up the list. So we should go
1508 * down the list to be sure that we not miss anything.
1509 */
1510 for (index--; index >= 0; index--) {
1511 if ((shl_get_r(index, &desc) == 0)
1512 && (strstr(desc.filename, name) != NULL)) {
1513 result = PR_Malloc(strlen(desc.filename)+1);
1514 if (result != NULL) {
1515 strcpy(result, desc.filename);
1516 }
1517 return result;
1518 }
1519 }
1520 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1521 return NULL;
1522 #elif defined(HPUX) && defined(USE_DLFCN)
1523 struct load_module_desc desc;
1524 char *result;
1525 const char *module_name;
1526
1527 if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) {
1528 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1529 DLLErrorInternal(_MD_ERRNO());
1530 return NULL;
1531 }
1532 module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0);
1533 if (module_name == NULL) {
1534 /* should not happen */
1535 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1536 DLLErrorInternal(_MD_ERRNO());
1537 return NULL;
1538 }
1539 result = PR_Malloc(strlen(module_name)+1);
1540 if (result != NULL) {
1541 strcpy(result, module_name);
1542 }
1543 return result;
1544 #elif defined(WIN32)
1545 PRUnichar wname[MAX_PATH];
1546 HMODULE handle = NULL;
1547 PRUnichar module_name[MAX_PATH];
1548 int len;
1549 char *result;
1550
1551 if (MultiByteToWideChar(CP_ACP, 0, name, -1, wname, MAX_PATH)) {
1552 handle = GetModuleHandleW(wname);
1553 }
1554 if (handle == NULL) {
1555 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1556 DLLErrorInternal(_MD_ERRNO());
1557 return NULL;
1558 }
1559 if (GetModuleFileNameW(handle, module_name, MAX_PATH) == 0) {
1560 /* should not happen */
1561 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1562 return NULL;
1563 }
1564 len = WideCharToMultiByte(CP_ACP, 0, module_name, -1,
1565 NULL, 0, NULL, NULL);
1566 if (len == 0) {
1567 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1568 return NULL;
1569 }
1570 result = PR_Malloc(len * sizeof(PRUnichar));
1571 if (result != NULL) {
1572 WideCharToMultiByte(CP_ACP, 0, module_name, -1,
1573 result, len, NULL, NULL);
1574 }
1575 return result;
1576 #elif defined(XP_OS2)
1577 HMODULE module = NULL;
1578 char module_name[_MAX_PATH];
1579 char *result;
1580 APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr) ;
1581 if ((NO_ERROR != ulrc) || (NULL == module) ) {
1582 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1583 DLLErrorInternal(_MD_ERRNO());
1584 return NULL;
1585 }
1586 ulrc = DosQueryModuleName(module, sizeof module_name, module_name);
1587 if (NO_ERROR != ulrc) {
1588 /* should not happen */
1589 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1590 return NULL;
1591 }
1592 result = PR_Malloc(strlen(module_name)+1);
1593 if (result != NULL) {
1594 strcpy(result, module_name);
1595 }
1596 return result;
1597 #else
1598 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1599 return NULL;
1600 #endif
1601 }
OLDNEW
« no previous file with comments | « mozilla/nsprpub/pr/src/io/prstdio.c ('k') | mozilla/nsprpub/pr/src/malloc/prmalloc.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698