LCOV - app.info - nsprpub/pr/src/linking/prlink.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/linking - prlink.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 256 | 19 | 7.4 %
| Date: | 2012-04-07 | Functions: | 19 | 1 | 5.3 %

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

Generated by: LCOV version 1.7