Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions | Variables
prlink.c File Reference
#include "primpl.h"
#include <string.h>

Go to the source code of this file.

Classes

struct  PRLibrary

Defines

#define _PR_DEFAULT_LD_FLAGS   PR_LD_LAZY
#define PR_LD_PATHW   0x8000 /* for PR_LibSpec_PathnameU */
#define ERR_STR_BUF_LENGTH   20

Functions

static PRLibrarypr_LoadLibraryByPathname (const char *name, PRIntn flags)
static char * errno_string (PRIntn oserr)
static void DLLErrorInternal (PRIntn oserr)
void _PR_InitLinker (void)
void _PR_ShutdownLinker (void)
 PR_IMPLEMENT (PRStatus)
 PR_GetLibraryPath (void)
 PR_GetLibraryName (const char *path, const char *lib)
 PR_FreeLibraryName (char *mem)
static PRLibrarypr_UnlockedFindLibrary (const char *name)
 PR_LoadLibraryWithFlags (PRLibSpec libSpec, PRIntn flags)
 PR_LoadLibrary (const char *name)
 PR_UnloadLibrary (PRLibrary *lib)
static voidpr_FindSymbolInLib (PRLibrary *lm, const char *name)
 PR_FindSymbol (PRLibrary *lib, const char *raw_name)
 PR_FindFunctionSymbol (PRLibrary *lib, const char *raw_name)
 PR_FindSymbolAndLibrary (const char *raw_name, PRLibrary **lib)
 PR_FindFunctionSymbolAndLibrary (const char *raw_name, PRLibrary **lib)
 PR_LoadStaticLibrary (const char *name, const PRStaticLinkTable *slt)
 PR_GetLibraryFilePathname (const char *name, PRFuncPtr addr)

Variables

static PRLibrarypr_loadmap
static PRLibrarypr_exe_loadmap
static PRMonitorpr_linker_lock
static char * _pr_currentLibPath = NULL
static char * errStrBuf = NULL

Class Documentation

struct PRLibrary

Definition at line 168 of file prlink.c.

Collaboration diagram for PRLibrary:
Class Members
char * name
PRLibrary * next
int refCount
const PRStaticLinkTable * staticTable

Define Documentation

Definition at line 89 of file prlink.c.

Definition at line 227 of file prlink.c.

#define PR_LD_PATHW   0x8000 /* for PR_LibSpec_PathnameU */

Definition at line 164 of file prlink.c.


Function Documentation

Definition at line 256 of file prlink.c.

