Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/nsprpub/pr/src/linking/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 25 kB image not shown  

Quelle  prlink.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "primpl.h"

#include <string.h>

#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
#    ifdef AIX
#      include <sys/ldr.h>
#      ifndef L_IGNOREUNLOAD /* AIX 4.3.3 does not have L_IGNOREUNLOAD. */
#        define L_IGNOREUNLOAD 0x10000000
#      endif
#    endif
#  elif defined(USE_HPSHL)
#    include <dl.h>
#  endif
#endif /* XP_UNIX */

#define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY

/*
 * On these platforms, symbols have a leading '_'.
 */

#if ((defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__))
#  define NEED_LEADING_UNDERSCORE
#endif

#define PR_LD_PATHW 0x8000 /* for PR_LibSpec_PathnameU */

/************************************************************************/

struct PRLibrary {
  char* name; /* Our own copy of the name string */
  PRLibrary* next;
  int refCount;
  const PRStaticLinkTable* staticTable;

#ifdef XP_PC
  HINSTANCE dlh;
#endif

#ifdef XP_UNIX
#  if defined(USE_HPSHL)
  shl_t dlh;
#  else
  void* dlh;
#  endif
#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);

/************************************************************************/

#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR)
#  define ERR_STR_BUF_LENGTH 20
#endif

static 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
  char errStrBuf[ERR_STR_BUF_LENGTH];
  PR_snprintf(errStrBuf, sizeof(errStrBuf), "error %d", oserr);
  error = errStrBuf;
#endif
  if (NULL != error) {
    PR_SetErrorText(strlen(error), error);
  }
/* DLLErrorInternal */

void _PR_InitLinker(void) {
  PRLibrary* lm = NULL;
#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");
  /* A module handle for the executable. */
  lm->dlh = GetModuleHandle(NULL);

  lm->refCount = 1;
  lm->staticTable = NULL;
  pr_exe_loadmap = lm;
  pr_loadmap = lm;

#elif defined(XP_UNIX)
#  ifdef HAVE_DLL
#    if defined(USE_DLFCN) && !defined(NO_DLOPEN_NULL)
  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(NO_DLOPEN_NULL)
  h = NULL; /* XXXX  toshok */ /* XXXX  vlad */
#    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 */

  if (lm) {
    PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (init)", lm->name));
  }

  PR_ExitMonitor(pr_linker_lock);
}

/*
 * _PR_ShutdownLinker does not unload the dlls loaded by the application
 * via calls to PR_LoadLibrary.  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;
  }
}

/******************************************************************************/

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

#if defined(XP_UNIX)
#  if defined(USE_DLFCN)
  {
    char* p = NULL;
    int len;

    ev = getenv("LD_LIBRARY_PATH");
    if (!ev) {
      ev = "/usr/lib:/lib";
    }
    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) {
    if (path) {
      fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
    } else {
      fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX);
    }
  } else {
    if (path) {
      fullname = PR_smprintf("%s\\%s", path, lib);
    } else {
      fullname = PR_smprintf("%s", lib);
    }
  }
