1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/linking/prlink.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1608 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "primpl.h" 1.10 + 1.11 +#include <string.h> 1.12 + 1.13 +#ifdef XP_BEOS 1.14 +#include <image.h> 1.15 +#endif 1.16 + 1.17 +#if defined(XP_MACOSX) && defined(USE_MACH_DYLD) 1.18 +#include <Carbon/Carbon.h> 1.19 +#include <CoreFoundation/CoreFoundation.h> 1.20 +#endif 1.21 + 1.22 +#ifdef XP_UNIX 1.23 +#ifdef USE_DLFCN 1.24 +#include <dlfcn.h> 1.25 +/* Define these on systems that don't have them. */ 1.26 +#ifndef RTLD_NOW 1.27 +#define RTLD_NOW 0 1.28 +#endif 1.29 +#ifndef RTLD_LAZY 1.30 +#define RTLD_LAZY RTLD_NOW 1.31 +#endif 1.32 +#ifndef RTLD_GLOBAL 1.33 +#define RTLD_GLOBAL 0 1.34 +#endif 1.35 +#ifndef RTLD_LOCAL 1.36 +#define RTLD_LOCAL 0 1.37 +#endif 1.38 +#ifdef AIX 1.39 +#include <sys/ldr.h> 1.40 +#ifndef L_IGNOREUNLOAD /* AIX 4.3.3 does not have L_IGNOREUNLOAD. */ 1.41 +#define L_IGNOREUNLOAD 0x10000000 1.42 +#endif 1.43 +#endif 1.44 +#ifdef OSF1 1.45 +#include <loader.h> 1.46 +#include <rld_interface.h> 1.47 +#endif 1.48 +#elif defined(USE_HPSHL) 1.49 +#include <dl.h> 1.50 +#elif defined(USE_MACH_DYLD) 1.51 +#include <mach-o/dyld.h> 1.52 +#endif 1.53 +#endif /* XP_UNIX */ 1.54 + 1.55 +#define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY 1.56 + 1.57 +/* 1.58 + * On these platforms, symbols have a leading '_'. 1.59 + */ 1.60 +#if (defined(DARWIN) && defined(USE_MACH_DYLD)) \ 1.61 + || defined(XP_OS2) \ 1.62 + || ((defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)) 1.63 +#define NEED_LEADING_UNDERSCORE 1.64 +#endif 1.65 + 1.66 +#define PR_LD_PATHW 0x8000 /* for PR_LibSpec_PathnameU */ 1.67 + 1.68 +/************************************************************************/ 1.69 + 1.70 +struct PRLibrary { 1.71 + char* name; /* Our own copy of the name string */ 1.72 + PRLibrary* next; 1.73 + int refCount; 1.74 + const PRStaticLinkTable* staticTable; 1.75 + 1.76 +#ifdef XP_PC 1.77 +#ifdef XP_OS2 1.78 + HMODULE dlh; 1.79 +#else 1.80 + HINSTANCE dlh; 1.81 +#endif 1.82 +#endif 1.83 + 1.84 +#if defined(XP_MACOSX) && defined(USE_MACH_DYLD) 1.85 + CFragConnectionID connection; 1.86 + CFBundleRef bundle; 1.87 + Ptr main; 1.88 + CFMutableDictionaryRef wrappers; 1.89 + const struct mach_header* image; 1.90 +#endif 1.91 + 1.92 +#ifdef XP_UNIX 1.93 +#if defined(USE_HPSHL) 1.94 + shl_t dlh; 1.95 +#elif defined(USE_MACH_DYLD) 1.96 + NSModule dlh; 1.97 +#else 1.98 + void* dlh; 1.99 +#endif 1.100 +#endif 1.101 + 1.102 +#ifdef XP_BEOS 1.103 + void* dlh; 1.104 + void* stub_dlh; 1.105 +#endif 1.106 +}; 1.107 + 1.108 +static PRLibrary *pr_loadmap; 1.109 +static PRLibrary *pr_exe_loadmap; 1.110 +static PRMonitor *pr_linker_lock; 1.111 +static char* _pr_currentLibPath = NULL; 1.112 + 1.113 +static PRLibrary *pr_LoadLibraryByPathname(const char *name, PRIntn flags); 1.114 + 1.115 +/************************************************************************/ 1.116 + 1.117 +#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) 1.118 +#define ERR_STR_BUF_LENGTH 20 1.119 +#endif 1.120 + 1.121 +static void DLLErrorInternal(PRIntn oserr) 1.122 +/* 1.123 +** This whole function, and most of the code in this file, are run 1.124 +** with a big hairy lock wrapped around it. Not the best of situations, 1.125 +** but will eventually come up with the right answer. 1.126 +*/ 1.127 +{ 1.128 + const char *error = NULL; 1.129 +#ifdef USE_DLFCN 1.130 + error = dlerror(); /* $$$ That'll be wrong some of the time - AOF */ 1.131 +#elif defined(HAVE_STRERROR) 1.132 + error = strerror(oserr); /* this should be okay */ 1.133 +#else 1.134 + char errStrBuf[ERR_STR_BUF_LENGTH]; 1.135 + PR_snprintf(errStrBuf, sizeof(errStrBuf), "error %d", oserr); 1.136 + error = errStrBuf; 1.137 +#endif 1.138 + if (NULL != error) 1.139 + PR_SetErrorText(strlen(error), error); 1.140 +} /* DLLErrorInternal */ 1.141 + 1.142 +void _PR_InitLinker(void) 1.143 +{ 1.144 + PRLibrary *lm = NULL; 1.145 +#if defined(XP_UNIX) 1.146 + void *h; 1.147 +#endif 1.148 + 1.149 + if (!pr_linker_lock) { 1.150 + pr_linker_lock = PR_NewNamedMonitor("linker-lock"); 1.151 + } 1.152 + PR_EnterMonitor(pr_linker_lock); 1.153 + 1.154 +#if defined(XP_PC) 1.155 + lm = PR_NEWZAP(PRLibrary); 1.156 + lm->name = strdup("Executable"); 1.157 +#if defined(XP_OS2) 1.158 + lm->dlh = NULLHANDLE; 1.159 +#else 1.160 + /* A module handle for the executable. */ 1.161 + lm->dlh = GetModuleHandle(NULL); 1.162 +#endif /* ! XP_OS2 */ 1.163 + 1.164 + lm->refCount = 1; 1.165 + lm->staticTable = NULL; 1.166 + pr_exe_loadmap = lm; 1.167 + pr_loadmap = lm; 1.168 + 1.169 +#elif defined(XP_UNIX) 1.170 +#ifdef HAVE_DLL 1.171 +#if defined(USE_DLFCN) && !defined(NO_DLOPEN_NULL) 1.172 + h = dlopen(0, RTLD_LAZY); 1.173 + if (!h) { 1.174 + char *error; 1.175 + 1.176 + DLLErrorInternal(_MD_ERRNO()); 1.177 + error = (char*)PR_MALLOC(PR_GetErrorTextLength()); 1.178 + (void) PR_GetErrorText(error); 1.179 + fprintf(stderr, "failed to initialize shared libraries [%s]\n", 1.180 + error); 1.181 + PR_DELETE(error); 1.182 + abort();/* XXX */ 1.183 + } 1.184 +#elif defined(USE_HPSHL) 1.185 + h = NULL; 1.186 + /* don't abort with this NULL */ 1.187 +#elif defined(USE_MACH_DYLD) || defined(NO_DLOPEN_NULL) 1.188 + h = NULL; /* XXXX toshok */ /* XXXX vlad */ 1.189 +#else 1.190 +#error no dll strategy 1.191 +#endif /* USE_DLFCN */ 1.192 + 1.193 + lm = PR_NEWZAP(PRLibrary); 1.194 + if (lm) { 1.195 + lm->name = strdup("a.out"); 1.196 + lm->refCount = 1; 1.197 + lm->dlh = h; 1.198 + lm->staticTable = NULL; 1.199 + } 1.200 + pr_exe_loadmap = lm; 1.201 + pr_loadmap = lm; 1.202 +#endif /* HAVE_DLL */ 1.203 +#endif /* XP_UNIX */ 1.204 + 1.205 + if (lm) { 1.206 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, 1.207 + ("Loaded library %s (init)", lm->name)); 1.208 + } 1.209 + 1.210 + PR_ExitMonitor(pr_linker_lock); 1.211 +} 1.212 + 1.213 +/* 1.214 + * _PR_ShutdownLinker does not unload the dlls loaded by the application 1.215 + * via calls to PR_LoadLibrary. Any dlls that still remain on the 1.216 + * pr_loadmap list when NSPR shuts down are application programming errors. 1.217 + * The only exception is pr_exe_loadmap, which was added to the list by 1.218 + * NSPR and hence should be cleaned up by NSPR. 1.219 + */ 1.220 +void _PR_ShutdownLinker(void) 1.221 +{ 1.222 + /* FIXME: pr_exe_loadmap should be destroyed. */ 1.223 + 1.224 + PR_DestroyMonitor(pr_linker_lock); 1.225 + pr_linker_lock = NULL; 1.226 + 1.227 + if (_pr_currentLibPath) { 1.228 + free(_pr_currentLibPath); 1.229 + _pr_currentLibPath = NULL; 1.230 + } 1.231 +} 1.232 + 1.233 +/******************************************************************************/ 1.234 + 1.235 +PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path) 1.236 +{ 1.237 + PRStatus rv = PR_SUCCESS; 1.238 + 1.239 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.240 + PR_EnterMonitor(pr_linker_lock); 1.241 + if (_pr_currentLibPath) { 1.242 + free(_pr_currentLibPath); 1.243 + } 1.244 + if (path) { 1.245 + _pr_currentLibPath = strdup(path); 1.246 + if (!_pr_currentLibPath) { 1.247 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.248 + rv = PR_FAILURE; 1.249 + } 1.250 + } else { 1.251 + _pr_currentLibPath = 0; 1.252 + } 1.253 + PR_ExitMonitor(pr_linker_lock); 1.254 + return rv; 1.255 +} 1.256 + 1.257 +/* 1.258 +** Return the library path for finding shared libraries. 1.259 +*/ 1.260 +PR_IMPLEMENT(char *) 1.261 +PR_GetLibraryPath(void) 1.262 +{ 1.263 + char *ev; 1.264 + char *copy = NULL; /* a copy of _pr_currentLibPath */ 1.265 + 1.266 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.267 + PR_EnterMonitor(pr_linker_lock); 1.268 + if (_pr_currentLibPath != NULL) { 1.269 + goto exit; 1.270 + } 1.271 + 1.272 + /* initialize pr_currentLibPath */ 1.273 + 1.274 +#ifdef XP_PC 1.275 + ev = getenv("LD_LIBRARY_PATH"); 1.276 + if (!ev) { 1.277 + ev = ".;\\lib"; 1.278 + } 1.279 + ev = strdup(ev); 1.280 +#endif 1.281 + 1.282 +#if defined(XP_UNIX) || defined(XP_BEOS) 1.283 +#if defined(USE_DLFCN) || defined(USE_MACH_DYLD) || defined(XP_BEOS) 1.284 + { 1.285 + char *p=NULL; 1.286 + int len; 1.287 + 1.288 +#ifdef XP_BEOS 1.289 + ev = getenv("LIBRARY_PATH"); 1.290 + if (!ev) { 1.291 + ev = "%A/lib:/boot/home/config/lib:/boot/beos/system/lib"; 1.292 + } 1.293 +#else 1.294 + ev = getenv("LD_LIBRARY_PATH"); 1.295 + if (!ev) { 1.296 + ev = "/usr/lib:/lib"; 1.297 + } 1.298 +#endif 1.299 + len = strlen(ev) + 1; /* +1 for the null */ 1.300 + 1.301 + p = (char*) malloc(len); 1.302 + if (p) { 1.303 + strcpy(p, ev); 1.304 + } /* if (p) */ 1.305 + ev = p; 1.306 + PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev)); 1.307 + 1.308 + } 1.309 +#else 1.310 + /* AFAIK there isn't a library path with the HP SHL interface --Rob */ 1.311 + ev = strdup(""); 1.312 +#endif 1.313 +#endif 1.314 + 1.315 + /* 1.316 + * If ev is NULL, we have run out of memory 1.317 + */ 1.318 + _pr_currentLibPath = ev; 1.319 + 1.320 + exit: 1.321 + if (_pr_currentLibPath) { 1.322 + copy = strdup(_pr_currentLibPath); 1.323 + } 1.324 + PR_ExitMonitor(pr_linker_lock); 1.325 + if (!copy) { 1.326 + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 1.327 + } 1.328 + return copy; 1.329 +} 1.330 + 1.331 +/* 1.332 +** Build library name from path, lib and extensions 1.333 +*/ 1.334 +PR_IMPLEMENT(char*) 1.335 +PR_GetLibraryName(const char *path, const char *lib) 1.336 +{ 1.337 + char *fullname; 1.338 + 1.339 +#ifdef XP_PC 1.340 + if (strstr(lib, PR_DLL_SUFFIX) == NULL) 1.341 + { 1.342 + if (path) { 1.343 + fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX); 1.344 + } else { 1.345 + fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX); 1.346 + } 1.347 + } else { 1.348 + if (path) { 1.349 + fullname = PR_smprintf("%s\\%s", path, lib); 1.350 + } else { 1.351 + fullname = PR_smprintf("%s", lib); 1.352 + } 1.353 + } 1.354 +#endif /* XP_PC */ 1.355 +#if defined(XP_UNIX) || defined(XP_BEOS) 1.356 + if (strstr(lib, PR_DLL_SUFFIX) == NULL) 1.357 + { 1.358 + if (path) { 1.359 + fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX); 1.360 + } else { 1.361 + fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX); 1.362 + } 1.363 + } else { 1.364 + if (path) { 1.365 + fullname = PR_smprintf("%s/%s", path, lib); 1.366 + } else { 1.367 + fullname = PR_smprintf("%s", lib); 1.368 + } 1.369 + } 1.370 +#endif /* XP_UNIX || XP_BEOS */ 1.371 + return fullname; 1.372 +} 1.373 + 1.374 +/* 1.375 +** Free the memory allocated, for the caller, by PR_GetLibraryName 1.376 +*/ 1.377 +PR_IMPLEMENT(void) 1.378 +PR_FreeLibraryName(char *mem) 1.379 +{ 1.380 + PR_smprintf_free(mem); 1.381 +} 1.382 + 1.383 +static PRLibrary* 1.384 +pr_UnlockedFindLibrary(const char *name) 1.385 +{ 1.386 + PRLibrary* lm = pr_loadmap; 1.387 + const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR); 1.388 + np = np ? np + 1 : name; 1.389 + while (lm) { 1.390 + const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR); 1.391 + cp = cp ? cp + 1 : lm->name; 1.392 +#ifdef WIN32 1.393 + /* Windows DLL names are case insensitive... */ 1.394 + if (strcmpi(np, cp) == 0) 1.395 +#elif defined(XP_OS2) 1.396 + if (stricmp(np, cp) == 0) 1.397 +#else 1.398 + if (strcmp(np, cp) == 0) 1.399 +#endif 1.400 + { 1.401 + /* found */ 1.402 + lm->refCount++; 1.403 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, 1.404 + ("%s incr => %d (find lib)", 1.405 + lm->name, lm->refCount)); 1.406 + return lm; 1.407 + } 1.408 + lm = lm->next; 1.409 + } 1.410 + return NULL; 1.411 +} 1.412 + 1.413 +PR_IMPLEMENT(PRLibrary*) 1.414 +PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags) 1.415 +{ 1.416 + if (flags == 0) { 1.417 + flags = _PR_DEFAULT_LD_FLAGS; 1.418 + } 1.419 + switch (libSpec.type) { 1.420 + case PR_LibSpec_Pathname: 1.421 + return pr_LoadLibraryByPathname(libSpec.value.pathname, flags); 1.422 +#ifdef WIN32 1.423 + case PR_LibSpec_PathnameU: 1.424 + /* 1.425 + * cast to |char *| and set PR_LD_PATHW flag so that 1.426 + * it can be cast back to PRUnichar* in the callee. 1.427 + */ 1.428 + return pr_LoadLibraryByPathname((const char*) 1.429 + libSpec.value.pathname_u, 1.430 + flags | PR_LD_PATHW); 1.431 +#endif 1.432 + default: 1.433 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.434 + return NULL; 1.435 + } 1.436 +} 1.437 + 1.438 +PR_IMPLEMENT(PRLibrary*) 1.439 +PR_LoadLibrary(const char *name) 1.440 +{ 1.441 + PRLibSpec libSpec; 1.442 + 1.443 + libSpec.type = PR_LibSpec_Pathname; 1.444 + libSpec.value.pathname = name; 1.445 + return PR_LoadLibraryWithFlags(libSpec, 0); 1.446 +} 1.447 + 1.448 +#if defined(USE_MACH_DYLD) 1.449 +static NSModule 1.450 +pr_LoadMachDyldModule(const char *name) 1.451 +{ 1.452 + NSObjectFileImage ofi; 1.453 + NSModule h = NULL; 1.454 + if (NSCreateObjectFileImageFromFile(name, &ofi) 1.455 + == NSObjectFileImageSuccess) { 1.456 + h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE 1.457 + | NSLINKMODULE_OPTION_RETURN_ON_ERROR); 1.458 + if (h == NULL) { 1.459 + NSLinkEditErrors linkEditError; 1.460 + int errorNum; 1.461 + const char *fileName; 1.462 + const char *errorString; 1.463 + NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString); 1.464 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, 1.465 + ("LoadMachDyldModule error %d:%d for file %s:\n%s", 1.466 + linkEditError, errorNum, fileName, errorString)); 1.467 + } 1.468 + if (NSDestroyObjectFileImage(ofi) == FALSE) { 1.469 + if (h) { 1.470 + (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE); 1.471 + h = NULL; 1.472 + } 1.473 + } 1.474 + } 1.475 + return h; 1.476 +} 1.477 +#endif 1.478 + 1.479 +#if defined(XP_MACOSX) && defined(USE_MACH_DYLD) 1.480 + 1.481 +/* 1.482 +** macLibraryLoadProc is a function definition for a Mac shared library 1.483 +** loading method. The "name" param is the same full or partial pathname 1.484 +** that was passed to pr_LoadLibraryByPathName. The function must fill 1.485 +** in the fields of "lm" which apply to its library type. Returns 1.486 +** PR_SUCCESS if successful. 1.487 +*/ 1.488 + 1.489 +typedef PRStatus (*macLibraryLoadProc)(const char *name, PRLibrary *lm); 1.490 + 1.491 +#ifdef __ppc__ 1.492 + 1.493 +/* 1.494 +** CFM and its TVectors only exist on PowerPC. Other OS X architectures 1.495 +** only use Mach-O as a native binary format. 1.496 +*/ 1.497 + 1.498 +static void* TV2FP(CFMutableDictionaryRef dict, const char* name, void *tvp) 1.499 +{ 1.500 + static uint32 glue[6] = { 0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420 }; 1.501 + uint32* newGlue = NULL; 1.502 + 1.503 + if (tvp != NULL) { 1.504 + CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII); 1.505 + if (nameRef) { 1.506 + CFMutableDataRef glueData = (CFMutableDataRef) CFDictionaryGetValue(dict, nameRef); 1.507 + if (glueData == NULL) { 1.508 + glueData = CFDataCreateMutable(NULL, sizeof(glue)); 1.509 + if (glueData != NULL) { 1.510 + newGlue = (uint32*) CFDataGetMutableBytePtr(glueData); 1.511 + memcpy(newGlue, glue, sizeof(glue)); 1.512 + newGlue[0] |= ((UInt32)tvp >> 16); 1.513 + newGlue[1] |= ((UInt32)tvp & 0xFFFF); 1.514 + MakeDataExecutable(newGlue, sizeof(glue)); 1.515 + CFDictionaryAddValue(dict, nameRef, glueData); 1.516 + CFRelease(glueData); 1.517 + 1.518 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: created wrapper for CFM function %s().", name)); 1.519 + } 1.520 + } else { 1.521 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: found wrapper for CFM function %s().", name)); 1.522 + 1.523 + newGlue = (uint32*) CFDataGetMutableBytePtr(glueData); 1.524 + } 1.525 + CFRelease(nameRef); 1.526 + } 1.527 + } 1.528 + 1.529 + return newGlue; 1.530 +} 1.531 + 1.532 +static PRStatus 1.533 +pr_LoadViaCFM(const char *name, PRLibrary *lm) 1.534 +{ 1.535 + OSErr err; 1.536 + Str255 errName; 1.537 + FSRef ref; 1.538 + FSSpec fileSpec; 1.539 + Boolean tempUnusedBool; 1.540 + 1.541 + /* 1.542 + * Make an FSSpec from the path name and call GetDiskFragment. 1.543 + */ 1.544 + 1.545 + /* Use direct conversion of POSIX path to FSRef to FSSpec. */ 1.546 + err = FSPathMakeRef((const UInt8*)name, &ref, NULL); 1.547 + if (err != noErr) 1.548 + return PR_FAILURE; 1.549 + err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, 1.550 + &fileSpec, NULL); 1.551 + if (err != noErr) 1.552 + return PR_FAILURE; 1.553 + 1.554 + /* Resolve an alias if this was one */ 1.555 + err = ResolveAliasFile(&fileSpec, true, &tempUnusedBool, 1.556 + &tempUnusedBool); 1.557 + if (err != noErr) 1.558 + return PR_FAILURE; 1.559 + 1.560 + /* Finally, try to load the library */ 1.561 + err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name, 1.562 + kLoadCFrag, &lm->connection, &lm->main, errName); 1.563 + 1.564 + if (err == noErr && lm->connection) { 1.565 + /* 1.566 + * if we're a mach-o binary, need to wrap all CFM function 1.567 + * pointers. need a hash-table of already seen function 1.568 + * pointers, etc. 1.569 + */ 1.570 + lm->wrappers = CFDictionaryCreateMutable(NULL, 16, 1.571 + &kCFTypeDictionaryKeyCallBacks, 1.572 + &kCFTypeDictionaryValueCallBacks); 1.573 + if (lm->wrappers) { 1.574 + lm->main = TV2FP(lm->wrappers, "main", lm->main); 1.575 + } else 1.576 + err = memFullErr; 1.577 + } 1.578 + return (err == noErr) ? PR_SUCCESS : PR_FAILURE; 1.579 +} 1.580 +#endif /* __ppc__ */ 1.581 + 1.582 +/* 1.583 +** Creates a CFBundleRef if the pathname refers to a Mac OS X bundle 1.584 +** directory. The caller is responsible for calling CFRelease() to 1.585 +** deallocate. 1.586 +*/ 1.587 + 1.588 +static PRStatus 1.589 +pr_LoadCFBundle(const char *name, PRLibrary *lm) 1.590 +{ 1.591 + CFURLRef bundleURL; 1.592 + CFBundleRef bundle = NULL; 1.593 + char pathBuf[PATH_MAX]; 1.594 + const char *resolvedPath; 1.595 + CFStringRef pathRef; 1.596 + 1.597 + /* Takes care of relative paths and symlinks */ 1.598 + resolvedPath = realpath(name, pathBuf); 1.599 + if (!resolvedPath) 1.600 + return PR_FAILURE; 1.601 + 1.602 + pathRef = CFStringCreateWithCString(NULL, pathBuf, kCFStringEncodingUTF8); 1.603 + if (pathRef) { 1.604 + bundleURL = CFURLCreateWithFileSystemPath(NULL, pathRef, 1.605 + kCFURLPOSIXPathStyle, true); 1.606 + if (bundleURL) { 1.607 + bundle = CFBundleCreate(NULL, bundleURL); 1.608 + CFRelease(bundleURL); 1.609 + } 1.610 + CFRelease(pathRef); 1.611 + } 1.612 + 1.613 + lm->bundle = bundle; 1.614 + return (bundle != NULL) ? PR_SUCCESS : PR_FAILURE; 1.615 +} 1.616 + 1.617 +static PRStatus 1.618 +pr_LoadViaDyld(const char *name, PRLibrary *lm) 1.619 +{ 1.620 + lm->dlh = pr_LoadMachDyldModule(name); 1.621 + if (lm->dlh == NULL) { 1.622 + lm->image = NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR 1.623 + | NSADDIMAGE_OPTION_WITH_SEARCHING); 1.624 + if (lm->image == NULL) { 1.625 + NSLinkEditErrors linkEditError; 1.626 + int errorNum; 1.627 + const char *fileName; 1.628 + const char *errorString; 1.629 + NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString); 1.630 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, 1.631 + ("LoadMachDyldModule error %d:%d for file %s:\n%s", 1.632 + linkEditError, errorNum, fileName, errorString)); 1.633 + } 1.634 + } 1.635 + return (lm->dlh != NULL || lm->image != NULL) ? PR_SUCCESS : PR_FAILURE; 1.636 +} 1.637 + 1.638 +#endif /* XP_MACOSX && USE_MACH_DYLD */ 1.639 + 1.640 +/* 1.641 +** Dynamically load a library. Only load libraries once, so scan the load 1.642 +** map first. 1.643 +*/ 1.644 +static PRLibrary* 1.645 +pr_LoadLibraryByPathname(const char *name, PRIntn flags) 1.646 +{ 1.647 + PRLibrary *lm; 1.648 + PRLibrary* result = NULL; 1.649 + PRInt32 oserr; 1.650 +#ifdef WIN32 1.651 + char utf8name_stack[MAX_PATH]; 1.652 + char *utf8name_malloc = NULL; 1.653 + char *utf8name = utf8name_stack; 1.654 + PRUnichar wname_stack[MAX_PATH]; 1.655 + PRUnichar *wname_malloc = NULL; 1.656 + PRUnichar *wname = wname_stack; 1.657 + int len; 1.658 +#endif 1.659 + 1.660 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.661 + 1.662 + /* See if library is already loaded */ 1.663 + PR_EnterMonitor(pr_linker_lock); 1.664 + 1.665 +#ifdef WIN32 1.666 + if (flags & PR_LD_PATHW) { 1.667 + /* cast back what's cast to |char *| for the argument passing. */ 1.668 + wname = (LPWSTR) name; 1.669 + } else { 1.670 + int wlen = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0); 1.671 + if (wlen > MAX_PATH) 1.672 + wname = wname_malloc = PR_Malloc(wlen * sizeof(PRUnichar)); 1.673 + if (wname == NULL || 1.674 + !MultiByteToWideChar(CP_ACP, 0, name, -1, wname, wlen)) { 1.675 + oserr = _MD_ERRNO(); 1.676 + goto unlock; 1.677 + } 1.678 + } 1.679 + len = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL); 1.680 + if (len > MAX_PATH) 1.681 + utf8name = utf8name_malloc = PR_Malloc(len); 1.682 + if (utf8name == NULL || 1.683 + !WideCharToMultiByte(CP_UTF8, 0, wname, -1, 1.684 + utf8name, len, NULL, NULL)) { 1.685 + oserr = _MD_ERRNO(); 1.686 + goto unlock; 1.687 + } 1.688 + /* the list of loaded library names are always kept in UTF-8 1.689 + * on Win32 platforms */ 1.690 + result = pr_UnlockedFindLibrary(utf8name); 1.691 +#else 1.692 + result = pr_UnlockedFindLibrary(name); 1.693 +#endif 1.694 + 1.695 + if (result != NULL) goto unlock; 1.696 + 1.697 + lm = PR_NEWZAP(PRLibrary); 1.698 + if (lm == NULL) { 1.699 + oserr = _MD_ERRNO(); 1.700 + goto unlock; 1.701 + } 1.702 + lm->staticTable = NULL; 1.703 + 1.704 +#ifdef XP_OS2 /* Why isn't all this stuff in MD code?! */ 1.705 + { 1.706 + HMODULE h; 1.707 + UCHAR pszError[_MAX_PATH]; 1.708 + ULONG ulRc = NO_ERROR; 1.709 + 1.710 + ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h); 1.711 + if (ulRc != NO_ERROR) { 1.712 + oserr = ulRc; 1.713 + PR_DELETE(lm); 1.714 + goto unlock; 1.715 + } 1.716 + lm->name = strdup(name); 1.717 + lm->dlh = h; 1.718 + lm->next = pr_loadmap; 1.719 + pr_loadmap = lm; 1.720 + } 1.721 +#endif /* XP_OS2 */ 1.722 + 1.723 +#ifdef WIN32 1.724 + { 1.725 + HINSTANCE h; 1.726 + 1.727 + h = LoadLibraryExW(wname, NULL, 1.728 + (flags & PR_LD_ALT_SEARCH_PATH) ? 1.729 + LOAD_WITH_ALTERED_SEARCH_PATH : 0); 1.730 + if (h == NULL) { 1.731 + oserr = _MD_ERRNO(); 1.732 + PR_DELETE(lm); 1.733 + goto unlock; 1.734 + } 1.735 + lm->name = strdup(utf8name); 1.736 + lm->dlh = h; 1.737 + lm->next = pr_loadmap; 1.738 + pr_loadmap = lm; 1.739 + } 1.740 +#endif /* WIN32 */ 1.741 + 1.742 +#if defined(XP_MACOSX) && defined(USE_MACH_DYLD) 1.743 + { 1.744 + int i; 1.745 + PRStatus status; 1.746 + 1.747 + static const macLibraryLoadProc loadProcs[] = { 1.748 +#ifdef __ppc__ 1.749 + pr_LoadViaDyld, pr_LoadCFBundle, pr_LoadViaCFM 1.750 +#else /* __ppc__ */ 1.751 + pr_LoadViaDyld, pr_LoadCFBundle 1.752 +#endif /* __ppc__ */ 1.753 + }; 1.754 + 1.755 + for (i = 0; i < sizeof(loadProcs) / sizeof(loadProcs[0]); i++) { 1.756 + if ((status = loadProcs[i](name, lm)) == PR_SUCCESS) 1.757 + break; 1.758 + } 1.759 + if (status != PR_SUCCESS) { 1.760 + oserr = cfragNoLibraryErr; 1.761 + PR_DELETE(lm); 1.762 + goto unlock; 1.763 + } 1.764 + lm->name = strdup(name); 1.765 + lm->next = pr_loadmap; 1.766 + pr_loadmap = lm; 1.767 + } 1.768 +#endif 1.769 + 1.770 +#if defined(XP_UNIX) && !(defined(XP_MACOSX) && defined(USE_MACH_DYLD)) 1.771 +#ifdef HAVE_DLL 1.772 + { 1.773 +#if defined(USE_DLFCN) 1.774 +#ifdef NTO 1.775 + /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */ 1.776 + int dl_flags = RTLD_GROUP; 1.777 +#elif defined(AIX) 1.778 + /* AIX needs RTLD_MEMBER to load an archive member. (bug 228899) */ 1.779 + int dl_flags = RTLD_MEMBER; 1.780 +#else 1.781 + int dl_flags = 0; 1.782 +#endif 1.783 + void *h = NULL; 1.784 + 1.785 + if (flags & PR_LD_LAZY) { 1.786 + dl_flags |= RTLD_LAZY; 1.787 + } 1.788 + if (flags & PR_LD_NOW) { 1.789 + dl_flags |= RTLD_NOW; 1.790 + } 1.791 + if (flags & PR_LD_GLOBAL) { 1.792 + dl_flags |= RTLD_GLOBAL; 1.793 + } 1.794 + if (flags & PR_LD_LOCAL) { 1.795 + dl_flags |= RTLD_LOCAL; 1.796 + } 1.797 +#if defined(DARWIN) 1.798 + /* ensure the file exists if it contains a slash character i.e. path */ 1.799 + /* DARWIN's dlopen ignores the provided path and checks for the */ 1.800 + /* plain filename in DYLD_LIBRARY_PATH */ 1.801 + if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL || 1.802 + PR_Access(name, PR_ACCESS_EXISTS) == PR_SUCCESS) { 1.803 + h = dlopen(name, dl_flags); 1.804 + } 1.805 +#else 1.806 + h = dlopen(name, dl_flags); 1.807 +#endif 1.808 +#elif defined(USE_HPSHL) 1.809 + int shl_flags = 0; 1.810 + shl_t h; 1.811 + 1.812 + /* 1.813 + * Use the DYNAMIC_PATH flag only if 'name' is a plain file 1.814 + * name (containing no directory) to match the behavior of 1.815 + * dlopen(). 1.816 + */ 1.817 + if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) { 1.818 + shl_flags |= DYNAMIC_PATH; 1.819 + } 1.820 + if (flags & PR_LD_LAZY) { 1.821 + shl_flags |= BIND_DEFERRED; 1.822 + } 1.823 + if (flags & PR_LD_NOW) { 1.824 + shl_flags |= BIND_IMMEDIATE; 1.825 + } 1.826 + /* No equivalent of PR_LD_GLOBAL and PR_LD_LOCAL. */ 1.827 + h = shl_load(name, shl_flags, 0L); 1.828 +#elif defined(USE_MACH_DYLD) 1.829 + NSModule h = pr_LoadMachDyldModule(name); 1.830 +#else 1.831 +#error Configuration error 1.832 +#endif 1.833 + if (!h) { 1.834 + oserr = _MD_ERRNO(); 1.835 + PR_DELETE(lm); 1.836 + goto unlock; 1.837 + } 1.838 + lm->name = strdup(name); 1.839 + lm->dlh = h; 1.840 + lm->next = pr_loadmap; 1.841 + pr_loadmap = lm; 1.842 + } 1.843 +#endif /* HAVE_DLL */ 1.844 +#endif /* XP_UNIX && !(XP_MACOSX && USE_MACH_DYLD) */ 1.845 + 1.846 + lm->refCount = 1; 1.847 + 1.848 +#ifdef XP_BEOS 1.849 + { 1.850 + image_info info; 1.851 + int32 cookie = 0; 1.852 + image_id imageid = B_ERROR; 1.853 + image_id stubid = B_ERROR; 1.854 + PRLibrary *p; 1.855 + 1.856 + for (p = pr_loadmap; p != NULL; p = p->next) { 1.857 + /* hopefully, our caller will always use the same string 1.858 + to refer to the same library */ 1.859 + if (strcmp(name, p->name) == 0) { 1.860 + /* we've already loaded this library */ 1.861 + imageid = info.id; 1.862 + lm->refCount++; 1.863 + break; 1.864 + } 1.865 + } 1.866 + 1.867 + if(imageid == B_ERROR) { 1.868 + /* it appears the library isn't yet loaded - load it now */ 1.869 + char stubName [B_PATH_NAME_LENGTH + 1]; 1.870 + 1.871 + /* the following is a work-around to a "bug" in the beos - 1.872 + the beos system loader allows only 32M (system-wide) 1.873 + to be used by code loaded as "add-ons" (code loaded 1.874 + through the 'load_add_on()' system call, which includes 1.875 + mozilla components), but allows 256M to be used by 1.876 + shared libraries. 1.877 + 1.878 + unfortunately, mozilla is too large to fit into the 1.879 + "add-on" space, so we must trick the loader into 1.880 + loading some of the components as shared libraries. this 1.881 + is accomplished by creating a "stub" add-on (an empty 1.882 + shared object), and linking it with the component 1.883 + (the actual .so file generated by the build process, 1.884 + without any modifications). when this stub is loaded 1.885 + by load_add_on(), the loader will automatically load the 1.886 + component into the shared library space. 1.887 + */ 1.888 + 1.889 + strcpy(stubName, name); 1.890 + strcat(stubName, ".stub"); 1.891 + 1.892 + /* first, attempt to load the stub (thereby loading the 1.893 + component as a shared library */ 1.894 + if ((stubid = load_add_on(stubName)) > B_ERROR) { 1.895 + /* the stub was loaded successfully. */ 1.896 + imageid = B_FILE_NOT_FOUND; 1.897 + 1.898 + cookie = 0; 1.899 + while (get_next_image_info(0, &cookie, &info) == B_OK) { 1.900 + const char *endOfSystemName = strrchr(info.name, '/'); 1.901 + const char *endOfPassedName = strrchr(name, '/'); 1.902 + if( 0 == endOfSystemName ) 1.903 + endOfSystemName = info.name; 1.904 + else 1.905 + endOfSystemName++; 1.906 + if( 0 == endOfPassedName ) 1.907 + endOfPassedName = name; 1.908 + else 1.909 + endOfPassedName++; 1.910 + if (strcmp(endOfSystemName, endOfPassedName) == 0) { 1.911 + /* this is the actual component - remember it */ 1.912 + imageid = info.id; 1.913 + break; 1.914 + } 1.915 + } 1.916 + 1.917 + } else { 1.918 + /* we failed to load the "stub" - try to load the 1.919 + component directly as an add-on */ 1.920 + stubid = B_ERROR; 1.921 + imageid = load_add_on(name); 1.922 + } 1.923 + } 1.924 + 1.925 + if (imageid <= B_ERROR) { 1.926 + oserr = imageid; 1.927 + PR_DELETE( lm ); 1.928 + goto unlock; 1.929 + } 1.930 + lm->name = strdup(name); 1.931 + lm->dlh = (void*)imageid; 1.932 + lm->stub_dlh = (void*)stubid; 1.933 + lm->next = pr_loadmap; 1.934 + pr_loadmap = lm; 1.935 + } 1.936 +#endif 1.937 + 1.938 + result = lm; /* success */ 1.939 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name)); 1.940 + 1.941 + unlock: 1.942 + if (result == NULL) { 1.943 + PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr); 1.944 + DLLErrorInternal(oserr); /* sets error text */ 1.945 + } 1.946 +#ifdef WIN32 1.947 + if (utf8name_malloc) 1.948 + PR_Free(utf8name_malloc); 1.949 + if (wname_malloc) 1.950 + PR_Free(wname_malloc); 1.951 +#endif 1.952 + PR_ExitMonitor(pr_linker_lock); 1.953 + return result; 1.954 +} 1.955 + 1.956 +/* 1.957 +** Unload a shared library which was loaded via PR_LoadLibrary 1.958 +*/ 1.959 +PR_IMPLEMENT(PRStatus) 1.960 +PR_UnloadLibrary(PRLibrary *lib) 1.961 +{ 1.962 + int result = 0; 1.963 + PRStatus status = PR_SUCCESS; 1.964 + 1.965 + if (lib == 0) { 1.966 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.967 + return PR_FAILURE; 1.968 + } 1.969 + 1.970 + PR_EnterMonitor(pr_linker_lock); 1.971 + 1.972 + if (lib->refCount <= 0) { 1.973 + PR_ExitMonitor(pr_linker_lock); 1.974 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.975 + return PR_FAILURE; 1.976 + } 1.977 + 1.978 + if (--lib->refCount > 0) { 1.979 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, 1.980 + ("%s decr => %d", 1.981 + lib->name, lib->refCount)); 1.982 + goto done; 1.983 + } 1.984 + 1.985 +#ifdef XP_BEOS 1.986 + if(((image_id)lib->stub_dlh) == B_ERROR) 1.987 + unload_add_on( (image_id) lib->dlh ); 1.988 + else 1.989 + unload_add_on( (image_id) lib->stub_dlh); 1.990 +#endif 1.991 + 1.992 +#ifdef XP_UNIX 1.993 +#ifdef HAVE_DLL 1.994 +#ifdef USE_DLFCN 1.995 + result = dlclose(lib->dlh); 1.996 +#elif defined(USE_HPSHL) 1.997 + result = shl_unload(lib->dlh); 1.998 +#elif defined(USE_MACH_DYLD) 1.999 + if (lib->dlh) 1.1000 + result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1; 1.1001 +#else 1.1002 +#error Configuration error 1.1003 +#endif 1.1004 +#endif /* HAVE_DLL */ 1.1005 +#endif /* XP_UNIX */ 1.1006 +#ifdef XP_PC 1.1007 + if (lib->dlh) { 1.1008 + FreeLibrary((HINSTANCE)(lib->dlh)); 1.1009 + lib->dlh = (HINSTANCE)NULL; 1.1010 + } 1.1011 +#endif /* XP_PC */ 1.1012 + 1.1013 +#if defined(XP_MACOSX) && defined(USE_MACH_DYLD) 1.1014 + /* Close the connection */ 1.1015 + if (lib->connection) 1.1016 + CloseConnection(&(lib->connection)); 1.1017 + if (lib->bundle) 1.1018 + CFRelease(lib->bundle); 1.1019 + if (lib->wrappers) 1.1020 + CFRelease(lib->wrappers); 1.1021 + /* No way to unload an image (lib->image) */ 1.1022 +#endif 1.1023 + 1.1024 + /* unlink from library search list */ 1.1025 + if (pr_loadmap == lib) 1.1026 + pr_loadmap = pr_loadmap->next; 1.1027 + else if (pr_loadmap != NULL) { 1.1028 + PRLibrary* prev = pr_loadmap; 1.1029 + PRLibrary* next = pr_loadmap->next; 1.1030 + while (next != NULL) { 1.1031 + if (next == lib) { 1.1032 + prev->next = next->next; 1.1033 + goto freeLib; 1.1034 + } 1.1035 + prev = next; 1.1036 + next = next->next; 1.1037 + } 1.1038 + /* 1.1039 + * fail (the library is not on the _pr_loadmap list), 1.1040 + * but don't wipe out an error from dlclose/shl_unload. 1.1041 + */ 1.1042 + PR_ASSERT(!"_pr_loadmap and lib->refCount inconsistent"); 1.1043 + if (result == 0) { 1.1044 + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); 1.1045 + status = PR_FAILURE; 1.1046 + } 1.1047 + } 1.1048 + /* 1.1049 + * We free the PRLibrary structure whether dlclose/shl_unload 1.1050 + * succeeds or not. 1.1051 + */ 1.1052 + 1.1053 + freeLib: 1.1054 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name)); 1.1055 + free(lib->name); 1.1056 + lib->name = NULL; 1.1057 + PR_DELETE(lib); 1.1058 + if (result != 0) { 1.1059 + PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO()); 1.1060 + DLLErrorInternal(_MD_ERRNO()); 1.1061 + status = PR_FAILURE; 1.1062 + } 1.1063 + 1.1064 +done: 1.1065 + PR_ExitMonitor(pr_linker_lock); 1.1066 + return status; 1.1067 +} 1.1068 + 1.1069 +static void* 1.1070 +pr_FindSymbolInLib(PRLibrary *lm, const char *name) 1.1071 +{ 1.1072 + void *f = NULL; 1.1073 +#ifdef XP_OS2 1.1074 + int rc; 1.1075 +#endif 1.1076 + 1.1077 + if (lm->staticTable != NULL) { 1.1078 + const PRStaticLinkTable* tp; 1.1079 + for (tp = lm->staticTable; tp->name; tp++) { 1.1080 + if (strcmp(name, tp->name) == 0) { 1.1081 + return (void*) tp->fp; 1.1082 + } 1.1083 + } 1.1084 + /* 1.1085 + ** If the symbol was not found in the static table then check if 1.1086 + ** the symbol was exported in the DLL... Win16 only!! 1.1087 + */ 1.1088 +#if !defined(WIN16) && !defined(XP_BEOS) 1.1089 + PR_SetError(PR_FIND_SYMBOL_ERROR, 0); 1.1090 + return (void*)NULL; 1.1091 +#endif 1.1092 + } 1.1093 + 1.1094 +#ifdef XP_OS2 1.1095 + rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); 1.1096 +#if defined(NEED_LEADING_UNDERSCORE) 1.1097 + /* 1.1098 + * Older plugins (not built using GCC) will have symbols that are not 1.1099 + * underscore prefixed. We check for that here. 1.1100 + */ 1.1101 + if (rc != NO_ERROR) { 1.1102 + name++; 1.1103 + DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); 1.1104 + } 1.1105 +#endif 1.1106 +#endif /* XP_OS2 */ 1.1107 + 1.1108 +#ifdef WIN32 1.1109 + f = GetProcAddress(lm->dlh, name); 1.1110 +#endif /* WIN32 */ 1.1111 + 1.1112 +#if defined(XP_MACOSX) && defined(USE_MACH_DYLD) 1.1113 +/* add this offset to skip the leading underscore in name */ 1.1114 +#define SYM_OFFSET 1 1.1115 + if (lm->bundle) { 1.1116 + CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII); 1.1117 + if (nameRef) { 1.1118 + f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef); 1.1119 + CFRelease(nameRef); 1.1120 + } 1.1121 + } 1.1122 + if (lm->connection) { 1.1123 + Ptr symAddr; 1.1124 + CFragSymbolClass symClass; 1.1125 + Str255 pName; 1.1126 + 1.1127 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_OFFSET)); 1.1128 + 1.1129 + c2pstrcpy(pName, name + SYM_OFFSET); 1.1130 + 1.1131 + f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL; 1.1132 + 1.1133 +#ifdef __ppc__ 1.1134 + /* callers expect mach-o function pointers, so must wrap tvectors with glue. */ 1.1135 + if (f && symClass == kTVectorCFragSymbol) { 1.1136 + f = TV2FP(lm->wrappers, name + SYM_OFFSET, f); 1.1137 + } 1.1138 +#endif /* __ppc__ */ 1.1139 + 1.1140 + if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main; 1.1141 + } 1.1142 + if (lm->image) { 1.1143 + NSSymbol symbol; 1.1144 + symbol = NSLookupSymbolInImage(lm->image, name, 1.1145 + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 1.1146 + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 1.1147 + if (symbol != NULL) 1.1148 + f = NSAddressOfSymbol(symbol); 1.1149 + else 1.1150 + f = NULL; 1.1151 + } 1.1152 +#undef SYM_OFFSET 1.1153 +#endif /* XP_MACOSX && USE_MACH_DYLD */ 1.1154 + 1.1155 +#ifdef XP_BEOS 1.1156 + if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_TEXT, &f ) ) { 1.1157 + f = NULL; 1.1158 + } 1.1159 +#endif 1.1160 + 1.1161 +#ifdef XP_UNIX 1.1162 +#ifdef HAVE_DLL 1.1163 +#ifdef USE_DLFCN 1.1164 + f = dlsym(lm->dlh, name); 1.1165 +#elif defined(USE_HPSHL) 1.1166 + if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) { 1.1167 + f = NULL; 1.1168 + } 1.1169 +#elif defined(USE_MACH_DYLD) 1.1170 + if (lm->dlh) { 1.1171 + NSSymbol symbol; 1.1172 + symbol = NSLookupSymbolInModule(lm->dlh, name); 1.1173 + if (symbol != NULL) 1.1174 + f = NSAddressOfSymbol(symbol); 1.1175 + else 1.1176 + f = NULL; 1.1177 + } 1.1178 +#endif 1.1179 +#endif /* HAVE_DLL */ 1.1180 +#endif /* XP_UNIX */ 1.1181 + if (f == NULL) { 1.1182 + PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO()); 1.1183 + DLLErrorInternal(_MD_ERRNO()); 1.1184 + } 1.1185 + return f; 1.1186 +} 1.1187 + 1.1188 +/* 1.1189 +** Called by class loader to resolve missing native's 1.1190 +*/ 1.1191 +PR_IMPLEMENT(void*) 1.1192 +PR_FindSymbol(PRLibrary *lib, const char *raw_name) 1.1193 +{ 1.1194 + void *f = NULL; 1.1195 +#if defined(NEED_LEADING_UNDERSCORE) 1.1196 + char *name; 1.1197 +#else 1.1198 + const char *name; 1.1199 +#endif 1.1200 + /* 1.1201 + ** Mangle the raw symbol name in any way that is platform specific. 1.1202 + */ 1.1203 +#if defined(NEED_LEADING_UNDERSCORE) 1.1204 + /* Need a leading _ */ 1.1205 + name = PR_smprintf("_%s", raw_name); 1.1206 +#elif defined(AIX) 1.1207 + /* 1.1208 + ** AIX with the normal linker put's a "." in front of the symbol 1.1209 + ** name. When use "svcc" and "svld" then the "." disappears. Go 1.1210 + ** figure. 1.1211 + */ 1.1212 + name = raw_name; 1.1213 +#else 1.1214 + name = raw_name; 1.1215 +#endif 1.1216 + 1.1217 + PR_EnterMonitor(pr_linker_lock); 1.1218 + PR_ASSERT(lib != NULL); 1.1219 + f = pr_FindSymbolInLib(lib, name); 1.1220 + 1.1221 +#if defined(NEED_LEADING_UNDERSCORE) 1.1222 + PR_smprintf_free(name); 1.1223 +#endif 1.1224 + 1.1225 + PR_ExitMonitor(pr_linker_lock); 1.1226 + return f; 1.1227 +} 1.1228 + 1.1229 +/* 1.1230 +** Return the address of the function 'raw_name' in the library 'lib' 1.1231 +*/ 1.1232 +PR_IMPLEMENT(PRFuncPtr) 1.1233 +PR_FindFunctionSymbol(PRLibrary *lib, const char *raw_name) 1.1234 +{ 1.1235 + return ((PRFuncPtr) PR_FindSymbol(lib, raw_name)); 1.1236 +} 1.1237 + 1.1238 +PR_IMPLEMENT(void*) 1.1239 +PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib) 1.1240 +{ 1.1241 + void *f = NULL; 1.1242 +#if defined(NEED_LEADING_UNDERSCORE) 1.1243 + char *name; 1.1244 +#else 1.1245 + const char *name; 1.1246 +#endif 1.1247 + PRLibrary* lm; 1.1248 + 1.1249 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.1250 + /* 1.1251 + ** Mangle the raw symbol name in any way that is platform specific. 1.1252 + */ 1.1253 +#if defined(NEED_LEADING_UNDERSCORE) 1.1254 + /* Need a leading _ */ 1.1255 + name = PR_smprintf("_%s", raw_name); 1.1256 +#elif defined(AIX) 1.1257 + /* 1.1258 + ** AIX with the normal linker put's a "." in front of the symbol 1.1259 + ** name. When use "svcc" and "svld" then the "." disappears. Go 1.1260 + ** figure. 1.1261 + */ 1.1262 + name = raw_name; 1.1263 +#else 1.1264 + name = raw_name; 1.1265 +#endif 1.1266 + 1.1267 + PR_EnterMonitor(pr_linker_lock); 1.1268 + 1.1269 + /* search all libraries */ 1.1270 + for (lm = pr_loadmap; lm != NULL; lm = lm->next) { 1.1271 + f = pr_FindSymbolInLib(lm, name); 1.1272 + if (f != NULL) { 1.1273 + *lib = lm; 1.1274 + lm->refCount++; 1.1275 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, 1.1276 + ("%s incr => %d (for %s)", 1.1277 + lm->name, lm->refCount, name)); 1.1278 + break; 1.1279 + } 1.1280 + } 1.1281 +#if defined(NEED_LEADING_UNDERSCORE) 1.1282 + PR_smprintf_free(name); 1.1283 +#endif 1.1284 + 1.1285 + PR_ExitMonitor(pr_linker_lock); 1.1286 + return f; 1.1287 +} 1.1288 + 1.1289 +PR_IMPLEMENT(PRFuncPtr) 1.1290 +PR_FindFunctionSymbolAndLibrary(const char *raw_name, PRLibrary* *lib) 1.1291 +{ 1.1292 + return ((PRFuncPtr) PR_FindSymbolAndLibrary(raw_name, lib)); 1.1293 +} 1.1294 + 1.1295 +/* 1.1296 +** Add a static library to the list of loaded libraries. If LoadLibrary 1.1297 +** is called with the name then we will pretend it was already loaded 1.1298 +*/ 1.1299 +PR_IMPLEMENT(PRLibrary*) 1.1300 +PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt) 1.1301 +{ 1.1302 + PRLibrary *lm=NULL; 1.1303 + PRLibrary* result = NULL; 1.1304 + 1.1305 + if (!_pr_initialized) _PR_ImplicitInitialization(); 1.1306 + 1.1307 + /* See if library is already loaded */ 1.1308 + PR_EnterMonitor(pr_linker_lock); 1.1309 + 1.1310 + /* If the lbrary is already loaded, then add the static table information... */ 1.1311 + result = pr_UnlockedFindLibrary(name); 1.1312 + if (result != NULL) { 1.1313 + PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) ); 1.1314 + result->staticTable = slt; 1.1315 + goto unlock; 1.1316 + } 1.1317 + 1.1318 + /* Add library to list...Mark it static */ 1.1319 + lm = PR_NEWZAP(PRLibrary); 1.1320 + if (lm == NULL) goto unlock; 1.1321 + 1.1322 + lm->name = strdup(name); 1.1323 + lm->refCount = 1; 1.1324 + lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0; 1.1325 + lm->staticTable = slt; 1.1326 + lm->next = pr_loadmap; 1.1327 + pr_loadmap = lm; 1.1328 + 1.1329 + result = lm; /* success */ 1.1330 + PR_ASSERT(lm->refCount == 1); 1.1331 + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->name)); 1.1332 + unlock: 1.1333 + PR_ExitMonitor(pr_linker_lock); 1.1334 + return result; 1.1335 +} 1.1336 + 1.1337 +PR_IMPLEMENT(char *) 1.1338 +PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr) 1.1339 +{ 1.1340 +#if defined(USE_DLFCN) && defined(HAVE_DLADDR) 1.1341 + Dl_info dli; 1.1342 + char *result; 1.1343 + 1.1344 + if (dladdr((void *)addr, &dli) == 0) { 1.1345 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); 1.1346 + DLLErrorInternal(_MD_ERRNO()); 1.1347 + return NULL; 1.1348 + } 1.1349 + result = PR_Malloc(strlen(dli.dli_fname)+1); 1.1350 + if (result != NULL) { 1.1351 + strcpy(result, dli.dli_fname); 1.1352 + } 1.1353 + return result; 1.1354 +#elif defined(USE_MACH_DYLD) 1.1355 + char *result; 1.1356 + const char *image_name; 1.1357 + int i, count = _dyld_image_count(); 1.1358 + 1.1359 + for (i = 0; i < count; i++) { 1.1360 + image_name = _dyld_get_image_name(i); 1.1361 + if (strstr(image_name, name) != NULL) { 1.1362 + result = PR_Malloc(strlen(image_name)+1); 1.1363 + if (result != NULL) { 1.1364 + strcpy(result, image_name); 1.1365 + } 1.1366 + return result; 1.1367 + } 1.1368 + } 1.1369 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); 1.1370 + return NULL; 1.1371 +#elif defined(AIX) 1.1372 + char *result; 1.1373 +#define LD_INFO_INCREMENT 64 1.1374 + struct ld_info *info; 1.1375 + unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info); 1.1376 + struct ld_info *infop; 1.1377 + int loadflags = L_GETINFO | L_IGNOREUNLOAD; 1.1378 + 1.1379 + for (;;) { 1.1380 + info = PR_Malloc(info_length); 1.1381 + if (info == NULL) { 1.1382 + return NULL; 1.1383 + } 1.1384 + /* If buffer is too small, loadquery fails with ENOMEM. */ 1.1385 + if (loadquery(loadflags, info, info_length) != -1) { 1.1386 + break; 1.1387 + } 1.1388 + /* 1.1389 + * Calling loadquery when compiled for 64-bit with the 1.1390 + * L_IGNOREUNLOAD flag can cause an invalid argument error 1.1391 + * on AIX 5.1. Detect this error the first time that 1.1392 + * loadquery is called, and try calling it again without 1.1393 + * this flag set. 1.1394 + */ 1.1395 + if (errno == EINVAL && (loadflags & L_IGNOREUNLOAD)) { 1.1396 + loadflags &= ~L_IGNOREUNLOAD; 1.1397 + if (loadquery(loadflags, info, info_length) != -1) { 1.1398 + break; 1.1399 + } 1.1400 + } 1.1401 + PR_Free(info); 1.1402 + if (errno != ENOMEM) { 1.1403 + /* should not happen */ 1.1404 + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); 1.1405 + return NULL; 1.1406 + } 1.1407 + /* retry with a larger buffer */ 1.1408 + info_length += LD_INFO_INCREMENT * sizeof(struct ld_info); 1.1409 + } 1.1410 + 1.1411 + for (infop = info; 1.1412 + ; 1.1413 + infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) { 1.1414 + unsigned long start = (unsigned long)infop->ldinfo_dataorg; 1.1415 + unsigned long end = start + infop->ldinfo_datasize; 1.1416 + if (start <= (unsigned long)addr && end > (unsigned long)addr) { 1.1417 + result = PR_Malloc(strlen(infop->ldinfo_filename)+1); 1.1418 + if (result != NULL) { 1.1419 + strcpy(result, infop->ldinfo_filename); 1.1420 + } 1.1421 + break; 1.1422 + } 1.1423 + if (!infop->ldinfo_next) { 1.1424 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); 1.1425 + result = NULL; 1.1426 + break; 1.1427 + } 1.1428 + } 1.1429 + PR_Free(info); 1.1430 + return result; 1.1431 +#elif defined(OSF1) 1.1432 + /* Contributed by Steve Streeter of HP */ 1.1433 + ldr_process_t process, ldr_my_process(); 1.1434 + ldr_module_t mod_id; 1.1435 + ldr_module_info_t info; 1.1436 + ldr_region_t regno; 1.1437 + ldr_region_info_t reginfo; 1.1438 + size_t retsize; 1.1439 + int rv; 1.1440 + char *result; 1.1441 + 1.1442 + /* Get process for which dynamic modules will be listed */ 1.1443 + 1.1444 + process = ldr_my_process(); 1.1445 + 1.1446 + /* Attach to process */ 1.1447 + 1.1448 + rv = ldr_xattach(process); 1.1449 + if (rv) { 1.1450 + /* should not happen */ 1.1451 + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); 1.1452 + return NULL; 1.1453 + } 1.1454 + 1.1455 + /* Print information for list of modules */ 1.1456 + 1.1457 + mod_id = LDR_NULL_MODULE; 1.1458 + 1.1459 + for (;;) { 1.1460 + 1.1461 + /* Get information for the next module in the module list. */ 1.1462 + 1.1463 + ldr_next_module(process, &mod_id); 1.1464 + if (ldr_inq_module(process, mod_id, &info, sizeof(info), 1.1465 + &retsize) != 0) { 1.1466 + /* No more modules */ 1.1467 + break; 1.1468 + } 1.1469 + if (retsize < sizeof(info)) { 1.1470 + continue; 1.1471 + } 1.1472 + 1.1473 + /* 1.1474 + * Get information for each region in the module and check if any 1.1475 + * contain the address of this function. 1.1476 + */ 1.1477 + 1.1478 + for (regno = 0; ; regno++) { 1.1479 + if (ldr_inq_region(process, mod_id, regno, ®info, 1.1480 + sizeof(reginfo), &retsize) != 0) { 1.1481 + /* No more regions */ 1.1482 + break; 1.1483 + } 1.1484 + if (((unsigned long)reginfo.lri_mapaddr <= 1.1485 + (unsigned long)addr) && 1.1486 + (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) > 1.1487 + (unsigned long)addr)) { 1.1488 + /* Found it. */ 1.1489 + result = PR_Malloc(strlen(info.lmi_name)+1); 1.1490 + if (result != NULL) { 1.1491 + strcpy(result, info.lmi_name); 1.1492 + } 1.1493 + return result; 1.1494 + } 1.1495 + } 1.1496 + } 1.1497 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); 1.1498 + return NULL; 1.1499 +#elif defined(HPUX) && defined(USE_HPSHL) 1.1500 + int index; 1.1501 + struct shl_descriptor desc; 1.1502 + char *result; 1.1503 + 1.1504 + for (index = 0; shl_get_r(index, &desc) == 0; index++) { 1.1505 + if (strstr(desc.filename, name) != NULL) { 1.1506 + result = PR_Malloc(strlen(desc.filename)+1); 1.1507 + if (result != NULL) { 1.1508 + strcpy(result, desc.filename); 1.1509 + } 1.1510 + return result; 1.1511 + } 1.1512 + } 1.1513 + /* 1.1514 + * Since the index value of a library is decremented if 1.1515 + * a library preceding it in the shared library search 1.1516 + * list was unloaded, it is possible that we missed some 1.1517 + * libraries as we went up the list. So we should go 1.1518 + * down the list to be sure that we not miss anything. 1.1519 + */ 1.1520 + for (index--; index >= 0; index--) { 1.1521 + if ((shl_get_r(index, &desc) == 0) 1.1522 + && (strstr(desc.filename, name) != NULL)) { 1.1523 + result = PR_Malloc(strlen(desc.filename)+1); 1.1524 + if (result != NULL) { 1.1525 + strcpy(result, desc.filename); 1.1526 + } 1.1527 + return result; 1.1528 + } 1.1529 + } 1.1530 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); 1.1531 + return NULL; 1.1532 +#elif defined(HPUX) && defined(USE_DLFCN) 1.1533 + struct load_module_desc desc; 1.1534 + char *result; 1.1535 + const char *module_name; 1.1536 + 1.1537 + if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) { 1.1538 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); 1.1539 + DLLErrorInternal(_MD_ERRNO()); 1.1540 + return NULL; 1.1541 + } 1.1542 + module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0); 1.1543 + if (module_name == NULL) { 1.1544 + /* should not happen */ 1.1545 + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); 1.1546 + DLLErrorInternal(_MD_ERRNO()); 1.1547 + return NULL; 1.1548 + } 1.1549 + result = PR_Malloc(strlen(module_name)+1); 1.1550 + if (result != NULL) { 1.1551 + strcpy(result, module_name); 1.1552 + } 1.1553 + return result; 1.1554 +#elif defined(WIN32) 1.1555 + PRUnichar wname[MAX_PATH]; 1.1556 + HMODULE handle = NULL; 1.1557 + PRUnichar module_name[MAX_PATH]; 1.1558 + int len; 1.1559 + char *result; 1.1560 + 1.1561 + if (MultiByteToWideChar(CP_ACP, 0, name, -1, wname, MAX_PATH)) { 1.1562 + handle = GetModuleHandleW(wname); 1.1563 + } 1.1564 + if (handle == NULL) { 1.1565 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); 1.1566 + DLLErrorInternal(_MD_ERRNO()); 1.1567 + return NULL; 1.1568 + } 1.1569 + if (GetModuleFileNameW(handle, module_name, MAX_PATH) == 0) { 1.1570 + /* should not happen */ 1.1571 + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); 1.1572 + return NULL; 1.1573 + } 1.1574 + len = WideCharToMultiByte(CP_ACP, 0, module_name, -1, 1.1575 + NULL, 0, NULL, NULL); 1.1576 + if (len == 0) { 1.1577 + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); 1.1578 + return NULL; 1.1579 + } 1.1580 + result = PR_Malloc(len * sizeof(PRUnichar)); 1.1581 + if (result != NULL) { 1.1582 + WideCharToMultiByte(CP_ACP, 0, module_name, -1, 1.1583 + result, len, NULL, NULL); 1.1584 + } 1.1585 + return result; 1.1586 +#elif defined(XP_OS2) 1.1587 + HMODULE module = NULL; 1.1588 + char module_name[_MAX_PATH]; 1.1589 + char *result; 1.1590 + APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr); 1.1591 + if ((NO_ERROR != ulrc) || (NULL == module) ) { 1.1592 + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); 1.1593 + DLLErrorInternal(_MD_ERRNO()); 1.1594 + return NULL; 1.1595 + } 1.1596 + ulrc = DosQueryModuleName(module, sizeof module_name, module_name); 1.1597 + if (NO_ERROR != ulrc) { 1.1598 + /* should not happen */ 1.1599 + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); 1.1600 + return NULL; 1.1601 + } 1.1602 + result = PR_Malloc(strlen(module_name)+1); 1.1603 + if (result != NULL) { 1.1604 + strcpy(result, module_name); 1.1605 + } 1.1606 + return result; 1.1607 +#else 1.1608 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.1609 + return NULL; 1.1610 +#endif 1.1611 +}