{
    PRLibrary *lm = NULL;
#if defined(XP_UNIX)
    void *h;
#endif

#ifdef WIN95
    if (!_pr_useUnicode) {
        loadLibraryW = EmulateLoadLibraryW;
    }
#endif

    if (!pr_linker_lock) {
        pr_linker_lock = PR_NewNamedMonitor("linker-lock");
    }
    PR_EnterMonitor(pr_linker_lock);

#if defined(XP_PC)
    lm = PR_NEWZAP(PRLibrary);
    lm->name = strdup("Executable");
        /* 
        ** In WIN32, GetProcAddress(...) expects a module handle in order to
        ** get exported symbols from the executable...
        **
        ** However, in WIN16 this is accomplished by passing NULL to 
        ** GetProcAddress(...)
        */
#if defined(_WIN32)
        lm->dlh = GetModuleHandle(NULL);
#else
        lm->dlh = (HINSTANCE)NULL;
#endif /* ! _WIN32 */

    lm->refCount    = 1;
    lm->staticTable = NULL;
    pr_exe_loadmap  = lm;
    pr_loadmap      = lm;

#elif defined(XP_UNIX)
#ifdef HAVE_DLL
#ifdef USE_DLFCN
    h = dlopen(0, RTLD_LAZY);
    if (!h) {
        char *error;
        
        DLLErrorInternal(_MD_ERRNO());
        error = (char*)PR_MALLOC(PR_GetErrorTextLength());
        (void) PR_GetErrorText(error);
        fprintf(stderr, "failed to initialize shared libraries [%s]\n",
            error);
        PR_DELETE(error);
        abort();/* XXX */
    }
#elif defined(USE_HPSHL)
    h = NULL;
    /* don't abort with this NULL */
#elif defined(USE_MACH_DYLD)
    h = NULL; /* XXXX  toshok */
#else
#error no dll strategy
#endif /* USE_DLFCN */

    lm = PR_NEWZAP(PRLibrary);
    if (lm) {
        lm->name = strdup("a.out");
        lm->refCount = 1;
        lm->dlh = h;
        lm->staticTable = NULL;
    }
    pr_exe_loadmap = lm;
    pr_loadmap = lm;
#endif /* HAVE_DLL */
#endif /* XP_UNIX */

    if (lm) {
        PR_LOG(_pr_linker_lm, PR_LOG_MIN,
            ("Loaded library %s (init)", lm->name));
    }

    PR_ExitMonitor(pr_linker_lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 374 of file prlink.c.

{
    /* FIXME: pr_exe_loadmap should be destroyed. */
    
    PR_DestroyMonitor(pr_linker_lock);
    pr_linker_lock = NULL;

    if (_pr_currentLibPath) {
        free(_pr_currentLibPath);
        _pr_currentLibPath = NULL;
    }

#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR)
    PR_DELETE(errStrBuf);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void DLLErrorInternal ( PRIntn  oserr) [static]

Definition at line 237 of file prlink.c.

{
    const char *error = NULL;
#ifdef USE_DLFCN
    error = dlerror();  /* $$$ That'll be wrong some of the time - AOF */
#elif defined(HAVE_STRERROR)
    error = strerror(oserr);  /* this should be okay */
#else
    error = errno_string(oserr);
#endif
    if (NULL != error)
        PR_SetErrorText(strlen(error), error);
}  /* DLLErrorInternal */

Here is the call graph for this function:

Here is the caller graph for this function:

static char* errno_string ( PRIntn  oserr) [static]

Definition at line 228 of file prlink.c.

Here is the call graph for this function:

Here is the caller graph for this function:

PR_FindFunctionSymbol ( PRLibrary lib,
const char *  raw_name 
)

Definition at line 1502 of file prlink.c.

{
    return ((PRFuncPtr) PR_FindSymbol(lib, raw_name));
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_FindFunctionSymbolAndLibrary ( const char *  raw_name,
PRLibrary **  lib 
)

Definition at line 1559 of file prlink.c.

{
    return ((PRFuncPtr) PR_FindSymbolAndLibrary(raw_name, lib));
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_FindSymbol ( PRLibrary lib,
const char *  raw_name 
)

Definition at line 1461 of file prlink.c.

{
    void *f = NULL;
#if defined(NEED_LEADING_UNDERSCORE)
    char *name;
#else
    const char *name;
#endif
    /*
    ** Mangle the raw symbol name in any way that is platform specific.
    */
#if defined(NEED_LEADING_UNDERSCORE)
    /* Need a leading _ */
    name = PR_smprintf("_%s", raw_name);
#elif defined(AIX)
    /*
    ** AIX with the normal linker put's a "." in front of the symbol
    ** name.  When use "svcc" and "svld" then the "." disappears. Go
    ** figure.
    */
    name = raw_name;
#else
    name = raw_name;
#endif

    PR_EnterMonitor(pr_linker_lock);
    PR_ASSERT(lib != NULL);
    f = pr_FindSymbolInLib(lib, name);

#if defined(NEED_LEADING_UNDERSCORE)
    PR_smprintf_free(name);
#endif

    PR_ExitMonitor(pr_linker_lock);
    return f;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_FindSymbolAndLibrary ( const char *  raw_name,
PRLibrary **  lib 
)

Definition at line 1508 of file prlink.c.

{
    void *f = NULL;
#if defined(NEED_LEADING_UNDERSCORE)
    char *name;
#else
    const char *name;
#endif
    PRLibrary* lm;

    if (!_pr_initialized) _PR_ImplicitInitialization();
    /*
    ** Mangle the raw symbol name in any way that is platform specific.
    */
#if defined(NEED_LEADING_UNDERSCORE)
    /* Need a leading _ */
    name = PR_smprintf("_%s", raw_name);
#elif defined(AIX)
    /*
    ** AIX with the normal linker put's a "." in front of the symbol
    ** name.  When use "svcc" and "svld" then the "." disappears. Go
    ** figure.
    */
    name = raw_name;
#else
    name = raw_name;
#endif

    PR_EnterMonitor(pr_linker_lock);

    /* search all libraries */
    for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
        f = pr_FindSymbolInLib(lm, name);
        if (f != NULL) {
            *lib = lm;
            lm->refCount++;
            PR_LOG(_pr_linker_lm, PR_LOG_MIN,
                       ("%s incr => %d (for %s)",
                    lm->name, lm->refCount, name));
            break;
        }
    }
#if defined(NEED_LEADING_UNDERSCORE)
    PR_smprintf_free(name);
#endif

    PR_ExitMonitor(pr_linker_lock);
    return f;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* pr_FindSymbolInLib ( PRLibrary lm,
const char *  name 
) [static]

Definition at line 1341 of file prlink.c.

{
    void *f = NULL;
#ifdef XP_OS2
    int rc;
#endif

    if (lm->staticTable != NULL) {
        const PRStaticLinkTable* tp;
        for (tp = lm->staticTable; tp->name; tp++) {
            if (strcmp(name, tp->name) == 0) {
                return (void*) tp->fp;
            }
        }
        /* 
        ** If the symbol was not found in the static table then check if
        ** the symbol was exported in the DLL... Win16 only!!
        */
#if !defined(WIN16) && !defined(XP_BEOS)
        PR_SetError(PR_FIND_SYMBOL_ERROR, 0);
        return (void*)NULL;
#endif
    }
    
#ifdef XP_OS2
    rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
#if defined(NEED_LEADING_UNDERSCORE)
    /*
     * Older plugins (not built using GCC) will have symbols that are not
     * underscore prefixed.  We check for that here.
     */
    if (rc != NO_ERROR) {
        name++;
        DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
    }
#endif
#endif  /* XP_OS2 */

#if defined(WIN32) || defined(WIN16)
    f = GetProcAddress(lm->dlh, name);
#endif  /* WIN32 || WIN16 */

#ifdef XP_MACOSX
/* add this offset to skip the leading underscore in name */
#define SYM_OFFSET 1
    if (lm->bundle) {
        CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII);
        if (nameRef) {
            f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef);
            CFRelease(nameRef);
        }
    }
    if (lm->connection) {
        Ptr                 symAddr;
        CFragSymbolClass    symClass;
        Str255              pName;
        
        PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_OFFSET));
        
        c2pstrcpy(pName, name + SYM_OFFSET);
        
        f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
        
        /* callers expect mach-o function pointers, so must wrap tvectors with glue. */
        if (f && symClass == kTVectorCFragSymbol) {
            f = TV2FP(lm->wrappers, name + SYM_OFFSET, f);
        }
        
        if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main;
    }
    if (lm->image) {
        NSSymbol symbol;
        symbol = NSLookupSymbolInImage(lm->image, name,
                 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
                 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
        if (symbol != NULL)
            f = NSAddressOfSymbol(symbol);
        else
            f = NULL;
    }
#undef SYM_OFFSET
#endif /* XP_MACOSX */

#ifdef XP_BEOS
    if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_TEXT, &f ) ) {
        f = NULL;
    }
#endif

#ifdef XP_UNIX
#ifdef HAVE_DLL
#ifdef USE_DLFCN
    f = dlsym(lm->dlh, name);
#elif defined(USE_HPSHL)
    if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) {
        f = NULL;
    }
#elif defined(USE_MACH_DYLD)
    if (lm->dlh) {
        NSSymbol symbol;
        symbol = NSLookupSymbolInModule(lm->dlh, name);
        if (symbol != NULL)
            f = NSAddressOfSymbol(symbol);
        else
            f = NULL;
    }
#endif
#endif /* HAVE_DLL */
#endif /* XP_UNIX */
    if (f == NULL) {
        PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
    }
    return f;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_FreeLibraryName ( char *  mem)

Definition at line 537 of file prlink.c.

{
    PR_smprintf_free(mem);
}

Here is the caller graph for this function:

PR_GetLibraryFilePathname ( const char *  name,
PRFuncPtr  addr 
)

Definition at line 1607 of file prlink.c.

{
#if defined(SOLARIS) || defined(LINUX) || defined(FREEBSD)
    Dl_info dli;
    char *result;

    if (dladdr((void *)addr, &dli) == 0) {
        PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
        return NULL;
    }
    result = PR_Malloc(strlen(dli.dli_fname)+1);
    if (result != NULL) {
        strcpy(result, dli.dli_fname);
    }
    return result;
#elif defined(USE_MACH_DYLD)
    char *result;
    char *image_name;
    int i, count = _dyld_image_count();

    for (i = 0; i < count; i++) {
        image_name = _dyld_get_image_name(i);
        if (strstr(image_name, name) != NULL) {
            result = PR_Malloc(strlen(image_name)+1);
            if (result != NULL) {
                strcpy(result, image_name);
            }
            return result;
        }
    }
    PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
    return NULL;
#elif defined(AIX)
    char *result;
#define LD_INFO_INCREMENT 64
    struct ld_info *info;
    unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info);
    struct ld_info *infop;
    int loadflags = L_GETINFO | L_IGNOREUNLOAD;

    for (;;) {
        info = PR_Malloc(info_length);
        if (info == NULL) {
            return NULL;
        }
        /* If buffer is too small, loadquery fails with ENOMEM. */
        if (loadquery(loadflags, info, info_length) != -1) {
            break;
        }
        /*
         * Calling loadquery when compiled for 64-bit with the
         * L_IGNOREUNLOAD flag can cause an invalid argument error
         * on AIX 5.1. Detect this error the first time that
         * loadquery is called, and try calling it again without
         * this flag set.
         */
        if (errno == EINVAL && (loadflags & L_IGNOREUNLOAD)) {
            loadflags &= ~L_IGNOREUNLOAD;
            if (loadquery(loadflags, info, info_length) != -1) {
                break;
            }
        }
        PR_Free(info);
        if (errno != ENOMEM) {
            /* should not happen */
            _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
            return NULL;
        }
        /* retry with a larger buffer */
        info_length += LD_INFO_INCREMENT * sizeof(struct ld_info);
    }

    for (infop = info;
         ;
         infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) {
        unsigned long start = (unsigned long)infop->ldinfo_dataorg;
        unsigned long end = start + infop->ldinfo_datasize;
        if (start <= (unsigned long)addr && end > (unsigned long)addr) {
            result = PR_Malloc(strlen(infop->ldinfo_filename)+1);
            if (result != NULL) {
                strcpy(result, infop->ldinfo_filename);
            }
            break;
        }
        if (!infop->ldinfo_next) {
            PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
            result = NULL;
            break;
        }
    }
    PR_Free(info);
    return result;
#elif defined(OSF1)
    /* Contributed by Steve Streeter of HP */
    ldr_process_t process, ldr_my_process();
    ldr_module_t mod_id;
    ldr_module_info_t info;
    ldr_region_t regno;
    ldr_region_info_t reginfo;
    size_t retsize;
    int rv;
    char *result;

    /* Get process for which dynamic modules will be listed */

    process = ldr_my_process();

    /* Attach to process */

    rv = ldr_xattach(process);
    if (rv) {
        /* should not happen */
        _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
        return NULL;
    }

    /* Print information for list of modules */

    mod_id = LDR_NULL_MODULE;

    for (;;) {

        /* Get information for the next module in the module list. */

        ldr_next_module(process, &mod_id);
        if (ldr_inq_module(process, mod_id, &info, sizeof(info),
                           &retsize) != 0) {
            /* No more modules */
            break;
        }
        if (retsize < sizeof(info)) {
            continue;
        }

        /*
         * Get information for each region in the module and check if any
         * contain the address of this function.
         */

        for (regno = 0; ; regno++) {
            if (ldr_inq_region(process, mod_id, regno, &reginfo,
                               sizeof(reginfo), &retsize) != 0) {
                /* No more regions */
                break;
            }
            if (((unsigned long)reginfo.lri_mapaddr <=
                (unsigned long)addr) &&
                (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) >
                (unsigned long)addr)) {
                /* Found it. */
                result = PR_Malloc(strlen(info.lmi_name)+1);
                if (result != NULL) {
                    strcpy(result, info.lmi_name);
                }
                return result;
            }
        }
    }
    PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
    return NULL;
