summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>1999-11-13 01:27:06 +0000
committerwtc%netscape.com <devnull@localhost>1999-11-13 01:27:06 +0000
commitcc28422f8c726bb37a5f3b92cc8a3a6b01ec74b2 (patch)
tree3bc59359e5ed2e6ba639302a23a425a1824fd6ac
parentf5dde81589c7dd84db9df8d00942650b592944fc (diff)
downloadnspr-hg-cc28422f8c726bb37a5f3b92cc8a3a6b01ec74b2.tar.gz
Bugzilla bug #16845: added new function PR_LoadLibraryWithFlags.
Also, use RTLD_LAZY on Linux (was using RTLD_NOW). Modified files: prlink.h, prlink.c.
-rw-r--r--pr/include/prlink.h68
-rw-r--r--pr/src/linking/prlink.c107
2 files changed, 165 insertions, 10 deletions
diff --git a/pr/include/prlink.h b/pr/include/prlink.h
index f18befa3..df1d8f8c 100644
--- a/pr/include/prlink.h
+++ b/pr/include/prlink.h
@@ -86,6 +86,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
** associated PRLibrary object is freed.
diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c
index bbf50190..1a299843 100644
--- a/pr/src/linking/prlink.c
+++ b/pr/src/linking/prlink.c
@@ -39,11 +39,6 @@
#ifdef XP_UNIX
#ifdef USE_DLFCN
#include <dlfcn.h>
-#ifdef LINUX
-#define _PR_DLOPEN_FLAGS RTLD_NOW
-#else
-#define _PR_DLOPEN_FLAGS RTLD_LAZY
-#endif /* LINUX */
#elif defined(USE_HPSHL)
#include <dl.h>
#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;
@@ -732,6 +797,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;
FSSpec resolvedSpec = *fileSpec;
@@ -789,6 +865,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;
FSSpec resolvedSpec = *fileSpec;