#endif /* XP_PC */
#if defined(XP_UNIX)
  if (strstr(lib, PR_DLL_SUFFIX) == NULL) {
    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 {
    if (path) {
      fullname = PR_smprintf("%s/%s", path, lib);
    } else {
      fullname = PR_smprintf("%s", lib);
    }
  }
#endif /* XP_UNIX */
  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;
  while (lm) {
    const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
    cp = cp ? cp + 1 : lm->name;
#ifdef WIN32
    /* Windows DLL names are case insensitive... */
    if (strcmpi(np, cp) == 0)
#else
    if (strcmp(np, cp) == 0)
#endif
    {
      /* found */
      lm->refCount++;
      PR_LOG(_pr_linker_lm, PR_LOG_MIN,
             ("%s incr => %d (find lib)", lm->name, lm->refCount));
      return lm;
    }
    lm = lm->next;
  }
  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 WIN32
    case PR_LibSpec_PathnameU:
      /*
       * cast to |char *| and set PR_LD_PATHW flag so that
       * it can be cast back to PRUnichar* in the callee.
       */

      return pr_LoadLibraryByPathname((const char*)libSpec.value.pathname_u,
                                      flags | PR_LD_PATHW);
#endif
    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.
*/

static PRLibrary* pr_LoadLibraryByPathname(const char* name, PRIntn flags) {
  PRLibrary* lm;
  PRLibrary* result = NULL;
  PRInt32 oserr;
#ifdef WIN32
  char utf8name_stack[MAX_PATH];
  char* utf8name_malloc = NULL;
  char* utf8name = utf8name_stack;
  PRUnichar wname_stack[MAX_PATH];
  PRUnichar* wname_malloc = NULL;
  PRUnichar* wname = wname_stack;
  int len;
#endif

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  /* See if library is already loaded */
  PR_EnterMonitor(pr_linker_lock);

#ifdef WIN32
  if (flags & PR_LD_PATHW) {
    /* cast back what's cast to |char *| for the argument passing. */
    wname = (LPWSTR)name;
  } else {
    int wlen = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
    if (wlen > MAX_PATH) {
      wname = wname_malloc = PR_Malloc(wlen * sizeof(PRUnichar));
    }
    if (wname == NULL ||
        !MultiByteToWideChar(CP_ACP, 0, name, -1, wname, wlen)) {
      oserr = _MD_ERRNO();
      goto unlock;
    }
  }
  len = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
  if (len > MAX_PATH) {
    utf8name = utf8name_malloc = PR_Malloc(len);
  }
  if (utf8name == NULL ||
      !WideCharToMultiByte(CP_UTF8, 0, wname, -1, utf8name, len, NULL, NULL)) {
    oserr = _MD_ERRNO();
    goto unlock;
  }
  /* the list of loaded library names are always kept in UTF-8
   * on Win32 platforms */

  result = pr_UnlockedFindLibrary(utf8name);
#else
  result = pr_UnlockedFindLibrary(name);
#endif

  if (result != NULL) {
    goto unlock;
  }

  lm = PR_NEWZAP(PRLibrary);
  if (lm == NULL) {
    oserr = _MD_ERRNO();
    goto unlock;
  }
  lm->staticTable = NULL;

#ifdef WIN32
  {
    HINSTANCE h;

    h = LoadLibraryExW(
        wname, NULL,
        (flags & PR_LD_ALT_SEARCH_PATH) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
    if (h == NULL) {
      oserr = _MD_ERRNO();
      PR_DELETE(lm);
      goto unlock;
    }
    lm->name = strdup(utf8name);
    lm->dlh = h;
    lm->next = pr_loadmap;
    pr_loadmap = lm;
  }
#endif /* WIN32 */

#if defined(XP_UNIX)
#  ifdef HAVE_DLL
  {
#    if defined(USE_DLFCN)
#      ifdef NTO
    /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */
    int dl_flags = RTLD_GROUP;
#      elif defined(AIX)
    /* AIX needs RTLD_MEMBER to load an archive member.  (bug 228899) */
    int dl_flags = RTLD_MEMBER;
#      else
    int dl_flags = 0;
#      endif
    void* h = NULL;
#      if defined(DARWIN)
    PRBool okToLoad = PR_FALSE;
#      endif

    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;
    }
#      if defined(DARWIN)
    /* If the file contains an absolute or relative path (slash)
     * and the path doesn't look like a System path, then require
     * the file exists.
     * The reason is that DARWIN's dlopen ignores the provided path
     * and checks for the plain filename in DYLD_LIBRARY_PATH,
     * which could load an unexpected version of a library. */

    if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) {
      /* no slash, allow to load from any location */
      okToLoad = PR_TRUE;
    } else {
      const char systemPrefix1[] = "/System/";
      const size_t systemPrefixLen1 = strlen(systemPrefix1);
      const char systemPrefix2[] = "/usr/lib/";
      const size_t systemPrefixLen2 = strlen(systemPrefix2);
      const size_t name_len = strlen(name);
      if (((name_len > systemPrefixLen1) &&
           (strncmp(name, systemPrefix1, systemPrefixLen1) == 0)) ||
          ((name_len > systemPrefixLen2) &&
           (strncmp(name, systemPrefix2, systemPrefixLen2) == 0))) {
        /* found at beginning, it's a system library.
         * Skip filesystem check (required for macOS 11),
         * allow loading from any location */

        okToLoad = PR_TRUE;
      } else if (PR_Access(name, PR_ACCESS_EXISTS) == PR_SUCCESS) {
        /* file exists, allow to load */
        okToLoad = PR_TRUE;
      }
    }
    if (okToLoad) {
      h = dlopen(name, dl_flags);
    }
#      else
    h = dlopen(name, dl_flags);
#      endif
#    elif defined(USE_HPSHL)
    int shl_flags = 0;
    shl_t h;

    /*
     * Use the DYNAMIC_PATH flag only if 'name' is a plain file
     * name (containing no directory) to match the behavior of
     * dlopen().
     */

    if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) {
      shl_flags |= DYNAMIC_PATH;
    }
    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);
