LCOV - code coverage report
Current view: top level - nsprpub/pr/src/linking - prlink.c (source / functions) Hit Total Coverage
Test: output.info Lines: 91 247 36.8 %
Date: 2017-07-14 16:53:18 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : 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           0 :     const char *error = NULL;
     126             : #ifdef USE_DLFCN
     127           0 :     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           0 :     if (NULL != error)
     136           0 :         PR_SetErrorText(strlen(error), error);
     137           0 : }  /* DLLErrorInternal */
     138             : 
     139           3 : void _PR_InitLinker(void)
     140             : {
     141           3 :     PRLibrary *lm = NULL;
     142             : #if defined(XP_UNIX)
     143             :     void *h;
     144             : #endif
     145             : 
     146           3 :     if (!pr_linker_lock) {
     147           3 :         pr_linker_lock = PR_NewNamedMonitor("linker-lock");
     148             :     }
     149           3 :     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           3 :     h = dlopen(0, RTLD_LAZY);
     170           3 :     if (!h) {
     171             :         char *error;
     172             :         
     173           0 :         DLLErrorInternal(_MD_ERRNO());
     174           0 :         error = (char*)PR_MALLOC(PR_GetErrorTextLength());
     175           0 :         (void) PR_GetErrorText(error);
     176           0 :         fprintf(stderr, "failed to initialize shared libraries [%s]\n",
     177             :             error);
     178           0 :         PR_DELETE(error);
     179           0 :         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           3 :     lm = PR_NEWZAP(PRLibrary);
     191           3 :     if (lm) {
     192           3 :         lm->name = strdup("a.out");
     193           3 :         lm->refCount = 1;
     194           3 :         lm->dlh = h;
     195           3 :         lm->staticTable = NULL;
     196             :     }
     197           3 :     pr_exe_loadmap = lm;
     198           3 :     pr_loadmap = lm;
     199             : #endif /* HAVE_DLL */
     200             : #endif /* XP_UNIX */
     201             : 
     202           3 :     if (lm) {
     203           3 :         PR_LOG(_pr_linker_lm, PR_LOG_MIN,
     204             :             ("Loaded library %s (init)", lm->name));
     205             :     }
     206             : 
     207           3 :     PR_ExitMonitor(pr_linker_lock);
     208           3 : }
     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           0 : void _PR_ShutdownLinker(void)
     218             : {
     219             :     /* FIXME: pr_exe_loadmap should be destroyed. */
     220             :     
     221           0 :     PR_DestroyMonitor(pr_linker_lock);
     222           0 :     pr_linker_lock = NULL;
     223             : 
     224           0 :     if (_pr_currentLibPath) {
     225           0 :         free(_pr_currentLibPath);
     226           0 :         _pr_currentLibPath = NULL;
     227             :     }
     228           0 : }
     229             : 
     230             : /******************************************************************************/
     231             : 
     232             : PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path)
     233             : {
     234           0 :     PRStatus rv = PR_SUCCESS;
     235             : 
     236           0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     237           0 :     PR_EnterMonitor(pr_linker_lock);
     238           0 :     if (_pr_currentLibPath) {
     239           0 :         free(_pr_currentLibPath);
     240             :     }
     241           0 :     if (path) {
     242           0 :         _pr_currentLibPath = strdup(path);
     243           0 :         if (!_pr_currentLibPath) {
     244           0 :             PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     245           0 :         rv = PR_FAILURE;
     246             :         }
     247             :     } else {
     248           0 :         _pr_currentLibPath = 0;
     249             :     }
     250           0 :     PR_ExitMonitor(pr_linker_lock);
     251           0 :     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           0 :     char *copy = NULL;  /* a copy of _pr_currentLibPath */
     262             : 
     263           0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     264           0 :     PR_EnterMonitor(pr_linker_lock);
     265           0 :     if (_pr_currentLibPath != NULL) {
     266           0 :         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           0 :     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           0 :     ev = getenv("LD_LIBRARY_PATH");
     292           0 :     if (!ev) {
     293           0 :         ev = "/usr/lib:/lib";
     294             :     }
     295             : #endif
     296           0 :     len = strlen(ev) + 1;        /* +1 for the null */
     297             : 
     298           0 :     p = (char*) malloc(len);
     299           0 :     if (p) {
     300           0 :         strcpy(p, ev);
     301             :     }   /* if (p)  */
     302           0 :     ev = p;
     303           0 :     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           0 :     _pr_currentLibPath = ev;
     316             : 
     317             :   exit:
     318           0 :     if (_pr_currentLibPath) {
     319           0 :         copy = strdup(_pr_currentLibPath);
     320             :     }
     321           0 :     PR_ExitMonitor(pr_linker_lock);
     322           0 :     if (!copy) {
     323           0 :         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     324             :     }
     325           0 :     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           1 :     if (strstr(lib, PR_DLL_SUFFIX) == NULL)
     354             :     {
     355           1 :         if (path) {
     356           1 :             fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX);
     357             :         } else {
     358           0 :             fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX);
     359             :         }
     360             :     } else {
     361           0 :         if (path) {
     362           0 :             fullname = PR_smprintf("%s/%s", path, lib);
     363             :         } else {
     364           0 :             fullname = PR_smprintf("%s", lib);
     365             :         }
     366             :     }
     367             : #endif /* XP_UNIX || XP_BEOS */
     368           1 :     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           1 :     PR_smprintf_free(mem);
     378           1 : }
     379             : 
     380             : static PRLibrary* 
     381           8 : pr_UnlockedFindLibrary(const char *name)
     382             : {
     383           8 :     PRLibrary* lm = pr_loadmap;
     384           8 :     const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR);
     385           8 :     np = np ? np + 1 : name;
     386          40 :     while (lm) {
     387          24 :     const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
     388          24 :     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          24 :     if (strcmp(np, cp)  == 0) 
     396             : #endif
     397             :     {
     398             :         /* found */
     399           0 :         lm->refCount++;
     400           0 :         PR_LOG(_pr_linker_lm, PR_LOG_MIN,
     401             :            ("%s incr => %d (find lib)",
     402             :             lm->name, lm->refCount));
     403           0 :         return lm;
     404             :     }
     405          24 :     lm = lm->next;
     406             :     }
     407           8 :     return NULL;
     408             : }
     409             : 
     410             : PR_IMPLEMENT(PRLibrary*)
     411             : PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags)
     412             : {
     413           8 :     if (flags == 0) {
     414           3 :         flags = _PR_DEFAULT_LD_FLAGS;
     415             :     }
     416           8 :     switch (libSpec.type) {
     417             :         case PR_LibSpec_Pathname:
     418           8 :             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           0 :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     431           0 :             return NULL;
     432             :     }
     433             : }
     434             :             
     435             : PR_IMPLEMENT(PRLibrary*) 
     436             : PR_LoadLibrary(const char *name)
     437             : {
     438             :     PRLibSpec libSpec;
     439             : 
     440           3 :     libSpec.type = PR_LibSpec_Pathname;
     441           3 :     libSpec.value.pathname = name;
     442           3 :     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, 0x7C0903A6, 0x4E800420 };
     498             :     uint32* newGlue = NULL;
     499             : 
     500             :     if (tvp != NULL) {
     501             :         CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII);
     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 for 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           8 : pr_LoadLibraryByPathname(const char *name, PRIntn flags)
     643             : {
     644             :     PRLibrary *lm;
     645           8 :     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           8 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     658             : 
     659             :     /* See if library is already loaded */
     660           8 :     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           8 :     result = pr_UnlockedFindLibrary(name);
     690             : #endif
     691             : 
     692           8 :     if (result != NULL) goto unlock;
     693             : 
     694           8 :     lm = PR_NEWZAP(PRLibrary);
     695           8 :     if (lm == NULL) {
     696           0 :         oserr = _MD_ERRNO();
     697           0 :         goto unlock;
     698             :     }
     699           8 :     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           8 :     int dl_flags = 0;
     779             : #endif
     780           8 :     void *h = NULL;
     781             : 
     782           8 :     if (flags & PR_LD_LAZY) {
     783           3 :         dl_flags |= RTLD_LAZY;
     784             :     }
     785           8 :     if (flags & PR_LD_NOW) {
     786           5 :         dl_flags |= RTLD_NOW;
     787             :     }
     788           8 :     if (flags & PR_LD_GLOBAL) {
     789           0 :         dl_flags |= RTLD_GLOBAL;
     790             :     }
     791           8 :     if (flags & PR_LD_LOCAL) {
     792           5 :         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           8 :     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           8 :     if (!h) {
     831           0 :         oserr = _MD_ERRNO();
     832           0 :         PR_DELETE(lm);
     833           0 :         goto unlock;
     834             :     }
     835           8 :     lm->name = strdup(name);
     836           8 :     lm->dlh = h;
     837           8 :     lm->next = pr_loadmap;
     838           8 :     pr_loadmap = lm;
     839             :     }
     840             : #endif /* HAVE_DLL */
     841             : #endif /* XP_UNIX && !(XP_MACOSX && USE_MACH_DYLD) */
     842             : 
     843           8 :     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           8 :     result = lm;    /* success */
     936           8 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name));
     937             : 
     938             :   unlock:
     939           8 :     if (result == NULL) {
     940           0 :         PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr);
     941           0 :         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           8 :     PR_ExitMonitor(pr_linker_lock);
     950           8 :     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           0 :     int result = 0;
     960           0 :     PRStatus status = PR_SUCCESS;
     961             : 
     962           0 :     if (lib == 0) {
     963           0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     964           0 :         return PR_FAILURE;
     965             :     }
     966             : 
     967           0 :     PR_EnterMonitor(pr_linker_lock);
     968             : 
     969           0 :     if (lib->refCount <= 0) {
     970           0 :         PR_ExitMonitor(pr_linker_lock);
     971           0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     972           0 :         return PR_FAILURE;
     973             :     }
     974             : 
     975           0 :     if (--lib->refCount > 0) {
     976           0 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN,
     977             :            ("%s decr => %d",
     978             :         lib->name, lib->refCount));
     979           0 :     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           0 :     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           0 :     if (pr_loadmap == lib)
    1023           0 :         pr_loadmap = pr_loadmap->next;
    1024           0 :     else if (pr_loadmap != NULL) {
    1025           0 :         PRLibrary* prev = pr_loadmap;
    1026           0 :         PRLibrary* next = pr_loadmap->next;
    1027           0 :         while (next != NULL) {
    1028           0 :             if (next == lib) {
    1029           0 :                 prev->next = next->next;
    1030           0 :                 goto freeLib;
    1031             :             }
    1032           0 :             prev = next;
    1033           0 :             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           0 :         PR_NOT_REACHED("_pr_loadmap and lib->refCount inconsistent");
    1040           0 :         if (result == 0) {
    1041           0 :             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    1042           0 :             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           0 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
    1052           0 :     free(lib->name);
    1053           0 :     lib->name = NULL;
    1054           0 :     PR_DELETE(lib);
    1055           0 :     if (result != 0) {
    1056           0 :         PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
    1057           0 :         DLLErrorInternal(_MD_ERRNO());
    1058           0 :         status = PR_FAILURE;
    1059             :     }
    1060             : 
    1061             : done:
    1062           0 :     PR_ExitMonitor(pr_linker_lock);
    1063           0 :     return status;
    1064             : }
    1065             : 
    1066             : static void* 
    1067          21 : pr_FindSymbolInLib(PRLibrary *lm, const char *name)
    1068             : {
    1069          21 :     void *f = NULL;
    1070             : #ifdef XP_OS2
    1071             :     int rc;
    1072             : #endif
    1073             : 
    1074          21 :     if (lm->staticTable != NULL) {
    1075             :         const PRStaticLinkTable* tp;
    1076           0 :         for (tp = lm->staticTable; tp->name; tp++) {
    1077           0 :             if (strcmp(name, tp->name) == 0) {
    1078           0 :                 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           0 :         PR_SetError(PR_FIND_SYMBOL_ERROR, 0);
    1087           0 :         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_OFFSET));
    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 glue. */
    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_TEXT, &f ) ) {
    1154             :         f = NULL;
    1155             :     }
    1156             : #endif
    1157             : 
    1158             : #ifdef XP_UNIX
    1159             : #ifdef HAVE_DLL
    1160             : #ifdef USE_DLFCN
    1161          21 :     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          21 :     if (f == NULL) {
    1179           0 :         PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
    1180           0 :         DLLErrorInternal(_MD_ERRNO());
    1181             :     }
    1182          21 :     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          21 :     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          21 :     name = raw_name;
    1212             : #endif
    1213             : 
    1214          21 :     PR_EnterMonitor(pr_linker_lock);
    1215          21 :     PR_ASSERT(lib != NULL);
    1216          21 :     f = pr_FindSymbolInLib(lib, name);
    1217             : 
    1218             : #if defined(NEED_LEADING_UNDERSCORE)
    1219             :     PR_smprintf_free(name);
    1220             : #endif
    1221             : 
    1222          21 :     PR_ExitMonitor(pr_linker_lock);
    1223          21 :     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          14 :     return ((PRFuncPtr) PR_FindSymbol(lib, raw_name));
    1233             : }
    1234             : 
    1235             : PR_IMPLEMENT(void*) 
    1236             : PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
    1237             : {
    1238           0 :     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           0 :     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           0 :     name = raw_name;
    1262             : #endif
    1263             : 
    1264           0 :     PR_EnterMonitor(pr_linker_lock);
    1265             : 
    1266             :     /* search all libraries */
    1267           0 :     for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
    1268           0 :         f = pr_FindSymbolInLib(lm, name);
    1269           0 :         if (f != NULL) {
    1270           0 :             *lib = lm;
    1271           0 :             lm->refCount++;
    1272           0 :             PR_LOG(_pr_linker_lm, PR_LOG_MIN,
    1273             :                        ("%s incr => %d (for %s)",
    1274             :                     lm->name, lm->refCount, name));
    1275           0 :             break;
    1276             :         }
    1277             :     }
    1278             : #if defined(NEED_LEADING_UNDERSCORE)
    1279             :     PR_smprintf_free(name);
    1280             : #endif
    1281             : 
    1282           0 :     PR_ExitMonitor(pr_linker_lock);
    1283           0 :     return f;
    1284             : }
    1285             : 
    1286             : PR_IMPLEMENT(PRFuncPtr) 
    1287             : PR_FindFunctionSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
    1288             : {
    1289           0 :     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           0 :     PRLibrary *lm=NULL;
    1300           0 :     PRLibrary* result = NULL;
    1301             : 
    1302           0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
    1303             : 
    1304             :     /* See if library is already loaded */
    1305           0 :     PR_EnterMonitor(pr_linker_lock);
    1306             : 
    1307             :     /* If the lbrary is already loaded, then add the static table information... */
    1308           0 :     result = pr_UnlockedFindLibrary(name);
    1309           0 :     if (result != NULL) {
    1310           0 :         PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) );
    1311           0 :         result->staticTable = slt;
    1312           0 :         goto unlock;
    1313             :     }
    1314             : 
    1315             :     /* Add library to list...Mark it static */
    1316           0 :     lm = PR_NEWZAP(PRLibrary);
    1317           0 :     if (lm == NULL) goto unlock;
    1318             : 
    1319           0 :     lm->name = strdup(name);
    1320           0 :     lm->refCount    = 1;
    1321           0 :     lm->dlh         = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0;
    1322           0 :     lm->staticTable = slt;
    1323           0 :     lm->next        = pr_loadmap;
    1324           0 :     pr_loadmap      = lm;
    1325             : 
    1326           0 :     result = lm;    /* success */
    1327           0 :     PR_ASSERT(lm->refCount == 1);
    1328           0 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->name));
    1329             :   unlock:
    1330           0 :     PR_ExitMonitor(pr_linker_lock);
    1331           0 :     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           6 :     if (dladdr((void *)addr, &dli) == 0) {
    1342           0 :         PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
    1343           0 :         DLLErrorInternal(_MD_ERRNO());
    1344           0 :         return NULL;
    1345             :     }
    1346           6 :     result = PR_Malloc(strlen(dli.dli_fname)+1);
    1347           6 :     if (result != NULL) {
    1348           6 :         strcpy(result, dli.dli_fname);
    1349             :     }
    1350           6 :     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             : }

Generated by: LCOV version 1.13