diff --git a/nsprpub/pr/include/prlink.h b/nsprpub/pr/include/prlink.h index f18befa3ea00..df1d8f8c9dc3 100644 --- a/nsprpub/pr/include/prlink.h +++ b/nsprpub/pr/include/prlink.h @@ -85,6 +85,74 @@ PR_EXTERN(void) PR_FreeLibraryName(char *mem); */ PR_EXTERN(PRLibrary*) PR_LoadLibrary(const char *name); +/* +** Each operating system has its preferred way of specifying +** a file in the file system. Most operating systems use +** a pathname. Mac OS, on the other hand, uses the FSSpec +** structure to specify a file. PRLibSpec allows NSPR clients +** to use the type of file specification that is most efficient +** for a particular platform. +** +** On some operating systems such as Mac OS, a shared library may +** contain code fragments that can be individually loaded. +** PRLibSpec also allows NSPR clients to identify a code fragment +** in a library, if code fragments are supported by the OS. +** A code fragment can be specified by name or by an integer index. +** +** Right now PRLibSpec supports three types of library specification: +** a pathname, a Mac code fragment by name, and a Mac code fragment +** by index. +*/ + +typedef enum PRLibSpecType { + PR_LibSpec_Pathname, + PR_LibSpec_MacNamedFragment, + PR_LibSpec_MacIndexedFragment +} PRLibSpecType; + +struct FSSpec; /* Mac OS FSSpec */ + +typedef struct PRLibSpec { + PRLibSpecType type; + union { + /* if type is PR_LibSpec_Pathname */ + const char *pathname; + + /* if type is PR_LibSpec_MacNamedFragment */ + struct { + const struct FSSpec *fsspec; + const char *name; + } mac_named_fragment; + + /* if type is PR_LibSpec_MacIndexedFragment */ + struct { + const struct FSSpec *fsspec; + PRUint32 index; + } mac_indexed_fragment; + } value; +} PRLibSpec; + +/* +** The following bit flags may be or'd together and passed +** as the 'flags' argument to PR_LoadLibraryWithFlags. +** Flags not supported by the underlying OS are ignored. +*/ + +#define PR_LD_LAZY 0x1 /* equivalent to RTLD_LAZY on Unix */ +#define PR_LD_NOW 0x2 /* equivalent to RTLD_NOW on Unix */ +#define PR_LD_GLOBAL 0x4 /* equivalent to RTLD_GLOBAL on Unix */ +#define PR_LD_LOCAL 0x8 /* equivalent to RTLD_LOCAL on Unix */ + +/* +** Load the specified library, in the manner specified by 'flags'. +*/ + +PR_EXTERN(PRLibrary *) +PR_LoadLibraryWithFlags( + PRLibSpec libSpec, /* the shared library */ + PRIntn flags /* flags that affect the loading */ +); + /* ** Unload a previously loaded library. If the library was a static ** library then the static link table will no longer be referenced. The diff --git a/nsprpub/pr/src/linking/prlink.c b/nsprpub/pr/src/linking/prlink.c index bbf50190e67b..1a299843149d 100644 --- a/nsprpub/pr/src/linking/prlink.c +++ b/nsprpub/pr/src/linking/prlink.c @@ -39,11 +39,6 @@ #ifdef XP_UNIX #ifdef USE_DLFCN #include -#ifdef LINUX -#define _PR_DLOPEN_FLAGS RTLD_NOW -#else -#define _PR_DLOPEN_FLAGS RTLD_LAZY -#endif /* LINUX */ #elif defined(USE_HPSHL) #include #elif defined(USE_MACH_DYLD) @@ -56,6 +51,8 @@ #endif #endif /* XP_UNIX */ +#define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY + /* * On these platforms, symbols have a leading '_'. */ @@ -103,6 +100,14 @@ static PRLibrary *pr_exe_loadmap; static PRMonitor *pr_linker_lock; static char* _pr_currentLibPath = NULL; +static PRLibrary *pr_LoadLibraryByPathname(const char *name, PRIntn flags); +#ifdef XP_MAC +static PRLibrary *pr_Mac_LoadNamedFragment(const FSSpec *fileSpec, + const char* fragmentName); +static PRLibrary *pr_Mac_LoadIndexedFragment(const FSSpec *fileSpec, + PRUint32 fragIndex); +#endif /* XP_MAC */ + /************************************************************************/ #if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) @@ -174,7 +179,7 @@ void _PR_InitLinker(void) #elif defined(XP_UNIX) #ifdef HAVE_DLL #ifdef USE_DLFCN - h = dlopen(0, _PR_DLOPEN_FLAGS ); + h = dlopen(0, RTLD_LAZY); if (!h) { char *error; @@ -417,12 +422,47 @@ pr_UnlockedFindLibrary(const char *name) return NULL; } +PR_IMPLEMENT(PRLibrary*) +PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags) +{ + if (flags == 0) { + flags = _PR_DEFAULT_LD_FLAGS; + } + switch (libSpec.type) { + case PR_LibSpec_Pathname: + return pr_LoadLibraryByPathname(libSpec.value.pathname, flags); +#ifdef XP_MAC + case PR_LibSpec_MacNamedFragment: + return pr_Mac_LoadNamedFragment( + libSpec.value.mac_named_fragment.fsspec, + libSpec.value.mac_named_fragment.name); + case PR_LibSpec_MacIndexedFragment: + return pr_Mac_LoadIndexedFragment( + libSpec.value.mac_indexed_fragment.fsspec, + libSpec.value.mac_indexed_fragment.index); +#endif /* XP_MAC */ + default: + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return NULL; + } +} + +PR_IMPLEMENT(PRLibrary*) +PR_LoadLibrary(const char *name) +{ + PRLibSpec libSpec; + + libSpec.type = PR_LibSpec_Pathname; + libSpec.value.pathname = name; + return PR_LoadLibraryWithFlags(libSpec, 0); +} + /* ** Dynamically load a library. Only load libraries once, so scan the load ** map first. */ -PR_IMPLEMENT(PRLibrary*) -PR_LoadLibrary(const char *name) +static PRLibrary* +pr_LoadLibraryByPathname(const char *name, PRIntn flags) { PRLibrary *lm; PRLibrary* result; @@ -647,9 +687,34 @@ PR_LoadLibrary(const char *name) #ifdef HAVE_DLL { #if defined(USE_DLFCN) - void *h = dlopen(name, _PR_DLOPEN_FLAGS ); + int dl_flags = 0; + 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) - shl_t h = shl_load(name, BIND_DEFERRED | DYNAMIC_PATH, 0L); + int shl_flags = DYNAMIC_PATH; + shl_t h; + + 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) NSObjectFileImage ofi; NSModule h = NULL; @@ -731,6 +796,17 @@ PR_FindLibrary(const char *name) PR_IMPLEMENT(PRLibrary*) PR_LoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName) +{ + PRLibSpec libSpec; + + libSpec.type = PR_LibSpec_MacNamedFragment; + libSpec.value.mac_named_fragment.fsspec = fileSpec; + libSpec.value.mac_named_fragment.name = fragmentName; + return PR_LoadLibraryWithFlags(libSpec, 0); +} + +static PRLibrary* +pr_Mac_LoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName) { PRLibrary* newLib = NULL; PRLibrary* result; @@ -788,6 +864,17 @@ unlock: PR_EXTERN(PRLibrary*) PR_LoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragIndex) +{ + PRLibSpec libSpec; + + libSpec.type = PR_LibSpec_MacIndexedFragment; + libSpec.value.mac_indexed_fragment.fsspec = fileSpec; + libSpec.value.mac_indexed_fragment.index = fragIndex; + return PR_LoadLibraryWithFlags(libSpec, 0); +} + +static PRLibrary* +pr_Mac_LoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragIndex) { PRLibrary* newLib = NULL; PRLibrary* result;