summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>2003-01-20 20:10:39 +0000
committerwtc%netscape.com <devnull@localhost>2003-01-20 20:10:39 +0000
commit8a8687fd4ed58964231134923b07c8a6742d21c8 (patch)
tree3615221ceab4bcbfe569f544fe4b0d01e35009f0
parent7dab13095b4b0fdad24d50fb8ff6072d779814ea (diff)
downloadnspr-hg-8a8687fd4ed58964231134923b07c8a6742d21c8.tar.gz
Bug 189332: Implemented the new function PR_GetLibraryFilePathname for
AIX, HP-UX, Linux, Mac OS X, OSF1, Solaris, and Windows. Added the new error code PR_LIBRARY_NOT_LOADED_ERROR for the error condition that the library specified by "name" and "addr" is not loaded. Added a new test, libfilename.c. Extended the PR_GetLibraryName function to not prepend any directory if the first argument "dir" is NULL. The OSF1 implementation was contributed by Steve Streeter <Stephen.Streeter@hp.com>. Modified files: prerr.h prlink.h nspr.def pr/src/linking/Makefile.in prlink.c compile-et.pl prerr.c prerr.et prerr.properties pr/tests/Makefile.in runtests.ksh runtests.sh Added file: pr/tests/libfilename.c Tag: NSPRPUB_PRE_4_2_CLIENT_BRANCH
-rw-r--r--pr/include/prerr.h5
-rw-r--r--pr/include/prlink.h8
-rw-r--r--pr/src/linking/Makefile.in5
-rw-r--r--pr/src/linking/prlink.c255
-rw-r--r--pr/src/misc/compile-et.pl2
-rw-r--r--pr/src/misc/prerr.c3
-rw-r--r--pr/src/misc/prerr.et1
-rw-r--r--pr/src/misc/prerr.properties2
-rw-r--r--pr/src/nspr.def5
-rw-r--r--pr/tests/Makefile.in1
-rwxr-xr-xpr/tests/runtests.ksh1
-rwxr-xr-xpr/tests/runtests.sh1
12 files changed, 279 insertions, 10 deletions
diff --git a/pr/include/prerr.h b/pr/include/prerr.h
index 530526b6..5bb6c9e8 100644
--- a/pr/include/prerr.h
+++ b/pr/include/prerr.h
@@ -263,8 +263,11 @@
/* Host is unreachable */
#define PR_HOST_UNREACHABLE_ERROR (-5927L)
+/* The library is not loaded */
+#define PR_LIBRARY_NOT_LOADED_ERROR (-5926L)
+
/* Placeholder for the end of the list */
-#define PR_MAX_ERROR (-5926L)
+#define PR_MAX_ERROR (-5925L)
extern void nspr_InitializePRErrorTable(void);
#define ERROR_TABLE_BASE_nspr (-6000L)
diff --git a/pr/include/prlink.h b/pr/include/prlink.h
index 3787a369..5ccd25f1 100644
--- a/pr/include/prlink.h
+++ b/pr/include/prlink.h
@@ -239,6 +239,14 @@ NSPR_API(PRFuncPtr) PR_FindFunctionSymbolAndLibrary(const char *name,
NSPR_API(PRLibrary*) PR_LoadStaticLibrary(
const char *name, const PRStaticLinkTable *table);
+/*
+** Return the pathname of the file that the library "name" was loaded
+** from. "addr" is the address of a function defined in the library.
+**
+** The caller is responsible for freeing the result with PR_Free.
+*/
+NSPR_API(char *) PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr);
+
PR_END_EXTERN_C
#endif /* prlink_h___ */
diff --git a/pr/src/linking/Makefile.in b/pr/src/linking/Makefile.in
index 79b464a4..d997ccba 100644
--- a/pr/src/linking/Makefile.in
+++ b/pr/src/linking/Makefile.in
@@ -58,6 +58,11 @@ TARGETS = $(OBJS)
INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+# For Dl_info and dladdr.
+ifeq ($(OS_TARGET),Linux)
+DEFINES += -D_GNU_SOURCE
+endif
+
# On Mac OS X use flat #includes.
ifeq ($(OS_TARGET),MacOSX)
INCLUDES += -I/Developer/Headers/FlatCarbon
diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c
index c34454e8..6b9f94a4 100644
--- a/pr/src/linking/prlink.c
+++ b/pr/src/linking/prlink.c
@@ -17,7 +17,7 @@
* Copyright (C) 1998-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
- * Contributor(s):
+ * Contributor(s): Steve Streeter (Hewlett-Packard Company)
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
@@ -78,6 +78,13 @@
#ifndef RTLD_LOCAL
#define RTLD_LOCAL 0
#endif
+#ifdef AIX
+#include <sys/ldr.h>
+#endif
+#ifdef OSF1
+#include <loader.h>
+#include <rld_interface.h>
+#endif
#elif defined(USE_HPSHL)
#include <dl.h>
#elif defined(USE_MACH_DYLD)
@@ -451,20 +458,40 @@ PR_GetLibraryName(const char *path, const char *lib)
#ifdef XP_PC
if (strstr(lib, PR_DLL_SUFFIX) == NULL)
{
- fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
+ if (path) {
+ fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
+ } else {
+ fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX);
+ }
} else {
- fullname = PR_smprintf("%s\\%s", path, lib);
+ if (path) {
+ fullname = PR_smprintf("%s\\%s", path, lib);
+ } else {
+ fullname = PR_smprintf("%s", lib);
+ }
}
#endif /* XP_PC */
#ifdef XP_MAC
- fullname = PR_smprintf("%s%s", path, lib);
+ if (path) {
+ fullname = PR_smprintf("%s%s", path, lib);
+ } else {
+ fullname = PR_smprintf("%s", lib);
+ }
#endif
#if defined(XP_UNIX) || defined(XP_BEOS)
if (strstr(lib, PR_DLL_SUFFIX) == NULL)
{
- fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX);
+ 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 {
- fullname = PR_smprintf("%s/%s", path, lib);
+ if (path) {
+ fullname = PR_smprintf("%s/%s", path, lib);
+ } else {
+ fullname = PR_smprintf("%s", lib);
+ }
}
#endif /* XP_UNIX || XP_BEOS */
return fullname;
@@ -1571,3 +1598,219 @@ PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt)
PR_ExitMonitor(pr_linker_lock);
return result;
}
+
+PR_IMPLEMENT(char *)
+PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr)
+{
+#if defined(SOLARIS) || defined(LINUX)
+ 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;
+
+ for (;;) {
+ info = PR_Malloc(info_length);
+ if (info == NULL) {
+ return NULL;
+ }
+ /* If buffer is too small, loadquery fails with ENOMEM. */
+ if (loadquery(L_GETINFO, 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)) {
+ if (strstr(infop->ldinfo_filename, name) != NULL) {
+ 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(HPUX) && defined(USE_HPSHL)
+ shl_t handle;
+ struct shl_descriptor desc;
+ char *result;
+
+ handle = shl_load(name, DYNAMIC_PATH, 0L);
+ if (handle == NULL) {
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ return NULL;
+ }
+ if (shl_gethandle_r(handle, &desc) == -1) {
+ /* should not happen */
+ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
+ return NULL;
+ }
+ result = PR_Malloc(strlen(desc.filename)+1);
+ if (result != NULL) {
+ strcpy(result, desc.filename);
+ }
+ return result;
+#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;
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+#endif
+}
diff --git a/pr/src/misc/compile-et.pl b/pr/src/misc/compile-et.pl
index c1c55dd7..8fafcb7b 100644
--- a/pr/src/misc/compile-et.pl
+++ b/pr/src/misc/compile-et.pl
@@ -129,7 +129,7 @@ print C "};\n\n";
printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n",
$base, $table_base, $table_item_count;
print C "\n";
-print C "void ", $table_name, "_InitializePRErrorTable", "() {\n";
+print C "void ", $table_name, "_InitializePRErrorTable", "(void) {\n";
print C " PR_ErrorInstallTable(&et);\n";
print C "}\n";
diff --git a/pr/src/misc/prerr.c b/pr/src/misc/prerr.c
index be24aff7..aaa1c38b 100644
--- a/pr/src/misc/prerr.c
+++ b/pr/src/misc/prerr.c
@@ -113,11 +113,12 @@ static const struct PRErrorMessage text[] = {
{"PR_SOCKET_SHUTDOWN_ERROR", "Socket shutdown"},
{"PR_CONNECT_ABORTED_ERROR", "Connection aborted"},
{"PR_HOST_UNREACHABLE_ERROR", "Host is unreachable"},
+ {"PR_LIBRARY_NOT_LOADED_ERROR", "The library is not loaded"},
{"PR_MAX_ERROR", "Placeholder for the end of the list"},
{0, 0}
};
-static const struct PRErrorTable et = { text, "prerr", -6000L, 75 };
+static const struct PRErrorTable et = { text, "prerr", -6000L, 76 };
void nspr_InitializePRErrorTable(void) {
PR_ErrorInstallTable(&et);
diff --git a/pr/src/misc/prerr.et b/pr/src/misc/prerr.et
index e7e21305..9281ee6e 100644
--- a/pr/src/misc/prerr.et
+++ b/pr/src/misc/prerr.et
@@ -128,6 +128,7 @@ ec PR_NETWORK_DOWN_ERROR, "Network is down"
ec PR_SOCKET_SHUTDOWN_ERROR, "Socket shutdown"
ec PR_CONNECT_ABORTED_ERROR, "Connection aborted"
ec PR_HOST_UNREACHABLE_ERROR, "Host is unreachable"
+ec PR_LIBRARY_NOT_LOADED_ERROR, "The library is not loaded"
ec PR_MAX_ERROR, "Placeholder for the end of the list"
diff --git a/pr/src/misc/prerr.properties b/pr/src/misc/prerr.properties
index 652545e0..f6f0db26 100644
--- a/pr/src/misc/prerr.properties
+++ b/pr/src/misc/prerr.properties
@@ -32,7 +32,6 @@
#
#
-#
# prerr.properties
# This file is automatically generated; please do not edit it.
PR_OUT_OF_MEMORY_ERROR=Memory allocation attempt failed
@@ -109,4 +108,5 @@ PR_NETWORK_DOWN_ERROR=Network is down
PR_SOCKET_SHUTDOWN_ERROR=Socket shutdown
PR_CONNECT_ABORTED_ERROR=Connection aborted
PR_HOST_UNREACHABLE_ERROR=Host is unreachable
+PR_LIBRARY_NOT_LOADED_ERROR=The library is not loaded
PR_MAX_ERROR=Placeholder for the end of the list
diff --git a/pr/src/nspr.def b/pr/src/nspr.def
index 6d4b9c68..75f3f890 100644
--- a/pr/src/nspr.def
+++ b/pr/src/nspr.def
@@ -389,3 +389,8 @@ NSPR_4.1 {
PR_ImportPipe;
PR_SetEnv;
} NSPR_4.0;
+
+NSPR_4.3 {
+ global:
+ PR_GetLibraryFilePathname;
+} NSPR_4.1;
diff --git a/pr/tests/Makefile.in b/pr/tests/Makefile.in
index a2def4c3..a1b7c686 100644
--- a/pr/tests/Makefile.in
+++ b/pr/tests/Makefile.in
@@ -94,6 +94,7 @@ CSRCS = \
joinuu.c \
layer.c \
lazyinit.c \
+ libfilename.c \
lltest.c \
lock.c \
lockfile.c \
diff --git a/pr/tests/runtests.ksh b/pr/tests/runtests.ksh
index aecd42ab..52b1186a 100755
--- a/pr/tests/runtests.ksh
+++ b/pr/tests/runtests.ksh
@@ -132,6 +132,7 @@ joinuk
joinuu
layer
lazyinit
+libfilename
lltest
lock
lockfile
diff --git a/pr/tests/runtests.sh b/pr/tests/runtests.sh
index ceba4559..4024e9cb 100755
--- a/pr/tests/runtests.sh
+++ b/pr/tests/runtests.sh
@@ -132,6 +132,7 @@ joinuk
joinuu
layer
lazyinit
+libfilename
lltest
lock
lockfile