#elif defined(VMS)
    /* Contributed by Colin Blake of HP */
    struct _imcb     *icb;
    ulong_t          status;
    char                device_name[MAX_DEVNAM];
    int                 device_name_len;
    $DESCRIPTOR         (device_name_desc, device_name);
    struct fibdef    fib;
    struct dsc$descriptor_s fib_desc = 
       { sizeof(struct fibdef), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *)&fib } ;
    IOSB             iosb;
    ITMLST           devlst[2] = {
                     {MAX_DEVNAM, DVI$_ALLDEVNAM, device_name, &device_name_len},
                     {0,0,0,0}};
    short               file_name_len;
    char                file_name[MAX_FILNAM+1];
    char             *result = NULL;
    struct dsc$descriptor_s file_name_desc = 
       { MAX_FILNAM, DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *) &file_name[0] } ;

    /*
    ** The address for the process image list could change in future versions
    ** of the operating system. 7FFD0688 is valid for V7.2 and V7.3 releases,
    ** so we use that for the default, but allow an environment variable
    ** (logical name) to override.
    */
    if (IAC$GL_IMAGE_LIST == NULL) {
        char *p = getenv("MOZILLA_IAC_GL_IMAGE_LIST");
        if (p)
            IAC$GL_IMAGE_LIST = (struct _imcb *) strtol(p,NULL,0);
        else
            IAC$GL_IMAGE_LIST = (struct _imcb *) 0x7FFD0688;
    }

    for (icb = IAC$GL_IMAGE_LIST->imcb$l_flink;
         icb != IAC$GL_IMAGE_LIST;
         icb = icb->imcb$l_flink) {
        if (((void *)addr >= icb->imcb$l_starting_address) && 
           ((void *)addr <= icb->imcb$l_end_address)) {
           /*
           ** This is the correct image.
           ** Get the device name.
           */
           status = sys$getdviw(0,icb->imcb$w_chan,0,&devlst,0,0,0,0);
           if ($VMS_STATUS_SUCCESS(status))
              device_name_desc.dsc$w_length = device_name_len;

           /*
           ** Get the FID.
           */
           memset(&fib,0,sizeof(struct fibdef));
           status = sys$qiow(0,icb->imcb$w_chan,IO$_ACCESS,&iosb,
                            0,0,&fib_desc,0,0,0,0,0);

           /*
           ** If we got the FID, now look up its name (if for some reason
           ** we didn't get the device name, this call will fail).
           */
           if (($VMS_STATUS_SUCCESS(status)) && ($VMS_STATUS_SUCCESS(iosb.cond))) {
              status = lib$fid_to_name (
                    &device_name_desc,
                    &fib.fib$w_fid,
                    &file_name_desc,
                    &file_name_len,
                    0, 0);

              /*
              ** If we succeeded then remove the version number and
              ** return a copy of the UNIX format version of the file name.
              */
              if ($VMS_STATUS_SUCCESS(status)) {
                  char *p, *result;
                  file_name[file_name_len] = 0;
                  p = strrchr(file_name,';');
                  if (p) *p = 0;
                  p = decc$translate_vms(&file_name[0]);
                  result = PR_Malloc(strlen(p)+1);
                  if (result != NULL) {
                     strcpy(result, p);
                  }
                  return result;
              }
            }
       }
    }

    /* Didn't find it */
    PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
    return NULL;

