diff options
author | wtc%netscape.com <devnull@localhost> | 2003-01-20 20:10:39 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2003-01-20 20:10:39 +0000 |
commit | 8a8687fd4ed58964231134923b07c8a6742d21c8 (patch) | |
tree | 3615221ceab4bcbfe569f544fe4b0d01e35009f0 | |
parent | 7dab13095b4b0fdad24d50fb8ff6072d779814ea (diff) | |
download | nspr-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.h | 5 | ||||
-rw-r--r-- | pr/include/prlink.h | 8 | ||||
-rw-r--r-- | pr/src/linking/Makefile.in | 5 | ||||
-rw-r--r-- | pr/src/linking/prlink.c | 255 | ||||
-rw-r--r-- | pr/src/misc/compile-et.pl | 2 | ||||
-rw-r--r-- | pr/src/misc/prerr.c | 3 | ||||
-rw-r--r-- | pr/src/misc/prerr.et | 1 | ||||
-rw-r--r-- | pr/src/misc/prerr.properties | 2 | ||||
-rw-r--r-- | pr/src/nspr.def | 5 | ||||
-rw-r--r-- | pr/tests/Makefile.in | 1 | ||||
-rwxr-xr-x | pr/tests/runtests.ksh | 1 | ||||
-rwxr-xr-x | pr/tests/runtests.sh | 1 |
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, ®info, + 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 |