#    else
#      error Configuration error
#    endif
    if (!h) {
      oserr = _MD_ERRNO();
      PR_DELETE(lm);
      goto unlock;
    }
    lm->name = strdup(name);
    lm->dlh = h;
    lm->next = pr_loadmap;
    pr_loadmap = lm;
  }
#  endif /* HAVE_DLL */
#endif   /* XP_UNIX */

  lm->refCount = 1;

  result = lm; /* success */
  PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name));

unlock:
  if (result == NULL) {
    PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr);
    DLLErrorInternal(oserr); /* sets error text */
  }
#ifdef WIN32
  if (utf8name_malloc) {
    PR_Free(utf8name_malloc);
  }
  if (wname_malloc) {
    PR_Free(wname_malloc);
  }
#endif
  PR_ExitMonitor(pr_linker_lock);
  return result;
}

/*
** Unload a shared library which was loaded via PR_LoadLibrary
*/

PR_IMPLEMENT(PRStatus)
PR_UnloadLibrary(PRLibrary* lib) {
  int result = 0;
  PRStatus status = PR_SUCCESS;

  if (lib == 0) {
    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    return PR_FAILURE;
  }

  PR_EnterMonitor(pr_linker_lock);

  if (lib->refCount <= 0) {
    PR_ExitMonitor(pr_linker_lock);
    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    return PR_FAILURE;
  }

  if (--lib->refCount > 0) {
    PR_LOG(_pr_linker_lm, PR_LOG_MIN,
           ("%s decr => %d", lib->name, lib->refCount));
    goto done;
  }

#ifdef XP_UNIX
#  ifdef HAVE_DLL
#    ifdef USE_DLFCN
  result = dlclose(lib->dlh);
#    elif defined(USE_HPSHL)
  result = shl_unload(lib->dlh);
#    else
#      error Configuration error
#    endif
#  endif /* HAVE_DLL */
#endif   /* XP_UNIX */
#ifdef XP_PC
  if (lib->dlh) {
    FreeLibrary((HINSTANCE)(lib->dlh));
    lib->dlh = (HINSTANCE)NULL;
  }
#endif /* XP_PC */

  /* unlink from library search list */
  if (pr_loadmap == lib) {
    pr_loadmap = pr_loadmap->next;
  } else if (pr_loadmap != NULL) {
    PRLibrary* prev = pr_loadmap;
    PRLibrary* next = pr_loadmap->next;
    while (next != NULL) {
      if (next == lib) {
        prev->next = next->next;
        goto freeLib;
      }
      prev = next;
      next = next->next;
    }
    /*
     * fail (the library is not on the _pr_loadmap list),
     * but don't wipe out an error from dlclose/shl_unload.
     */

    PR_NOT_REACHED("_pr_loadmap and lib->refCount inconsistent");
    if (result == 0) {
      PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
      status = PR_FAILURE;
    }
  }
  /*
   * We free the PRLibrary structure whether dlclose/shl_unload
   * succeeds or not.
   */


freeLib:
  PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
  free(lib->name);
  lib->name = NULL;
  PR_DELETE(lib);
  if (result != 0) {
    PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
    DLLErrorInternal(_MD_ERRNO());
    status = PR_FAILURE;
  }

done:
  PR_ExitMonitor(pr_linker_lock);
  return status;
}