#elif defined(HPUX) && defined(USE_HPSHL)
    int index;
    struct shl_descriptor desc;
    char *result;

    for (index = 0; shl_get_r(index, &desc) == 0; index++) {
        if (strstr(desc.filename, name) != NULL) {
            result = PR_Malloc(strlen(desc.filename)+1);
            if (result != NULL) {
                strcpy(result, desc.filename);
            }
            return result;
        }
    }
    /*
     * Since the index value of a library is decremented if
     * a library preceding it in the shared library search
     * list was unloaded, it is possible that we missed some
     * libraries as we went up the list.  So we should go
     * down the list to be sure that we not miss anything.
     */
    for (index--; index >= 0; index--) {
        if ((shl_get_r(index, &desc) == 0)
                && (strstr(desc.filename, name) != NULL)) {
            result = PR_Malloc(strlen(desc.filename)+1);
            if (result != NULL) {
                strcpy(result, desc.filename);
            }
            return result;
        }
    }
    PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
    return NULL;
#elif defined(HPUX) && defined(USE_DLFCN)
    struct load_module_desc desc;
    char *result;
    const char *module_name;

    if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) {
        PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
        return NULL;
    }
    module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0);
    if (module_name == NULL) {
        /* should not happen */
        _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
        return NULL;
    }
    result = PR_Malloc(strlen(module_name)+1);
    if (result != NULL) {
        strcpy(result, module_name);
    }
    return result;
