Implement two new functions: LoadLibraryPermanently and
[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 #include "ltdl.h"
16 #include <cassert>
17
18 //===----------------------------------------------------------------------===//
19 //=== WARNING: Implementation here must contain only TRULY operating system
20 //===          independent code. 
21 //===----------------------------------------------------------------------===//
22
23 static bool did_initialize_ltdl = false;
24
25 static inline void check_ltdl_initialization() {
26   if (!did_initialize_ltdl) {
27     if (0 != lt_dlinit())
28       throw std::string(lt_dlerror());
29     did_initialize_ltdl = true;
30   }
31 }
32
33 static std::vector<lt_dlhandle> OpenedHandles;
34
35 namespace llvm {
36
37 using namespace sys;
38
39 DynamicLibrary::DynamicLibrary() : handle(0) {
40   check_ltdl_initialization();
41
42   lt_dlhandle a_handle = lt_dlopen(0);
43
44   if (a_handle == 0)
45     throw std::string("Can't open program as dynamic library");
46   
47   handle = a_handle;
48   OpenedHandles.push_back(a_handle);
49 }
50
51 DynamicLibrary::DynamicLibrary(const char*filename) : handle(0) {
52   check_ltdl_initialization();
53
54   lt_dlhandle a_handle = lt_dlopen(filename);
55
56   if (a_handle == 0)
57     a_handle = lt_dlopenext(filename);
58
59   if (a_handle == 0)
60     throw std::string("Can't open :") + filename + ": " + lt_dlerror();
61
62   handle = a_handle;
63   OpenedHandles.push_back(a_handle);
64 }
65
66 DynamicLibrary::~DynamicLibrary() {
67   lt_dlhandle a_handle = (lt_dlhandle) handle;
68   if (a_handle) {
69     lt_dlclose(a_handle);
70
71     for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
72          E = OpenedHandles.end(); I != E; ++I) {
73       if (*I == a_handle) {
74         // Note: don't use the swap/pop_back trick here. Order is important.
75         OpenedHandles.erase(I);
76       }
77     }
78   }
79 }
80
81 void DynamicLibrary::LoadLibraryPermanently(const char* filename) {
82   check_ltdl_initialization();
83   lt_dlhandle a_handle = lt_dlopen(filename);
84
85   if (a_handle == 0)
86     a_handle = lt_dlopenext(filename);
87
88   if (a_handle == 0)
89     throw std::string("Can't open :") + filename + ": " + lt_dlerror();
90
91   lt_dlmakeresident(a_handle);
92
93   OpenedHandles.push_back(a_handle);
94 }
95
96 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
97   check_ltdl_initialization();
98   for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(),
99        E = OpenedHandles.end(); I != E; ++I) {
100     lt_ptr ptr = lt_dlsym(*I, symbolName);
101     if (ptr)
102       return ptr;
103   }
104   return 0;
105 }
106
107 void *DynamicLibrary::GetAddressOfSymbol(const char *symbolName) {
108   assert(handle != 0 && "Invalid DynamicLibrary handle");
109   return lt_dlsym((lt_dlhandle) handle, symbolName);
110 }
111
112 } // namespace llvm