nsprpub/pr/src/linking/prlink.c

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

mercurial