#elif defined(WIN32)
    HMODULE handle;
    char module_name[MAX_PATH];
    char *result;

    handle = GetModuleHandle(name);
    if (handle == NULL) {
        PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
        return NULL;
    }
    if (GetModuleFileName(handle, module_name, sizeof module_name) == 0) {
        /* should not happen */
        _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
        return NULL;
    }
    result = PR_Malloc(strlen(module_name)+1);
    if (result != NULL) {
        strcpy(result, module_name);
    }
    return result;
#elif defined(XP_OS2)
    HMODULE module = NULL;
    char module_name[_MAX_PATH];
    char *result;
    APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr);
    if ((NO_ERROR != ulrc) || (NULL == module) ) {
        PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
        return NULL;
    }
    ulrc = DosQueryModuleName(module, sizeof module_name, module_name);
    if (NO_ERROR != ulrc) {
        /* should not happen */
        _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
        return NULL;
    }
    result = PR_Malloc(strlen(module_name)+1);
    if (result != NULL) {
        strcpy(result, module_name);
    }
    return result;
#else
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return NULL;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_GetLibraryName ( const char *  path,
const char *  lib 
)

Definition at line 494 of file prlink.c.

{
    char *fullname;

#ifdef XP_PC
    if (strstr(lib, PR_DLL_SUFFIX) == NULL)
    {
        if (path) {
            fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
        } else {
            fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX);
        }
    } else {
        if (path) {
            fullname = PR_smprintf("%s\\%s", path, lib);
        } else {
            fullname = PR_smprintf("%s", lib);
        }
    }
#endif /* XP_PC */
#if defined(XP_UNIX) || defined(XP_BEOS)
    if (strstr(lib, PR_DLL_SUFFIX) == NULL)
    {
        if (path) {
            fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX);
        } else {
            fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX);
        }
    } else {
        if (path) {
            fullname = PR_smprintf("%s/%s", path, lib);
        } else {
            fullname = PR_smprintf("%s", lib);
        }
    }
#endif /* XP_UNIX || XP_BEOS */
    return fullname;
}

Here is the caller graph for this function:

Definition at line 420 of file prlink.c.

{
    char *ev;
    char *copy = NULL;  /* a copy of _pr_currentLibPath */

    if (!_pr_initialized) _PR_ImplicitInitialization();
    PR_EnterMonitor(pr_linker_lock);
    if (_pr_currentLibPath != NULL) {
        goto exit;
    }

    /* initialize pr_currentLibPath */

#ifdef XP_PC
    ev = getenv("LD_LIBRARY_PATH");
    if (!ev) {
    ev = ".;\\lib";
    }
    ev = strdup(ev);
#endif

#if defined(XP_UNIX) || defined(XP_BEOS)
#if defined(USE_DLFCN) || defined(USE_MACH_DYLD) || defined(XP_BEOS)
    {
    char *p=NULL;
    int len;

#ifdef XP_BEOS
    ev = getenv("LIBRARY_PATH");
    if (!ev) {
        ev = "%A/lib:/boot/home/config/lib:/boot/beos/system/lib";
    }
#else
    ev = getenv("LD_LIBRARY_PATH");
    if (!ev) {
        ev = "/usr/lib:/lib";
    }
#endif
    len = strlen(ev) + 1;        /* +1 for the null */

    p = (char*) malloc(len);
    if (p) {
        strcpy(p, ev);
    }   /* if (p)  */
    ev = p;
    PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev));

    }
#else
    /* AFAIK there isn't a library path with the HP SHL interface --Rob */
    ev = strdup("");
#endif
#endif

    /*
     * If ev is NULL, we have run out of memory
     */
    _pr_currentLibPath = ev;

  exit:
    if (_pr_currentLibPath) {
        copy = strdup(_pr_currentLibPath);
    }
    PR_ExitMonitor(pr_linker_lock);
    if (!copy) {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    }
    return copy;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 394 of file prlink.c.

Here is the call graph for this function:

PR_LoadLibrary ( const char *  name)

Definition at line 598 of file prlink.c.

