📄 prlink.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "primpl.h"#include <string.h>#ifdef XP_BEOS#include <image.h>#endif#ifdef XP_MAC#include <CodeFragments.h>#include <TextUtils.h>#include <Types.h>#include <Strings.h>#include <Aliases.h>#if TARGET_CARBON#include <CFURL.h>#include <CFBundle.h>#include <CFString.h>#endif#include "macdll.h"#include "mdmac.h"#endif#ifdef XP_UNIX#ifdef USE_DLFCN#include <dlfcn.h>/* Define these on systems that don't have them. */#ifndef RTLD_NOW#define RTLD_NOW 0#endif#ifndef RTLD_LAZY#define RTLD_LAZY RTLD_NOW#endif#ifndef RTLD_GLOBAL#define RTLD_GLOBAL 0#endif#ifndef RTLD_LOCAL#define RTLD_LOCAL 0#endif#elif defined(USE_HPSHL)#include <dl.h>#elif defined(USE_MACH_DYLD)#include <mach-o/dyld.h>#endif#endif /* XP_UNIX */#define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY/* * On these platforms, symbols have a leading '_'. */#if defined(SUNOS4) || defined(DARWIN) || defined(NEXTSTEP) \ || defined(OPENBSD) || defined(WIN16) \ || (defined(NETBSD) && !defined(__ELF__))#define NEED_LEADING_UNDERSCORE#endif#ifdef XP_PCtypedef PRStaticLinkTable *NODL_PROC(void);#endif/************************************************************************/struct PRLibrary { char* name; /* Our own copy of the name string */ PRLibrary* next; int refCount; const PRStaticLinkTable* staticTable;#ifdef XP_PC#ifdef XP_OS2 HMODULE dlh;#else HINSTANCE dlh;#endif#endif#ifdef XP_MAC CFragConnectionID dlh;#if TARGET_CARBON CFBundleRef bundle;#endif Ptr main;#endif#ifdef XP_UNIX#if defined(USE_HPSHL) shl_t dlh;#elif defined(USE_MACH_DYLD) NSModule dlh;#else void* dlh;#endif #endif #ifdef XP_BEOS void* dlh; void* stub_dlh;#endif};static PRLibrary *pr_loadmap;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_MACstatic 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)static char* errStrBuf = NULL;#define ERR_STR_BUF_LENGTH 20static char* errno_string(PRIntn oserr){ if (errStrBuf == NULL) errStrBuf = PR_MALLOC(ERR_STR_BUF_LENGTH); PR_snprintf(errStrBuf, ERR_STR_BUF_LENGTH, "error %d", oserr); return errStrBuf;}#endifstatic void DLLErrorInternal(PRIntn oserr)/*** This whole function, and most of the code in this file, are run** with a big hairy lock wrapped around it. Not the best of situations,** but will eventually come up with the right answer.*/{ const char *error = NULL;#ifdef USE_DLFCN error = dlerror(); /* $$$ That'll be wrong some of the time - AOF */#elif defined(HAVE_STRERROR) error = strerror(oserr); /* this should be okay */#else error = errno_string(oserr);#endif if (NULL != error) PR_SetErrorText(strlen(error), error);} /* DLLErrorInternal */void _PR_InitLinker(void){#ifndef XP_MAC PRLibrary *lm;#endif#if defined(XP_UNIX) void *h;#endif if (!pr_linker_lock) { pr_linker_lock = PR_NewNamedMonitor("linker-lock"); } PR_EnterMonitor(pr_linker_lock);#if defined(XP_PC) lm = PR_NEWZAP(PRLibrary); lm->name = strdup("Executable"); /* ** In WIN32, GetProcAddress(...) expects a module handle in order to ** get exported symbols from the executable... ** ** However, in WIN16 this is accomplished by passing NULL to ** GetProcAddress(...) */#if defined(_WIN32) lm->dlh = GetModuleHandle(NULL);#else lm->dlh = (HINSTANCE)NULL;#endif /* ! _WIN32 */ lm->refCount = 1; lm->staticTable = NULL; pr_exe_loadmap = lm; pr_loadmap = lm;#elif defined(XP_UNIX)#ifdef HAVE_DLL#ifdef USE_DLFCN h = dlopen(0, RTLD_LAZY); if (!h) { char *error; DLLErrorInternal(_MD_ERRNO()); error = (char*)PR_MALLOC(PR_GetErrorTextLength()); (void) PR_GetErrorText(error); fprintf(stderr, "failed to initialize shared libraries [%s]\n", error); PR_DELETE(error); abort();/* XXX */ }#elif defined(USE_HPSHL) h = NULL; /* don't abort with this NULL */#elif defined(USE_MACH_DYLD) h = NULL; /* XXXX toshok */#else#error no dll strategy#endif /* USE_DLFCN */ lm = PR_NEWZAP(PRLibrary); if (lm) { lm->name = strdup("a.out"); lm->refCount = 1; lm->dlh = h; lm->staticTable = NULL; } pr_exe_loadmap = lm; pr_loadmap = lm;#endif /* HAVE_DLL */#endif /* XP_UNIX */#ifndef XP_MAC PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (init)", lm?lm->name:"NULL"));#endif PR_ExitMonitor(pr_linker_lock);}#if defined(WIN16)/* * _PR_ShutdownLinker unloads all dlls loaded by the application via * calls to PR_LoadLibrary */void _PR_ShutdownLinker(void){ PR_EnterMonitor(pr_linker_lock); while (pr_loadmap) { if (pr_loadmap->refCount > 1) {#ifdef DEBUG fprintf(stderr, "# Forcing library to unload: %s (%d outstanding references)\n", pr_loadmap->name, pr_loadmap->refCount);#endif pr_loadmap->refCount = 1; } PR_UnloadLibrary(pr_loadmap); } PR_ExitMonitor(pr_linker_lock); PR_DestroyMonitor(pr_linker_lock); pr_linker_lock = NULL;}#else/* * _PR_ShutdownLinker was originally only used on WIN16 (see above), * but I think it should also be used on other platforms. However, * I disagree with the original implementation's unloading the dlls * for the application. Any dlls that still remain on the pr_loadmap * list when NSPR shuts down are application programming errors. The * only exception is pr_exe_loadmap, which was added to the list by * NSPR and hence should be cleaned up by NSPR. */void _PR_ShutdownLinker(void){ /* FIXME: pr_exe_loadmap should be destroyed. */ PR_DestroyMonitor(pr_linker_lock); pr_linker_lock = NULL; if (_pr_currentLibPath) { free(_pr_currentLibPath); _pr_currentLibPath = NULL; }#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) PR_DELETE(errStrBuf);#endif}#endif/******************************************************************************/PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path){ PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); if (_pr_currentLibPath) { free(_pr_currentLibPath); } if (path) { _pr_currentLibPath = strdup(path); if (!_pr_currentLibPath) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); rv = PR_FAILURE; } } else { _pr_currentLibPath = 0; } PR_ExitMonitor(pr_linker_lock); return rv;}/*** Return the library path for finding shared libraries.*/PR_IMPLEMENT(char *) PR_GetLibraryPath(void){ char *ev; char *copy = NULL; /* a copy of _pr_currentLibPath */ if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); if (_pr_currentLibPath != NULL) { goto exit; } /* initialize pr_currentLibPath */#ifdef XP_PC ev = getenv("LD_LIBRARY_PATH"); if (!ev) { ev = ".;\\lib"; } ev = strdup(ev);#endif#ifdef XP_MAC { char *p; int len; ev = getenv("LD_LIBRARY_PATH"); if (!ev) ev = ""; len = strlen(ev) + 1; /* +1 for the null */ p = (char*) malloc(len); if (p) { strcpy(p, ev); } ev = p; }#endif#if defined(XP_UNIX) || defined(XP_BEOS)#if defined(USE_DLFCN) || defined(USE_MACH_DYLD) || defined(XP_BEOS) { char *p=NULL; int len;#ifdef XP_BEOS ev = getenv("LIBRARY_PATH"); if (!ev) { ev = "%A/lib:/boot/home/config/lib:/boot/beos/system/lib"; }#else ev = getenv("LD_LIBRARY_PATH"); if (!ev) { ev = "/usr/lib:/lib"; }#endif len = strlen(ev) + 1; /* +1 for the null */ p = (char*) malloc(len); if (p) { strcpy(p, ev); } /* if (p) */ ev = p; PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev)); }#else /* AFAIK there isn't a library path with the HP SHL interface --Rob */ ev = strdup("");#endif#endif /* * If ev is NULL, we have run out of memory */ _pr_currentLibPath = ev; exit: if (_pr_currentLibPath) { copy = strdup(_pr_currentLibPath); } PR_ExitMonitor(pr_linker_lock); if (!copy) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return copy;}/*** Build library name from path, lib and extensions*/PR_IMPLEMENT(char*) PR_GetLibraryName(const char *path, const char *lib){ char *fullname;#ifdef XP_PC if (strstr(lib, PR_DLL_SUFFIX) == NULL) { fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX); } else { fullname = PR_smprintf("%s\\%s", path, lib); }#endif /* XP_PC */#ifdef XP_MAC fullname = PR_smprintf("%s%s", path, 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); } else { fullname = PR_smprintf("%s/%s", path, lib); }#endif /* XP_UNIX || XP_BEOS */ return fullname;}/*** Free the memory allocated, for the caller, by PR_GetLibraryName*/PR_IMPLEMENT(void) PR_FreeLibraryName(char *mem){ PR_smprintf_free(mem);}static PRLibrary* pr_UnlockedFindLibrary(const char *name){ PRLibrary* lm = pr_loadmap; const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR); np = np ? np + 1 : name;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -