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

Side by Side Diff: nspr/pr/src/linking/prlink.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nspr/pr/src/io/prstdio.c ('k') | nspr/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) {
963 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
964 return PR_FAILURE;
965 }
966
967 PR_EnterMonitor(pr_linker_lock);
968
969 if (lib->refCount <= 0) {
970 PR_ExitMonitor(pr_linker_lock);
971 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
972 return PR_FAILURE;
973 }
974
975 if (--lib->refCount > 0) {
976 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
977 ("%s decr => %d",
978 lib->name, lib->refCount));
979 goto done;
980 }
981
982 #ifdef XP_BEOS
983 if(((image_id)lib->stub_dlh) == B_ERROR)
984 unload_add_on( (image_id) lib->dlh );
985 else
986 unload_add_on( (image_id) lib->stub_dlh);
987 #endif
988
989 #ifdef XP_UNIX
990 #ifdef HAVE_DLL
991 #ifdef USE_DLFCN
992 result = dlclose(lib->dlh);
993 #elif defined(USE_HPSHL)
994 result = shl_unload(lib->dlh);
995 #elif defined(USE_MACH_DYLD)
996 if (lib->dlh)
997 result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1;
998 #else
999 #error Configuration error
1000 #endif
1001 #endif /* HAVE_DLL */
1002 #endif /* XP_UNIX */
1003 #ifdef XP_PC
1004 if (lib->dlh) {
1005 FreeLibrary((HINSTANCE)(lib->dlh));
1006 lib->dlh = (HINSTANCE)NULL;
1007 }
1008 #endif /* XP_PC */
1009
1010 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
1011 /* Close the connection */
1012 if (lib->connection)
1013 CloseConnection(&(lib->connection));
1014 if (lib->bundle)
1015 CFRelease(lib->bundle);
1016 if (lib->wrappers)
1017 CFRelease(lib->wrappers);
1018 /* No way to unload an image (lib->image) */
1019 #endif
1020
1021 /* unlink from library search list */
1022 if (pr_loadmap == lib)
1023 pr_loadmap = pr_loadmap->next;
1024 else if (pr_loadmap != NULL) {
1025 PRLibrary* prev = pr_loadmap;
1026 PRLibrary* next = pr_loadmap->next;
1027 while (next != NULL) {
1028 if (next == lib) {
1029 prev->next = next->next;
1030 goto freeLib;
1031 }
1032 prev = next;
1033 next = next->next;
1034 }
1035 /*
1036 * fail (the library is not on the _pr_loadmap list),
1037 * but don't wipe out an error from dlclose/shl_unload.
1038 */
1039 PR_NOT_REACHED("_pr_loadmap and lib->refCount inconsistent");
1040 if (result == 0) {
1041 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
1042 status = PR_FAILURE;
1043 }
1044 }
1045 /*
1046 * We free the PRLibrary structure whether dlclose/shl_unload
1047 * succeeds or not.
1048 */
1049
1050 freeLib:
1051 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
1052 free(lib->name);
1053 lib->name = NULL;
1054 PR_DELETE(lib);
1055 if (result != 0) {
1056 PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
1057 DLLErrorInternal(_MD_ERRNO());
1058 status = PR_FAILURE;
1059 }
1060
1061 done:
1062 PR_ExitMonitor(pr_linker_lock);
1063 return status;
1064 }
1065
1066 static void*
1067 pr_FindSymbolInLib(PRLibrary *lm, const char *name)
1068 {
1069 void *f = NULL;
1070 #ifdef XP_OS2
1071 int rc;
1072 #endif
1073
1074 if (lm->staticTable != NULL) {
1075 const PRStaticLinkTable* tp;
1076 for (tp = lm->staticTable; tp->name; tp++) {
1077 if (strcmp(name, tp->name) == 0) {
1078 return (void*) tp->fp;
1079 }
1080 }
1081 /*
1082 ** If the symbol was not found in the static table then check if
1083 ** the symbol was exported in the DLL... Win16 only!!
1084 */
1085 #if !defined(WIN16) && !defined(XP_BEOS)
1086 PR_SetError(PR_FIND_SYMBOL_ERROR, 0);
1087 return (void*)NULL;
1088 #endif
1089 }
1090
1091 #ifdef XP_OS2
1092 rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
1093 #if defined(NEED_LEADING_UNDERSCORE)
1094 /*
1095 * Older plugins (not built using GCC) will have symbols that are not
1096 * underscore prefixed. We check for that here.
1097 */
1098 if (rc != NO_ERROR) {
1099 name++;
1100 DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
1101 }
1102 #endif
1103 #endif /* XP_OS2 */
1104
1105 #ifdef WIN32
1106 f = GetProcAddress(lm->dlh, name);
1107 #endif /* WIN32 */
1108
1109 #if defined(XP_MACOSX) && defined(USE_MACH_DYLD)
1110 /* add this offset to skip the leading underscore in name */
1111 #define SYM_OFFSET 1
1112 if (lm->bundle) {
1113 CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII);
1114 if (nameRef) {
1115 f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef);
1116 CFRelease(nameRef);
1117 }
1118 }
1119 if (lm->connection) {
1120 Ptr symAddr;
1121 CFragSymbolClass symClass;
1122 Str255 pName;
1123
1124 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_O FFSET));
1125
1126 c2pstrcpy(pName, name + SYM_OFFSET);
1127
1128 f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
1129
1130 #ifdef __ppc__
1131 /* callers expect mach-o function pointers, so must wrap tvectors with g lue. */
1132 if (f && symClass == kTVectorCFragSymbol) {
1133 f = TV2FP(lm->wrappers, name + SYM_OFFSET, f);
1134 }
1135 #endif /* __ppc__ */
1136
1137 if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main;
1138 }
1139 if (lm->image) {
1140 NSSymbol symbol;
1141 symbol = NSLookupSymbolInImage(lm->image, name,
1142 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1143 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
1144 if (symbol != NULL)
1145 f = NSAddressOfSymbol(symbol);
1146 else
1147 f = NULL;
1148 }
1149 #undef SYM_OFFSET
1150 #endif /* XP_MACOSX && USE_MACH_DYLD */
1151
1152 #ifdef XP_BEOS
1153 if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_T EXT, &f ) ) {
1154 f = NULL;
1155 }
1156 #endif
1157
1158 #ifdef XP_UNIX
1159 #ifdef HAVE_DLL
1160 #ifdef USE_DLFCN
1161 f = dlsym(lm->dlh, name);
1162 #elif defined(USE_HPSHL)
1163 if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) {
1164 f = NULL;
1165 }
1166 #elif defined(USE_MACH_DYLD)
1167 if (lm->dlh) {
1168 NSSymbol symbol;
1169 symbol = NSLookupSymbolInModule(lm->dlh, name);
1170 if (symbol != NULL)
1171 f = NSAddressOfSymbol(symbol);
1172 else
1173 f = NULL;
1174 }
1175 #endif
1176 #endif /* HAVE_DLL */
1177 #endif /* XP_UNIX */
1178 if (f == NULL) {
1179 PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
1180 DLLErrorInternal(_MD_ERRNO());
1181 }
1182 return f;
1183 }
1184
1185 /*
1186 ** Called by class loader to resolve missing native's
1187 */
1188 PR_IMPLEMENT(void*)
1189 PR_FindSymbol(PRLibrary *lib, const char *raw_name)
1190 {
1191 void *f = NULL;
1192 #if defined(NEED_LEADING_UNDERSCORE)
1193 char *name;
1194 #else
1195 const char *name;
1196 #endif
1197 /*
1198 ** Mangle the raw symbol name in any way that is platform specific.
1199 */
1200 #if defined(NEED_LEADING_UNDERSCORE)
1201 /* Need a leading _ */
1202 name = PR_smprintf("_%s", raw_name);
1203 #elif defined(AIX)
1204 /*
1205 ** AIX with the normal linker put's a "." in front of the symbol
1206 ** name. When use "svcc" and "svld" then the "." disappears. Go
1207 ** figure.
1208 */
1209 name = raw_name;
1210 #else
1211 name = raw_name;
1212 #endif
1213
1214 PR_EnterMonitor(pr_linker_lock);
1215 PR_ASSERT(lib != NULL);
1216 f = pr_FindSymbolInLib(lib, name);
1217
1218 #if defined(NEED_LEADING_UNDERSCORE)
1219 PR_smprintf_free(name);
1220 #endif
1221
1222 PR_ExitMonitor(pr_linker_lock);
1223 return f;
1224 }
1225
1226 /*
1227 ** Return the address of the function 'raw_name' in the library 'lib'
1228 */
1229 PR_IMPLEMENT(PRFuncPtr)
1230 PR_FindFunctionSymbol(PRLibrary *lib, const char *raw_name)
1231 {
1232 return ((PRFuncPtr) PR_FindSymbol(lib, raw_name));
1233 }
1234
1235 PR_IMPLEMENT(void*)
1236 PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
1237 {
1238 void *f = NULL;
1239 #if defined(NEED_LEADING_UNDERSCORE)
1240 char *name;
1241 #else
1242 const char *name;
1243 #endif
1244 PRLibrary* lm;
1245
1246 if (!_pr_initialized) _PR_ImplicitInitialization();
1247 /*
1248 ** Mangle the raw symbol name in any way that is platform specific.
1249 */
1250 #if defined(NEED_LEADING_UNDERSCORE)
1251 /* Need a leading _ */
1252 name = PR_smprintf("_%s", raw_name);
1253 #elif defined(AIX)
1254 /*
1255 ** AIX with the normal linker put's a "." in front of the symbol
1256 ** name. When use "svcc" and "svld" then the "." disappears. Go
1257 ** figure.
1258 */
1259 name = raw_name;
1260 #else
1261 name = raw_name;
1262 #endif
1263
1264 PR_EnterMonitor(pr_linker_lock);
1265
1266 /* search all libraries */
1267 for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
1268 f = pr_FindSymbolInLib(lm, name);
1269 if (f != NULL) {
1270 *lib = lm;
1271 lm->refCount++;
1272 PR_LOG(_pr_linker_lm, PR_LOG_MIN,
1273 ("%s incr => %d (for %s)",
1274 lm->name, lm->refCount, name));
1275 break;
1276 }
1277 }
1278 #if defined(NEED_LEADING_UNDERSCORE)
1279 PR_smprintf_free(name);
1280 #endif
1281
1282 PR_ExitMonitor(pr_linker_lock);
1283 return f;
1284 }
1285
1286 PR_IMPLEMENT(PRFuncPtr)
1287 PR_FindFunctionSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
1288 {
1289 return ((PRFuncPtr) PR_FindSymbolAndLibrary(raw_name, lib));
1290 }
1291
1292 /*
1293 ** Add a static library to the list of loaded libraries. If LoadLibrary
1294 ** is called with the name then we will pretend it was already loaded
1295 */
1296 PR_IMPLEMENT(PRLibrary*)
1297 PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt)
1298 {
1299 PRLibrary *lm=NULL;
1300 PRLibrary* result = NULL;
1301
1302 if (!_pr_initialized) _PR_ImplicitInitialization();
1303
1304 /* See if library is already loaded */
1305 PR_EnterMonitor(pr_linker_lock);
1306
1307 /* If the lbrary is already loaded, then add the static table information... */
1308 result = pr_UnlockedFindLibrary(name);
1309 if (result != NULL) {
1310 PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) );
1311 result->staticTable = slt;
1312 goto unlock;
1313 }
1314
1315 /* Add library to list...Mark it static */
1316 lm = PR_NEWZAP(PRLibrary);
1317 if (lm == NULL) goto unlock;
1318
1319 lm->name = strdup(name);
1320 lm->refCount = 1;
1321 lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0;
1322 lm->staticTable = slt;
1323 lm->next = pr_loadmap;
1324 pr_loadmap = lm;
1325
1326 result = lm; /* success */
1327 PR_ASSERT(lm->refCount == 1);
1328 PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->nam e));
1329 unlock:
1330 PR_ExitMonitor(pr_linker_lock);
1331 return result;
1332 }
1333
1334 PR_IMPLEMENT(char *)
1335 PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr)
1336 {
1337 #if defined(USE_DLFCN) && defined(HAVE_DLADDR)
1338 Dl_info dli;
1339 char *result;
1340
1341 if (dladdr((void *)addr, &dli) == 0) {
1342 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1343 DLLErrorInternal(_MD_ERRNO());
1344 return NULL;
1345 }
1346 result = PR_Malloc(strlen(dli.dli_fname)+1);
1347 if (result != NULL) {
1348 strcpy(result, dli.dli_fname);
1349 }
1350 return result;
1351 #elif defined(USE_MACH_DYLD)
1352 char *result;
1353 const char *image_name;
1354 int i, count = _dyld_image_count();
1355
1356 for (i = 0; i < count; i++) {
1357 image_name = _dyld_get_image_name(i);
1358 if (strstr(image_name, name) != NULL) {
1359 result = PR_Malloc(strlen(image_name)+1);
1360 if (result != NULL) {
1361 strcpy(result, image_name);
1362 }
1363 return result;
1364 }
1365 }
1366 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1367 return NULL;
1368 #elif defined(AIX)
1369 char *result;
1370 #define LD_INFO_INCREMENT 64
1371 struct ld_info *info;
1372 unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info);
1373 struct ld_info *infop;
1374 int loadflags = L_GETINFO | L_IGNOREUNLOAD;
1375
1376 for (;;) {
1377 info = PR_Malloc(info_length);
1378 if (info == NULL) {
1379 return NULL;
1380 }
1381 /* If buffer is too small, loadquery fails with ENOMEM. */
1382 if (loadquery(loadflags, info, info_length) != -1) {
1383 break;
1384 }
1385 /*
1386 * Calling loadquery when compiled for 64-bit with the
1387 * L_IGNOREUNLOAD flag can cause an invalid argument error
1388 * on AIX 5.1. Detect this error the first time that
1389 * loadquery is called, and try calling it again without
1390 * this flag set.
1391 */
1392 if (errno == EINVAL && (loadflags & L_IGNOREUNLOAD)) {
1393 loadflags &= ~L_IGNOREUNLOAD;
1394 if (loadquery(loadflags, info, info_length) != -1) {
1395 break;
1396 }
1397 }
1398 PR_Free(info);
1399 if (errno != ENOMEM) {
1400 /* should not happen */
1401 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1402 return NULL;
1403 }
1404 /* retry with a larger buffer */
1405 info_length += LD_INFO_INCREMENT * sizeof(struct ld_info);
1406 }
1407
1408 for (infop = info;
1409 ;
1410 infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) {
1411 unsigned long start = (unsigned long)infop->ldinfo_dataorg;
1412 unsigned long end = start + infop->ldinfo_datasize;
1413 if (start <= (unsigned long)addr && end > (unsigned long)addr) {
1414 result = PR_Malloc(strlen(infop->ldinfo_filename)+1);
1415 if (result != NULL) {
1416 strcpy(result, infop->ldinfo_filename);
1417 }
1418 break;
1419 }
1420 if (!infop->ldinfo_next) {
1421 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1422 result = NULL;
1423 break;
1424 }
1425 }
1426 PR_Free(info);
1427 return result;
1428 #elif defined(OSF1)
1429 /* Contributed by Steve Streeter of HP */
1430 ldr_process_t process, ldr_my_process();
1431 ldr_module_t mod_id;
1432 ldr_module_info_t info;
1433 ldr_region_t regno;
1434 ldr_region_info_t reginfo;
1435 size_t retsize;
1436 int rv;
1437 char *result;
1438
1439 /* Get process for which dynamic modules will be listed */
1440
1441 process = ldr_my_process();
1442
1443 /* Attach to process */
1444
1445 rv = ldr_xattach(process);
1446 if (rv) {
1447 /* should not happen */
1448 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1449 return NULL;
1450 }
1451
1452 /* Print information for list of modules */
1453
1454 mod_id = LDR_NULL_MODULE;
1455
1456 for (;;) {
1457
1458 /* Get information for the next module in the module list. */
1459
1460 ldr_next_module(process, &mod_id);
1461 if (ldr_inq_module(process, mod_id, &info, sizeof(info),
1462 &retsize) != 0) {
1463 /* No more modules */
1464 break;
1465 }
1466 if (retsize < sizeof(info)) {
1467 continue;
1468 }
1469
1470 /*
1471 * Get information for each region in the module and check if any
1472 * contain the address of this function.
1473 */
1474
1475 for (regno = 0; ; regno++) {
1476 if (ldr_inq_region(process, mod_id, regno, &reginfo,
1477 sizeof(reginfo), &retsize) != 0) {
1478 /* No more regions */
1479 break;
1480 }
1481 if (((unsigned long)reginfo.lri_mapaddr <=
1482 (unsigned long)addr) &&
1483 (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) >
1484 (unsigned long)addr)) {
1485 /* Found it. */
1486 result = PR_Malloc(strlen(info.lmi_name)+1);
1487 if (result != NULL) {
1488 strcpy(result, info.lmi_name);
1489 }
1490 return result;
1491 }
1492 }
1493 }
1494 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1495 return NULL;
1496 #elif defined(HPUX) && defined(USE_HPSHL)
1497 int index;
1498 struct shl_descriptor desc;
1499 char *result;
1500
1501 for (index = 0; shl_get_r(index, &desc) == 0; index++) {
1502 if (strstr(desc.filename, name) != NULL) {
1503 result = PR_Malloc(strlen(desc.filename)+1);
1504 if (result != NULL) {
1505 strcpy(result, desc.filename);
1506 }
1507 return result;
1508 }
1509 }
1510 /*
1511 * Since the index value of a library is decremented if
1512 * a library preceding it in the shared library search
1513 * list was unloaded, it is possible that we missed some
1514 * libraries as we went up the list. So we should go
1515 * down the list to be sure that we not miss anything.
1516 */
1517 for (index--; index >= 0; index--) {
1518 if ((shl_get_r(index, &desc) == 0)
1519 && (strstr(desc.filename, name) != NULL)) {
1520 result = PR_Malloc(strlen(desc.filename)+1);
1521 if (result != NULL) {
1522 strcpy(result, desc.filename);
1523 }
1524 return result;
1525 }
1526 }
1527 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
1528 return NULL;
1529 #elif defined(HPUX) && defined(USE_DLFCN)
1530 struct load_module_desc desc;
1531 char *result;
1532 const char *module_name;
1533
1534 if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) {
1535 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1536 DLLErrorInternal(_MD_ERRNO());
1537 return NULL;
1538 }
1539 module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0);
1540 if (module_name == NULL) {
1541 /* should not happen */
1542 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1543 DLLErrorInternal(_MD_ERRNO());
1544 return NULL;
1545 }
1546 result = PR_Malloc(strlen(module_name)+1);
1547 if (result != NULL) {
1548 strcpy(result, module_name);
1549 }
1550 return result;
1551 #elif defined(WIN32)
1552 PRUnichar wname[MAX_PATH];
1553 HMODULE handle = NULL;
1554 PRUnichar module_name[MAX_PATH];
1555 int len;
1556 char *result;
1557
1558 if (MultiByteToWideChar(CP_ACP, 0, name, -1, wname, MAX_PATH)) {
1559 handle = GetModuleHandleW(wname);
1560 }
1561 if (handle == NULL) {
1562 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1563 DLLErrorInternal(_MD_ERRNO());
1564 return NULL;
1565 }
1566 if (GetModuleFileNameW(handle, module_name, MAX_PATH) == 0) {
1567 /* should not happen */
1568 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1569 return NULL;
1570 }
1571 len = WideCharToMultiByte(CP_ACP, 0, module_name, -1,
1572 NULL, 0, NULL, NULL);
1573 if (len == 0) {
1574 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1575 return NULL;
1576 }
1577 result = PR_Malloc(len * sizeof(PRUnichar));
1578 if (result != NULL) {
1579 WideCharToMultiByte(CP_ACP, 0, module_name, -1,
1580 result, len, NULL, NULL);
1581 }
1582 return result;
1583 #elif defined(XP_OS2)
1584 HMODULE module = NULL;
1585 char module_name[_MAX_PATH];
1586 char *result;
1587 APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr) ;
1588 if ((NO_ERROR != ulrc) || (NULL == module) ) {
1589 PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
1590 DLLErrorInternal(_MD_ERRNO());
1591 return NULL;
1592 }
1593 ulrc = DosQueryModuleName(module, sizeof module_name, module_name);
1594 if (NO_ERROR != ulrc) {
1595 /* should not happen */
1596 _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
1597 return NULL;
1598 }
1599 result = PR_Malloc(strlen(module_name)+1);
1600 if (result != NULL) {
1601 strcpy(result, module_name);
1602 }
1603 return result;
1604 #else
1605 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1606 return NULL;
1607 #endif
1608 }
OLDNEW
« no previous file with comments | « nspr/pr/src/io/prstdio.c ('k') | nspr/pr/src/malloc/prmalloc.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698