{
    PRLibSpec libSpec;

    libSpec.type = PR_LibSpec_Pathname;
    libSpec.value.pathname = name;
    return PR_LoadLibraryWithFlags(libSpec, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRLibrary * pr_LoadLibraryByPathname ( const char *  name,
PRIntn  flags 
) [static]

Definition at line 803 of file prlink.c.

{
    PRLibrary *lm;
    PRLibrary* result = NULL;
    PRInt32 oserr;
#ifdef WIN32
    char utf8name_stack[MAX_PATH];
    char *utf8name_malloc = NULL;
    char *utf8name = utf8name_stack;
    PRUnichar wname_stack[MAX_PATH];
    PRUnichar *wname_malloc = NULL;
    PRUnichar *wname = wname_stack;
    int len;
#endif

    if (!_pr_initialized) _PR_ImplicitInitialization();

    /* See if library is already loaded */
    PR_EnterMonitor(pr_linker_lock);

#ifdef WIN32
    if (flags & PR_LD_PATHW) {
        /* cast back what's cast to |char *| for the argument passing. */
        wname = (LPWSTR) name;
    } else {
        int wlen = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
        if (wlen > MAX_PATH)
            wname = wname_malloc = PR_Malloc(wlen * sizeof(PRUnichar));
        if (wname == NULL ||
            !MultiByteToWideChar(CP_ACP, 0,  name, -1, wname, wlen)) {
            oserr = _MD_ERRNO();
            goto unlock;
        }
    }
    len = pr_ConvertUTF16toUTF8(wname, NULL, 0);
    if (len > MAX_PATH)
        utf8name = utf8name_malloc = PR_Malloc(len);
    if (utf8name == NULL ||
        !pr_ConvertUTF16toUTF8(wname, utf8name, len)) {
        oserr = _MD_ERRNO();
        goto unlock;
    }
    /* the list of loaded library names are always kept in UTF-8 
     * on Win32 platforms */
    result = pr_UnlockedFindLibrary(utf8name);
#else
    result = pr_UnlockedFindLibrary(name);
#endif

    if (result != NULL) goto unlock;

    lm = PR_NEWZAP(PRLibrary);
    if (lm == NULL) {
        oserr = _MD_ERRNO();
        goto unlock;
    }
    lm->staticTable = NULL;

#ifdef XP_OS2  /* Why isn't all this stuff in MD code?! */
    {
        HMODULE h;
        UCHAR pszError[_MAX_PATH];
        ULONG ulRc = NO_ERROR;

          ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h);
          if (ulRc != NO_ERROR) {
              oserr = ulRc;
              PR_DELETE(lm);
              goto unlock;
          }
          lm->name = strdup(name);
          lm->dlh  = h;
          lm->next = pr_loadmap;
          pr_loadmap = lm;
    }
#endif /* XP_OS2 */

#if defined(WIN32) || defined(WIN16)
    {
    HINSTANCE h;

#ifdef WIN32
#ifdef WIN95
    if (flags & PR_LD_PATHW)
        h = loadLibraryW(wname);
    else
        h = LoadLibraryA(name);
#else
    if (flags & PR_LD_PATHW)
        h = LoadLibraryW(wname);
    else
        h = LoadLibraryA(name);
#endif /* WIN95 */
#else 
    h = LoadLibrary(name);
#endif
    if (h < (HINSTANCE)HINSTANCE_ERROR) {
        oserr = _MD_ERRNO();
        PR_DELETE(lm);
        goto unlock;
    }
#ifdef WIN32
    lm->name = strdup(utf8name);
#else
    lm->name = strdup(name);
#endif
    lm->dlh = h;
    lm->next = pr_loadmap;
    pr_loadmap = lm;
    }
#endif /* WIN32 || WIN16 */

#ifdef XP_MACOSX
    {
    int     i;
    PRStatus status;

    static const macLibraryLoadProc loadProcs[] = {
        pr_LoadViaDyld, pr_LoadCFBundle, pr_LoadViaCFM
    };

    for (i = 0; i < sizeof(loadProcs) / sizeof(loadProcs[0]); i++) {
        if ((status = loadProcs[i](name, lm)) == PR_SUCCESS)
            break;
    }
    if (status != PR_SUCCESS) {
        oserr = cfragNoLibraryErr;
        PR_DELETE(lm);
        goto unlock;        
    }
    lm->name = strdup(name);
    lm->next = pr_loadmap;
    pr_loadmap = lm;
    }
#endif

#if defined(XP_UNIX) && !defined(XP_MACOSX)
#ifdef HAVE_DLL
    {
#if defined(USE_DLFCN)
#ifdef NTO
    /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */
    int dl_flags = RTLD_GROUP;
#elif defined(AIX)
    /* AIX needs RTLD_MEMBER to load an archive member.  (bug 228899) */
    int dl_flags = RTLD_MEMBER;
#else
    int dl_flags = 0;
#endif
    void *h;

    if (flags & PR_LD_LAZY) {
        dl_flags |= RTLD_LAZY;
    }
    if (flags & PR_LD_NOW) {
        dl_flags |= RTLD_NOW;
    }
    if (flags & PR_LD_GLOBAL) {
        dl_flags |= RTLD_GLOBAL;
    }
    if (flags & PR_LD_LOCAL) {
        dl_flags |= RTLD_LOCAL;
    }
    h = dlopen(name, dl_flags);
#elif defined(USE_HPSHL)
    int shl_flags = 0;
    shl_t h;

    /*
     * Use the DYNAMIC_PATH flag only if 'name' is a plain file
     * name (containing no directory) to match the behavior of
     * dlopen().
     */
    if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) {
        shl_flags |= DYNAMIC_PATH;
    }
    if (flags & PR_LD_LAZY) {
        shl_flags |= BIND_DEFERRED;
    }
    if (flags & PR_LD_NOW) {
        shl_flags |= BIND_IMMEDIATE;
    }
    /* No equivalent of PR_LD_GLOBAL and PR_LD_LOCAL. */
    h = shl_load(name, shl_flags, 0L);
#elif defined(USE_MACH_DYLD)
    NSModule h = pr_LoadMachDyldModule(name);
#else
#error Configuration error
#endif
    if (!h) {
        oserr = _MD_ERRNO();
        PR_DELETE(lm);
        goto unlock;
    }
    lm->name = strdup(name);
    lm->dlh = h;
    lm->next = pr_loadmap;
    pr_loadmap = lm;
    }
#endif /* HAVE_DLL */
#endif /* XP_UNIX */

    lm->refCount = 1;

#ifdef XP_BEOS
    {
        image_info info;
        int32 cookie = 0;
        image_id imageid = B_ERROR;
        image_id stubid = B_ERROR;
        PRLibrary *p;

        for (p = pr_loadmap; p != NULL; p = p->next) {
            /* hopefully, our caller will always use the same string
               to refer to the same library */
            if (strcmp(name, p->name) == 0) {
                /* we've already loaded this library */
                imageid = info.id;
                lm->refCount++;
                break;
            }
        }

        if(imageid == B_ERROR) {
            /* it appears the library isn't yet loaded - load it now */
            char stubName [B_PATH_NAME_LENGTH + 1];

            /* the following is a work-around to a "bug" in the beos -
               the beos system loader allows only 32M (system-wide)
               to be used by code loaded as "add-ons" (code loaded
               through the 'load_add_on()' system call, which includes
               mozilla components), but allows 256M to be used by
               shared libraries.
               
               unfortunately, mozilla is too large to fit into the
               "add-on" space, so we must trick the loader into
               loading some of the components as shared libraries.  this
               is accomplished by creating a "stub" add-on (an empty
               shared object), and linking it with the component
               (the actual .so file generated by the build process,
               without any modifications).  when this stub is loaded
               by load_add_on(), the loader will automatically load the
               component into the shared library space.
            */

            strcpy(stubName, name);
            strcat(stubName, ".stub");

            /* first, attempt to load the stub (thereby loading the
               component as a shared library */
            if ((stubid = load_add_on(stubName)) > B_ERROR) {
                /* the stub was loaded successfully. */
                imageid = B_FILE_NOT_FOUND;

                cookie = 0;
                while (get_next_image_info(0, &cookie, &info) == B_OK) {
                    const char *endOfSystemName = strrchr(info.name, '/');
                    const char *endOfPassedName = strrchr(name, '/');
                    if( 0 == endOfSystemName ) 
                        endOfSystemName = info.name;
                    else
                        endOfSystemName++;
                    if( 0 == endOfPassedName )
                        endOfPassedName = name;
                    else
                        endOfPassedName++;
                    if (strcmp(endOfSystemName, endOfPassedName) == 0) {
                        /* this is the actual component - remember it */
                        imageid = info.id;
                        break;
                    }
                }

            } else {
                /* we failed to load the "stub" - try to load the
                   component directly as an add-on */
                stubid = B_ERROR;
                imageid = load_add_on(name);
            }
        }

        if (imageid <= B_ERROR) {
            oserr = imageid;
            PR_DELETE( lm );
            goto unlock;
        }
        lm->name = strdup(name);
        lm->dlh = (void*)imageid;
        lm->stub_dlh = (void*)stubid;
        lm->next = pr_loadmap;
        pr_loadmap = lm;
    }
#endif

    result = lm;    /* success */
    PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name));

  unlock:
    if (result == NULL) {
        PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr);
        DLLErrorInternal(oserr);  /* sets error text */
    }
