Bugzilla bug #16845: added new function PR_LoadLibraryWithFlags.

Also, use RTLD_LAZY on Linux (was using RTLD_NOW).
Modified files: prlink.h, prlink.c.
This commit is contained in:
wtc%netscape.com 1999-11-13 01:27:06 +00:00
parent 3bba682ce9
commit 4bd1fc48f2
2 changed files with 165 additions and 10 deletions

View File

@ -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

View File

@ -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;
@ -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;