LCOV - code coverage report
Current view: directory - nsprpub/pr/src/linking - prlink.c (source / functions) Found Hit Coverage
Test: app.info Lines: 256 144 56.2 %
Date: 2012-06-02 Functions: 19 14 73.7 %

       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             142 : 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             142 :     const char *error = NULL;
     159                 : #ifdef USE_DLFCN
     160             142 :     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             142 :     if (NULL != error)
     169             142 :         PR_SetErrorText(strlen(error), error);
     170             142 : }  /* DLLErrorInternal */
     171                 : 
     172           20034 : void _PR_InitLinker(void)
     173                 : {
     174           20034 :     PRLibrary *lm = NULL;
     175                 : #if defined(XP_UNIX)
     176                 :     void *h;
     177                 : #endif
     178                 : 
     179           20034 :     if (!pr_linker_lock) {
     180           20034 :         pr_linker_lock = PR_NewNamedMonitor("linker-lock");
     181                 :     }
     182           20034 :     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           20034 :     h = dlopen(0, RTLD_LAZY);
     203           20034 :     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           20034 :     lm = PR_NEWZAP(PRLibrary);
     224           20034 :     if (lm) {
     225           20034 :         lm->name = strdup("a.out");
     226           20034 :         lm->refCount = 1;
     227           20034 :         lm->dlh = h;
     228           20034 :         lm->staticTable = NULL;
     229                 :     }
     230           20034 :     pr_exe_loadmap = lm;
     231           20034 :     pr_loadmap = lm;
     232                 : #endif /* HAVE_DLL */
     233                 : #endif /* XP_UNIX */
     234                 : 
     235           20034 :     if (lm) {
     236           20034 :         PR_LOG(_pr_linker_lm, PR_LOG_MIN,
     237                 :             ("Loaded library %s (init)", lm->name));
     238                 :     }
     239                 : 
     240           20034 :     PR_ExitMonitor(pr_linker_lock);
     241           20034 : }
     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             140 : void _PR_ShutdownLinker(void)
     251                 : {
     252                 :     /* FIXME: pr_exe_loadmap should be destroyed. */
     253                 :     
     254             140 :     PR_DestroyMonitor(pr_linker_lock);
     255             140 :     pr_linker_lock = NULL;
     256                 : 
     257             140 :     if (_pr_currentLibPath) {
     258               0 :         free(_pr_currentLibPath);
     259               0 :         _pr_currentLibPath = NULL;
     260                 :     }
     261             140 : }
     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             328 : 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             328 :     if (strstr(lib, PR_DLL_SUFFIX) == NULL)
     387                 :     {
     388             328 :         if (path) {
     389             328 :             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             328 :     return fullname;
     402                 : }
     403                 : 
     404                 : /*
     405                 : ** Free the memory allocated, for the caller, by PR_GetLibraryName
     406                 : */
     407                 : PR_IMPLEMENT(void) 
     408             328 : PR_FreeLibraryName(char *mem)
     409                 : {
     410             328 :     PR_smprintf_free(mem);
     411             328 : }
     412                 : 
     413                 : static PRLibrary* 
     414            8376 : pr_UnlockedFindLibrary(const char *name)
     415                 : {
     416            8376 :     PRLibrary* lm = pr_loadmap;
     417            8376 :     const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR);
     418            8376 :     np = np ? np + 1 : name;
     419           44745 :     while (lm) {
     420           28330 :     const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
     421           28330 :     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           28330 :     if (strcmp(np, cp)  == 0) 
     429                 : #endif
     430                 :     {
     431                 :         /* found */
     432             337 :         lm->refCount++;
     433             337 :         PR_LOG(_pr_linker_lm, PR_LOG_MIN,
     434                 :            ("%s incr => %d (find lib)",
     435                 :             lm->name, lm->refCount));
     436             337 :         return lm;
     437                 :     }
     438           27993 :     lm = lm->next;
     439                 :     }
     440            8039 :     return NULL;
     441                 : }
     442                 : 
     443                 : PR_IMPLEMENT(PRLibrary*)
     444            8376 : PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags)
     445                 : {
     446            8376 :     if (flags == 0) {
     447            6651 :         flags = _PR_DEFAULT_LD_FLAGS;
     448                 :     }
     449            8376 :     switch (libSpec.type) {
     450                 :         case PR_LibSpec_Pathname:
     451            8376 :             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            6421 : PR_LoadLibrary(const char *name)
     470                 : {
     471                 :     PRLibSpec libSpec;
     472                 : 
     473            6421 :     libSpec.type = PR_LibSpec_Pathname;
     474            6421 :     libSpec.value.pathname = name;
     475            6421 :     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            8376 : pr_LoadLibraryByPathname(const char *name, PRIntn flags)
     676                 : {
     677                 :     PRLibrary *lm;
     678            8376 :     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            8376 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     691                 : 
     692                 :     /* See if library is already loaded */
     693            8376 :     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            8376 :     result = pr_UnlockedFindLibrary(name);
     723                 : #endif
     724                 : 
     725            8376 :     if (result != NULL) goto unlock;
     726                 : 
     727            8039 :     lm = PR_NEWZAP(PRLibrary);
     728            8039 :     if (lm == NULL) {
     729               0 :         oserr = _MD_ERRNO();
     730               0 :         goto unlock;
     731                 :     }
     732            8039 :     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            8039 :     int dl_flags = 0;
     812                 : #endif
     813            8039 :     void *h = NULL;
     814                 : 
     815            8039 :     if (flags & PR_LD_LAZY) {
     816            6650 :         dl_flags |= RTLD_LAZY;
     817                 :     }
     818            8039 :     if (flags & PR_LD_NOW) {
     819            1389 :         dl_flags |= RTLD_NOW;
     820                 :     }
     821            8039 :     if (flags & PR_LD_GLOBAL) {
     822               0 :         dl_flags |= RTLD_GLOBAL;
     823                 :     }
     824            8039 :     if (flags & PR_LD_LOCAL) {
     825            1389 :         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            8039 :     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            8039 :     if (!h) {
     864             142 :         oserr = _MD_ERRNO();
     865             142 :         PR_DELETE(lm);
     866             142 :         goto unlock;
     867                 :     }
     868            7897 :     lm->name = strdup(name);
     869            7897 :     lm->dlh = h;
     870            7897 :     lm->next = pr_loadmap;
     871            7897 :     pr_loadmap = lm;
     872                 :     }
     873                 : #endif /* HAVE_DLL */
     874                 : #endif /* XP_UNIX && !(XP_MACOSX && USE_MACH_DYLD) */
     875                 : 
     876            7897 :     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            7897 :     result = lm;    /* success */
     969            7897 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name));
     970                 : 
     971                 :   unlock:
     972            8376 :     if (result == NULL) {
     973             142 :         PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr);
     974             142 :         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            8376 :     PR_ExitMonitor(pr_linker_lock);
     983            8376 :     return result;
     984                 : }
     985                 : 
     986                 : /*
     987                 : ** Unload a shared library which was loaded via PR_LoadLibrary
     988                 : */
     989                 : PR_IMPLEMENT(PRStatus) 
     990            1707 : PR_UnloadLibrary(PRLibrary *lib)
     991                 : {
     992            1707 :     int result = 0;
     993            1707 :     PRStatus status = PR_SUCCESS;
     994                 : 
     995            1707 :     if ((lib == 0) || (lib->refCount <= 0)) {
     996               0 :         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
     997               0 :         return PR_FAILURE;
     998                 :     }
     999                 : 
    1000            1707 :     PR_EnterMonitor(pr_linker_lock);
    1001            1707 :     if (--lib->refCount > 0) {
    1002             317 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN,
    1003                 :            ("%s decr => %d",
    1004                 :         lib->name, lib->refCount));
    1005             317 :     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            1390 :     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            1390 :     if (pr_loadmap == lib)
    1049             422 :         pr_loadmap = pr_loadmap->next;
    1050             968 :     else if (pr_loadmap != NULL) {
    1051             968 :         PRLibrary* prev = pr_loadmap;
    1052             968 :         PRLibrary* next = pr_loadmap->next;
    1053            2505 :         while (next != NULL) {
    1054            1537 :             if (next == lib) {
    1055             968 :                 prev->next = next->next;
    1056             968 :                 goto freeLib;
    1057                 :             }
    1058             569 :             prev = next;
    1059             569 :             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            1390 :     PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
    1078            1390 :     free(lib->name);
    1079            1390 :     lib->name = NULL;
    1080            1390 :     PR_DELETE(lib);
    1081            1390 :     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            1707 :     PR_ExitMonitor(pr_linker_lock);
    1089            1707 :     return status;
    1090                 : }
    1091                 : 
    1092                 : static void* 
    1093           16377 : pr_FindSymbolInLib(PRLibrary *lm, const char *name)
    1094                 : {
    1095           16377 :     void *f = NULL;
    1096                 : #ifdef XP_OS2
    1097                 :     int rc;
    1098                 : #endif
    1099                 : 
    1100           16377 :     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           16377 :     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           16377 :     if (f == NULL) {
    1205               0 :         PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
    1206               0 :         DLLErrorInternal(_MD_ERRNO());
    1207                 :     }
    1208           16377 :     return f;
    1209                 : }
    1210                 : 
    1211                 : /*
    1212                 : ** Called by class loader to resolve missing native's
    1213                 : */
    1214                 : PR_IMPLEMENT(void*) 
    1215           16377 : PR_FindSymbol(PRLibrary *lib, const char *raw_name)
    1216                 : {
    1217           16377 :     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           16377 :     name = raw_name;
    1238                 : #endif
    1239                 : 
    1240           16377 :     PR_EnterMonitor(pr_linker_lock);
    1241           16377 :     PR_ASSERT(lib != NULL);
    1242           16377 :     f = pr_FindSymbolInLib(lib, name);
    1243                 : 
    1244                 : #if defined(NEED_LEADING_UNDERSCORE)
    1245                 :     PR_smprintf_free(name);
    1246                 : #endif
    1247                 : 
    1248           16377 :     PR_ExitMonitor(pr_linker_lock);
    1249           16377 :     return f;
    1250                 : }
    1251                 : 
    1252                 : /*
    1253                 : ** Return the address of the function 'raw_name' in the library 'lib'
    1254                 : */
    1255                 : PR_IMPLEMENT(PRFuncPtr) 
    1256            8963 : PR_FindFunctionSymbol(PRLibrary *lib, const char *raw_name)
    1257                 : {
    1258            8963 :     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            2053 : 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            2053 :     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            2053 :     result = PR_Malloc(strlen(dli.dli_fname)+1);
    1373            2053 :     if (result != NULL) {
    1374            2053 :         strcpy(result, dli.dli_fname);
    1375                 :     }
    1376            2053 :     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