#ifdef WIN32
    if (utf8name_malloc) 
        PR_Free(utf8name_malloc);
    if (wname_malloc)
        PR_Free(wname_malloc);
#endif
    PR_ExitMonitor(pr_linker_lock);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_LoadLibraryWithFlags ( PRLibSpec  libSpec,
PRIntn  flags 
)

Definition at line 573 of file prlink.c.

{
    if (flags == 0) {
        flags = _PR_DEFAULT_LD_FLAGS;
    }
    switch (libSpec.type) {
        case PR_LibSpec_Pathname:
            return pr_LoadLibraryByPathname(libSpec.value.pathname, flags);
#ifdef WIN32
        case PR_LibSpec_PathnameU:
            /*
             * cast to |char *| and set PR_LD_PATHW flag so that
             * it can be cast back to PRUnichar* in the callee.
             */
            return pr_LoadLibraryByPathname((const char*) 
                                            libSpec.value.pathname_u, 
                                            flags | PR_LD_PATHW);
#endif
        default:
            PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
            return NULL;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_LoadStaticLibrary ( const char *  name,
const PRStaticLinkTable slt 
)

Definition at line 1569 of file prlink.c.

{
    PRLibrary *lm=NULL;
    PRLibrary* result = NULL;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    /* See if library is already loaded */
    PR_EnterMonitor(pr_linker_lock);

    /* If the lbrary is already loaded, then add the static table information... */
    result = pr_UnlockedFindLibrary(name);
    if (result != NULL) {
        PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) );
        result->staticTable = slt;
        goto unlock;
    }

    /* Add library to list...Mark it static */
    lm = PR_NEWZAP(PRLibrary);
    if (lm == NULL) goto unlock;

    lm->name = strdup(name);
    lm->refCount    = 1;
    lm->dlh         = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0;
    lm->staticTable = slt;
    lm->next        = pr_loadmap;
    pr_loadmap      = lm;

    result = lm;    /* success */
    PR_ASSERT(lm->refCount == 1);
  unlock:
    PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->name));
    PR_ExitMonitor(pr_linker_lock);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1238 of file prlink.c.