static void* pr_FindSymbolInLib(PRLibrary* lm, const char* name) {
  void* f = NULL;

  if (lm->staticTable != NULL) {
    const PRStaticLinkTable* tp;
    for (tp = lm->staticTable; tp->name; tp++) {
      if (strcmp(name, tp->name) == 0) {
        return (void*)tp->fp;
      }
    }
    /*
    ** If the symbol was not found in the static table then check if
    ** the symbol was exported in the DLL...
    */

    PR_SetError(PR_FIND_SYMBOL_ERROR, 0);
    return (void*)NULL;
  }

#ifdef WIN32
  f = GetProcAddress(lm->dlh, name);
#endif /* WIN32 */

#ifdef XP_UNIX
#  ifdef HAVE_DLL
#    ifdef USE_DLFCN
  f = dlsym(lm->dlh, name);
#    elif defined(USE_HPSHL)
  if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) {
    f = NULL;
  }
#    endif
#  endif /* HAVE_DLL */
#endif   /* XP_UNIX */
  if (f == NULL) {
    PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
    DLLErrorInternal(_MD_ERRNO());
  }
  return f;
}

/*
** Called by class loader to resolve missing native's
*/

PR_IMPLEMENT(void*)
PR_FindSymbol(PRLibrary* lib, const char* raw_name) {
  void* f = NULL;
#if defined(NEED_LEADING_UNDERSCORE)
  char* name;
#else
  const char* name;
#endif
  /*
  ** Mangle the raw symbol name in any way that is platform specific.
  */

#if defined(NEED_LEADING_UNDERSCORE)
  /* Need a leading _ */
  name = PR_smprintf("_%s", raw_name);
#elif defined(AIX)
  /*
  ** AIX with the normal linker put's a "." in front of the symbol
  ** name.  When use "svcc" and "svld" then the "." disappears. Go
  ** figure.
  */

  name = raw_name;
#else
  name = raw_name;
#endif

  PR_EnterMonitor(pr_linker_lock);
  PR_ASSERT(lib != NULL);
  f = pr_FindSymbolInLib(lib, name);

#if defined(NEED_LEADING_UNDERSCORE)
  PR_smprintf_free(name);
#endif

  PR_ExitMonitor(pr_linker_lock);
  return f;
}

/*
** Return the address of the function 'raw_name' in the library 'lib'
*/

PR_IMPLEMENT(PRFuncPtr)
PR_FindFunctionSymbol(PRLibrary* lib, const char* raw_name) {
  return ((PRFuncPtr)PR_FindSymbol(lib, raw_name));
}

PR_IMPLEMENT(void*)
PR_FindSymbolAndLibrary(const char* raw_name, PRLibrary** lib) {
  void* f = NULL;
#if defined(NEED_LEADING_UNDERSCORE)
  char* name;
#else
  const char* name;
#endif
  PRLibrary* lm;

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }
  /*
  ** Mangle the raw symbol name in any way that is platform specific.
  */

#if defined(NEED_LEADING_UNDERSCORE)
  /* Need a leading _ */
  name = PR_smprintf("_%s", raw_name);
#elif defined(AIX)
  /*
  ** AIX with the normal linker put's a "." in front of the symbol
  ** name.  When use "svcc" and "svld" then the "." disappears. Go
  ** figure.
  */

  name = raw_name;
#else
  name = raw_name;
#endif

  PR_EnterMonitor(pr_linker_lock);

  /* search all libraries */
  for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
    f = pr_FindSymbolInLib(lm, name);
    if (f != NULL) {
      *lib = lm;
      lm->refCount++;
      PR_LOG(_pr_linker_lm, PR_LOG_MIN,
             ("%s incr => %d (for %s)", lm->name, lm->refCount, name));
      break;
    }
  }
#if defined(NEED_LEADING_UNDERSCORE)
  PR_smprintf_free(name);
#endif

  PR_ExitMonitor(pr_linker_lock);
  return f;
}

PR_IMPLEMENT(PRFuncPtr)
PR_FindFunctionSymbolAndLibrary(const char* raw_name, PRLibrary** lib) {
  return ((PRFuncPtr)PR_FindSymbolAndLibrary(raw_name, lib));
}

/*
** Add a static library to the list of loaded libraries. If LoadLibrary
** is called with the name then we will pretend it was already loaded
*/

