Eliminate use of ltdl.c when doing a VC++ build. Because libtool isn't used,
[oota-llvm.git] / lib / System / DynamicLibrary.cpp
1 //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Reid Spencer and is distributed under the 
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 //  This header file implements the operating system DynamicLibrary concept.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/System/DynamicLibrary.h"
15
16 // It is not possible to use ltdl.c on VC++ builds as the terms of its LGPL
17 // license and special exception would cause all of LLVM to be placed under
18 // the LGPL.  This is because the exception applies only when libtool is
19 // used, and obviously libtool is not used with Visual Studio.  An entirely
20 // separate implementation is provided in win32/DynamicLibrary.cpp.
21
22 #ifdef _WIN32
23
24 #include "win32/DynamicLibrary.cpp"
25
26 #else
27
28 #include "ltdl.h"
29 #include <cassert>
30 using namespace llvm;
31 using namespace llvm::sys;
32
33 //===----------------------------------------------------------------------===//
34 //=== WARNING: Implementation here must contain only TRULY operating system
35 //===          independent code. 
36 //===----------------------------------------------------------------------===//
37
38 static bool did_initialize_ltdl = false;
39
40 static inline void check_ltdl_initialization() {
41   if (!did_initialize_ltdl) {
42     if (0 != lt_dlinit())
43       throw std::string(lt_dlerror());
44     did_initialize_ltdl = true;
45   }
46 }
47
48 static std::vector<lt_dlhandle> OpenedHandles;
49
50 DynamicLibrary::DynamicLibrary() : handle(0) {
51   check_ltdl_initialization();
52
53   lt_dlhandle a_handle = lt_dlopen(0);
54
55   if (a_handle == 0)
56     throw std::string("Can't open program as dynamic library");
57   
58   handle = a_handle;
59   OpenedHandles.push_back(a_handle);
60 }
61
62 DynamicLibrary::DynamicLibrary(const char*filename) : handle(0) {
63   check_ltdl_initialization();
64
65   lt_dlhandle a_handle = lt_dlopen(filename);
66
67   if (a_handle == 0)
68     a_handle = lt_dlopenext(filename);
69
70   if (a_handle == 0)
71     throw std::string("Can't open :") + filename + ": " + lt_dlerror();
72
73   handle = a_handle;
74   OpenedHandles.push_back(a_handle);
75 }
76
77 DynamicLibrary::~DynamicLibrary() {
78   lt_dlhandle a_handle = (lt_dlhandle) handle;
79   if (a_handle) {
80     lt_dlclose(a_handle);
81
82     for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
83          E = OpenedHandles.end(); I != E; ++I) {
84       if (*I == a_handle) {
85         // Note: don't use the swap/pop_back trick here. Order is important.
86         OpenedHandles.erase(I);
87       }
88     }
89   }
90 }
91
92 void DynamicLibrary::LoadLibraryPermanently(const char* filename) {
93   check_ltdl_initialization();
94   lt_dlhandle a_handle = lt_dlopen(filename);
95
96   if (a_handle == 0)
97     a_handle = lt_dlopenext(filename);
98
99   if (a_handle == 0)
100     throw std::string("Can't open :") + filename + ": " + lt_dlerror();
101
102   lt_dlmakeresident(a_handle);
103
104   OpenedHandles.push_back(a_handle);
105 }
106
107 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
108   check_ltdl_initialization();
109   for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
110        E = OpenedHandles.end(); I != E; ++I) {
111     lt_ptr ptr = lt_dlsym(*I, symbolName);
112     if (ptr)
113       return ptr;
114   }
115
116   // If this is darwin, it has some funky issues, try to solve them here.  Some
117   // important symbols are marked 'private external' which doesn't allow
118   // SearchForAddressOfSymbol to find them.  As such, we special case them here,
119   // there is only a small handful of them.
120 #ifdef __APPLE__
121   {
122 #define EXPLICIT_SYMBOL(SYM) \
123    extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
124     EXPLICIT_SYMBOL(__ashldi3);
125     EXPLICIT_SYMBOL(__ashrdi3);
126     EXPLICIT_SYMBOL(__cmpdi2);
127     EXPLICIT_SYMBOL(__divdi3);
128     EXPLICIT_SYMBOL(__eprintf);
129     EXPLICIT_SYMBOL(__fixdfdi);
130     EXPLICIT_SYMBOL(__fixsfdi);
131     EXPLICIT_SYMBOL(__fixunsdfdi);
132     EXPLICIT_SYMBOL(__fixunssfdi);
133     EXPLICIT_SYMBOL(__floatdidf);
134     EXPLICIT_SYMBOL(__floatdisf);
135     EXPLICIT_SYMBOL(__lshrdi3);
136     EXPLICIT_SYMBOL(__moddi3);
137     EXPLICIT_SYMBOL(__udivdi3);
138     EXPLICIT_SYMBOL(__umoddi3);
139 #undef EXPLICIT_SYMBOL
140   }
141 #endif
142
143   return 0;
144 }
145
146 void *DynamicLibrary::GetAddressOfSymbol(const char *symbolName) {
147   assert(handle != 0 && "Invalid DynamicLibrary handle");
148   return lt_dlsym((lt_dlhandle) handle, symbolName);
149 }
150
151 #endif // _WIN32