{
    int result = 0;
    PRStatus status = PR_SUCCESS;

    if ((lib == 0) || (lib->refCount <= 0)) {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return PR_FAILURE;
    }

    PR_EnterMonitor(pr_linker_lock);
    if (--lib->refCount > 0) {
    PR_LOG(_pr_linker_lm, PR_LOG_MIN,
           ("%s decr => %d",
        lib->name, lib->refCount));
    goto done;
    }

#ifdef XP_BEOS
    if(((image_id)lib->stub_dlh) == B_ERROR)
        unload_add_on( (image_id) lib->dlh );
    else
        unload_add_on( (image_id) lib->stub_dlh);
#endif

#ifdef XP_UNIX
#ifdef HAVE_DLL
#ifdef USE_DLFCN
    result = dlclose(lib->dlh);
#elif defined(USE_HPSHL)
    result = shl_unload(lib->dlh);
#elif defined(USE_MACH_DYLD)
    if (lib->dlh)
        result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1;
#else
#error Configuration error
#endif
#endif /* HAVE_DLL */
#endif /* XP_UNIX */
#ifdef XP_PC
    if (lib->dlh) {
        FreeLibrary((HINSTANCE)(lib->dlh));
        lib->dlh = (HINSTANCE)NULL;
    }
#endif  /* XP_PC */

#ifdef XP_MACOSX
    /* Close the connection */
    if (lib->connection)
        CloseConnection(&(lib->connection));
    if (lib->bundle)
        CFRelease(lib->bundle);
    if (lib->wrappers)
        CFRelease(lib->wrappers);
    /* No way to unload an image (lib->image) */
#endif

    /* unlink from library search list */
    if (pr_loadmap == lib)
        pr_loadmap = pr_loadmap->next;
    else if (pr_loadmap != NULL) {
        PRLibrary* prev = pr_loadmap;
        PRLibrary* next = pr_loadmap->next;
        while (next != NULL) {
            if (next == lib) {
                prev->next = next->next;
                goto freeLib;
            }
            prev = next;
            next = next->next;
        }
        /*
         * fail (the library is not on the _pr_loadmap list),
         * but don't wipe out an error from dlclose/shl_unload.
         */
        PR_ASSERT(!"_pr_loadmap and lib->refCount inconsistent");
        if (result == 0) {
            PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
            status = PR_FAILURE;
        }
    }
    /*
     * We free the PRLibrary structure whether dlclose/shl_unload
     * succeeds or not.
     */

  freeLib:
    PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
    free(lib->name);
    lib->name = NULL;
    PR_DELETE(lib);
    if (result != 0) {
        PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
        DLLErrorInternal(_MD_ERRNO());
        status = PR_FAILURE;
    }

done:
    PR_ExitMonitor(pr_linker_lock);
    return status;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRLibrary* pr_UnlockedFindLibrary ( const char *  name) [static]

Definition at line 543 of file prlink.c.

{
    PRLibrary* lm = pr_loadmap;
    const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR);
    np = np ? np + 1 : name;
    while (lm) {
    const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
    cp = cp ? cp + 1 : lm->name;
#ifdef WIN32
        /* Windows DLL names are case insensitive... */
    if (strcmpi(np, cp) == 0) 
#elif defined(XP_OS2)
    if (stricmp(np, cp) == 0)
#else
    if (strcmp(np, cp)  == 0) 
#endif
    {
        /* found */
        lm->refCount++;
        PR_LOG(_pr_linker_lm, PR_LOG_MIN,
           ("%s incr => %d (find lib)",
            lm->name, lm->refCount));
        return lm;
    }
    lm = lm->next;
    }
    return NULL;
}

Here is the caller graph for this function:


Variable Documentation

char* _pr_currentLibPath = NULL [static]

Definition at line 209 of file prlink.c.

char* errStrBuf = NULL [static]

Definition at line 226 of file prlink.c.

Definition at line 207 of file prlink.c.

Definition at line 208 of file prlink.c.

PRLibrary* pr_loadmap [static]

Definition at line 206 of file prlink.c.