PR_IMPLEMENT(PRLibrary*)
PR_LoadStaticLibrary(const char* name, const PRStaticLinkTable* slt) {
  PRLibrary* lm = NULL;
  PRLibrary* result = NULL;

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  /* See if library is already loaded */
  PR_EnterMonitor(pr_linker_lock);

  /* If the lbrary is already loaded, then add the static table information...
   */

  result = pr_UnlockedFindLibrary(name);
  if (result != NULL) {
    PR_ASSERT((result->staticTable == NULL) || (result->staticTable == slt));
    result->staticTable = slt;
    goto unlock;
  }

  /* Add library to list...Mark it static */
  lm = PR_NEWZAP(PRLibrary);
  if (lm == NULL) {
    goto unlock;
  }

  lm->name = strdup(name);
  lm->refCount = 1;
  lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0;
  lm->staticTable = slt;
  lm->next = pr_loadmap;
  pr_loadmap = lm;

  result = lm; /* success */
  PR_ASSERT(lm->refCount == 1);
  PR_LOG(_pr_linker_lm, PR_LOG_MIN,
         ("Loaded library %s (static lib)", lm->name));
unlock:
  PR_ExitMonitor(pr_linker_lock);
  return result;
}

PR_IMPLEMENT(char*)
PR_GetLibraryFilePathname(const char* name, PRFuncPtr addr) {
#if defined(USE_DLFCN) && defined(HAVE_DLADDR)
  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(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;
  int loadflags = L_GETINFO | L_IGNOREUNLOAD;

  for (;;) {
    info = PR_Malloc(info_length);
    if (info == NULL) {
      return NULL;
    }
    /* If buffer is too small, loadquery fails with ENOMEM. */
    if (loadquery(loadflags, info, info_length) != -1) {
      break;
    }
    /*
     * Calling loadquery when compiled for 64-bit with the
     * L_IGNOREUNLOAD flag can cause an invalid argument error
     * on AIX 5.1. Detect this error the first time that
     * loadquery is called, and try calling it again without
     * this flag set.
     */

    if (errno == EINVAL && (loadflags & L_IGNOREUNLOAD)) {
      loadflags &= ~L_IGNOREUNLOAD;
      if (loadquery(loadflags, 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)) {
    unsigned long start = (unsigned long)infop->ldinfo_dataorg;
    unsigned long end = start + infop->ldinfo_datasize;
    if (start <= (unsigned long)addr && end > (unsigned long)addr) {
      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(HPUX) && defined(USE_HPSHL)
  int index;
  struct shl_descriptor desc;
  char* result;

  for (index = 0; shl_get_r(index, &desc) == 0; index++) {
    if (strstr(desc.filename, name) != NULL) {
      result = PR_Malloc(strlen(desc.filename) + 1);
      if (result != NULL) {
        strcpy(result, desc.filename);
      }
      return result;
    }
  }
  /*
   * Since the index value of a library is decremented if
   * a library preceding it in the shared library search
   * list was unloaded, it is possible that we missed some
   * libraries as we went up the list.  So we should go
   * down the list to be sure that we not miss anything.
   */

  for (index--; index >= 0; index--) {
    if ((shl_get_r(index, &desc) == 0) &&
        (strstr(desc.filename, name) != NULL)) {
      result = PR_Malloc(strlen(desc.filename) + 1);
      if (result != NULL) {
        strcpy(result, desc.filename);
      }
      return result;
    }
  }
  PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
  return NULL;
#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)
  PRUnichar wname[MAX_PATH];
  HMODULE handle = NULL;
  PRUnichar module_name[MAX_PATH];
  int len;
  char* result;

  if (MultiByteToWideChar(CP_ACP, 0, name, -1, wname, MAX_PATH)) {
    handle = GetModuleHandleW(wname);
  }
  if (handle == NULL) {
    PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
    DLLErrorInternal(_MD_ERRNO());
    return NULL;
  }
  if (GetModuleFileNameW(handle, module_name, MAX_PATH) == 0) {
    /* should not happen */
    _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
    return NULL;
  }
  len = WideCharToMultiByte(CP_ACP, 0, module_name, -1, NULL, 0, NULL, NULL);
  if (len == 0) {
    _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
    return NULL;
  }
  result = PR_Malloc(len * sizeof(PRUnichar));
  if (result != NULL) {
    WideCharToMultiByte(CP_ACP, 0, module_name, -1, result, len, NULL, NULL);
  }
  return result;
#else
  PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  return NULL;
#endif
}

Messung V0.5
C=92 H=91 G=91

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.