mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
ccaba64332
This fixes PR4512 and eliminating static ctors is always good. Losing thread safety is unfortunate, but the code is just incredibly poorly designed. If someone is interested, the "right" solution is to split DynamicLibrary.cpp into two separate pieces: a stateless piece in libsystem, and a simple support file in libsupport that has the "state" (e.g. AddSymbol) in managed static objects. Doing this would both fix memory leaks we already have, as well as make the code thread safe again. it would also make sense to move all the unix specific code in System/DynamicLibrary.cpp into System/Unix/DynamicLibrary.inc. llvm-svn: 74927
160 lines
4.5 KiB
C++
160 lines
4.5 KiB
C++
//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This header file implements the operating system DynamicLibrary concept.
|
|
//
|
|
// FIXME: This file leaks the ExplicitSymbols and OpenedHandles vector, and is
|
|
// not thread safe!
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/System/DynamicLibrary.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
#include "llvm/Config/config.h"
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
// Collection of symbol name/value pairs to be searched prior to any libraries.
|
|
static std::map<std::string, void*> *ExplicitSymbols = 0;
|
|
|
|
void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName,
|
|
void *symbolValue) {
|
|
if (ExplicitSymbols == 0)
|
|
ExplicitSymbols = new std::map<std::string, void*>();
|
|
(*ExplicitSymbols)[symbolName] = symbolValue;
|
|
}
|
|
|
|
#ifdef LLVM_ON_WIN32
|
|
|
|
#include "Win32/DynamicLibrary.inc"
|
|
|
|
#else
|
|
|
|
#include <dlfcn.h>
|
|
using namespace llvm;
|
|
using namespace llvm::sys;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//=== WARNING: Implementation here must contain only TRULY operating system
|
|
//=== independent code.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
static std::vector<void *> *OpenedHandles = 0;
|
|
|
|
|
|
bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
|
|
std::string *ErrMsg) {
|
|
void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL);
|
|
if (H == 0) {
|
|
if (ErrMsg) *ErrMsg = dlerror();
|
|
return true;
|
|
}
|
|
if (OpenedHandles == 0)
|
|
OpenedHandles = new std::vector<void *>();
|
|
OpenedHandles->push_back(H);
|
|
return false;
|
|
}
|
|
|
|
void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
|
|
// First check symbols added via AddSymbol().
|
|
if (ExplicitSymbols) {
|
|
std::map<std::string, void *>::iterator I =
|
|
ExplicitSymbols->find(symbolName);
|
|
std::map<std::string, void *>::iterator E = ExplicitSymbols->end();
|
|
|
|
if (I != E)
|
|
return I->second;
|
|
}
|
|
|
|
// Now search the libraries.
|
|
if (OpenedHandles) {
|
|
for (std::vector<void *>::iterator I = OpenedHandles->begin(),
|
|
E = OpenedHandles->end(); I != E; ++I) {
|
|
//lt_ptr ptr = lt_dlsym(*I, symbolName);
|
|
void *ptr = dlsym(*I, symbolName);
|
|
if (ptr) {
|
|
return ptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define EXPLICIT_SYMBOL(SYM) \
|
|
extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
|
|
|
|
// If this is darwin, it has some funky issues, try to solve them here. Some
|
|
// important symbols are marked 'private external' which doesn't allow
|
|
// SearchForAddressOfSymbol to find them. As such, we special case them here,
|
|
// there is only a small handful of them.
|
|
|
|
#ifdef __APPLE__
|
|
{
|
|
EXPLICIT_SYMBOL(__ashldi3);
|
|
EXPLICIT_SYMBOL(__ashrdi3);
|
|
EXPLICIT_SYMBOL(__cmpdi2);
|
|
EXPLICIT_SYMBOL(__divdi3);
|
|
EXPLICIT_SYMBOL(__eprintf);
|
|
EXPLICIT_SYMBOL(__fixdfdi);
|
|
EXPLICIT_SYMBOL(__fixsfdi);
|
|
EXPLICIT_SYMBOL(__fixunsdfdi);
|
|
EXPLICIT_SYMBOL(__fixunssfdi);
|
|
EXPLICIT_SYMBOL(__floatdidf);
|
|
EXPLICIT_SYMBOL(__floatdisf);
|
|
EXPLICIT_SYMBOL(__lshrdi3);
|
|
EXPLICIT_SYMBOL(__moddi3);
|
|
EXPLICIT_SYMBOL(__udivdi3);
|
|
EXPLICIT_SYMBOL(__umoddi3);
|
|
}
|
|
#endif
|
|
|
|
#ifdef __CYGWIN__
|
|
{
|
|
EXPLICIT_SYMBOL(_alloca);
|
|
EXPLICIT_SYMBOL(__main);
|
|
}
|
|
#endif
|
|
|
|
#undef EXPLICIT_SYMBOL
|
|
|
|
// This macro returns the address of a well-known, explicit symbol
|
|
#define EXPLICIT_SYMBOL(SYM) \
|
|
if (!strcmp(symbolName, #SYM)) return &SYM
|
|
|
|
// On linux we have a weird situation. The stderr/out/in symbols are both
|
|
// macros and global variables because of standards requirements. So, we
|
|
// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
|
|
#if defined(__linux__)
|
|
{
|
|
EXPLICIT_SYMBOL(stderr);
|
|
EXPLICIT_SYMBOL(stdout);
|
|
EXPLICIT_SYMBOL(stdin);
|
|
}
|
|
#else
|
|
// For everything else, we want to check to make sure the symbol isn't defined
|
|
// as a macro before using EXPLICIT_SYMBOL.
|
|
{
|
|
#ifndef stdin
|
|
EXPLICIT_SYMBOL(stdin);
|
|
#endif
|
|
#ifndef stdout
|
|
EXPLICIT_SYMBOL(stdout);
|
|
#endif
|
|
#ifndef stderr
|
|
EXPLICIT_SYMBOL(stderr);
|
|
#endif
|
|
}
|
|
#endif
|
|
#undef EXPLICIT_SYMBOL
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif // LLVM_ON_WIN32
|