1 //===-- llvm/Support/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the sys::DynamicLibrary class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_SUPPORT_DYNAMICLIBRARY_H
14 #define LLVM_SUPPORT_DYNAMICLIBRARY_H
15 
16 #include <string>
17 
18 namespace llvm {
19 
20 class StringRef;
21 
22 namespace sys {
23 
24 /// This class provides a portable interface to dynamic libraries which also
25 /// might be known as shared libraries, shared objects, dynamic shared
26 /// objects, or dynamic link libraries. Regardless of the terminology or the
27 /// operating system interface, this class provides a portable interface that
28 /// allows dynamic libraries to be loaded and searched for externally
29 /// defined symbols. This is typically used to provide "plug-in" support.
30 /// It also allows for symbols to be defined which don't live in any library,
31 /// but rather the main program itself, useful on Windows where the main
32 /// executable cannot be searched.
33 class DynamicLibrary {
34   // Placeholder whose address represents an invalid library.
35   // We use this instead of NULL or a pointer-int pair because the OS library
36   // might define 0 or 1 to be "special" handles, such as "search all".
37   static char Invalid;
38 
39   // Opaque data used to interface with OS-specific dynamic library handling.
40   void *Data;
41 
42 public:
43   explicit DynamicLibrary(void *data = &Invalid) : Data(data) {}
44 
45   /// Return the OS specific handle value.
46   void *getOSSpecificHandle() const { return Data; }
47 
48   /// Returns true if the object refers to a valid library.
49   bool isValid() const { return Data != &Invalid; }
50 
51   /// Searches through the library for the symbol \p symbolName. If it is
52   /// found, the address of that symbol is returned. If not, NULL is returned.
53   /// Note that NULL will also be returned if the library failed to load.
54   /// Use isValid() to distinguish these cases if it is important.
55   /// Note that this will \e not search symbols explicitly registered by
56   /// AddSymbol().
57   void *getAddressOfSymbol(const char *symbolName);
58 
59   /// This function permanently loads the dynamic library at the given path
60   /// using the library load operation from the host operating system. The
61   /// library instance will only be closed when global destructors run, and
62   /// there is no guarantee when the library will be unloaded.
63   ///
64   /// This returns a valid DynamicLibrary instance on success and an invalid
65   /// instance on failure (see isValid()). \p *errMsg will only be modified if
66   /// the library fails to load.
67   ///
68   /// It is safe to call this function multiple times for the same library.
69   /// Open a dynamic library permanently.
70   static DynamicLibrary getPermanentLibrary(const char *filename,
71                                             std::string *errMsg = nullptr);
72 
73   /// Registers an externally loaded library. The library will be unloaded
74   /// when the program terminates.
75   ///
76   /// It is safe to call this function multiple times for the same library,
77   /// though ownership is only taken if there was no error.
78   static DynamicLibrary addPermanentLibrary(void *handle,
79                                             std::string *errMsg = nullptr);
80 
81   /// This function permanently loads the dynamic library at the given path.
82   /// Use this instead of getPermanentLibrary() when you won't need to get
83   /// symbols from the library itself.
84   ///
85   /// It is safe to call this function multiple times for the same library.
86   static bool LoadLibraryPermanently(const char *Filename,
87                                      std::string *ErrMsg = nullptr) {
88     return !getPermanentLibrary(Filename, ErrMsg).isValid();
89   }
90 
91   /// This function loads the dynamic library at the given path, using the
92   /// library load operation from the host operating system. The library
93   /// instance will be closed when closeLibrary is called or global destructors
94   /// are run, but there is no guarantee when the library will be unloaded.
95   ///
96   /// This returns a valid DynamicLibrary instance on success and an invalid
97   /// instance on failure (see isValid()). \p *Err will only be modified if the
98   /// library fails to load.
99   ///
100   /// It is safe to call this function multiple times for the same library.
101   static DynamicLibrary getLibrary(const char *FileName,
102                                    std::string *Err = nullptr);
103 
104   /// This function closes the dynamic library at the given path, using the
105   /// library close operation of the host operating system, and there is no
106   /// guarantee if or when this will cause the the library to be unloaded.
107   ///
108   /// This function should be called only if the library was loaded using the
109   /// getLibrary() function.
110   static void closeLibrary(DynamicLibrary &Lib);
111 
112   enum SearchOrdering {
113     /// SO_Linker - Search as a call to dlsym(dlopen(NULL)) would when
114     /// DynamicLibrary::getPermanentLibrary(NULL) has been called or
115     /// search the list of explcitly loaded symbols if not.
116     SO_Linker,
117     /// SO_LoadedFirst - Search all loaded libraries, then as SO_Linker would.
118     SO_LoadedFirst,
119     /// SO_LoadedLast - Search as SO_Linker would, then loaded libraries.
120     /// Only useful to search if libraries with RTLD_LOCAL have been added.
121     SO_LoadedLast,
122     /// SO_LoadOrder - Or this in to search libraries in the ordered loaded.
123     /// The default bahaviour is to search loaded libraries in reverse.
124     SO_LoadOrder = 4
125   };
126   static SearchOrdering SearchOrder; // = SO_Linker
127 
128   /// This function will search through all previously loaded dynamic
129   /// libraries for the symbol \p symbolName. If it is found, the address of
130   /// that symbol is returned. If not, null is returned. Note that this will
131   /// search permanently loaded libraries (getPermanentLibrary()) as well
132   /// as explicitly registered symbols (AddSymbol()).
133   /// @throws std::string on error.
134   /// Search through libraries for address of a symbol
135   static void *SearchForAddressOfSymbol(const char *symbolName);
136 
137   /// Convenience function for C++ophiles.
138   static void *SearchForAddressOfSymbol(const std::string &symbolName) {
139     return SearchForAddressOfSymbol(symbolName.c_str());
140   }
141 
142   /// This functions permanently adds the symbol \p symbolName with the
143   /// value \p symbolValue.  These symbols are searched before any
144   /// libraries.
145   /// Add searchable symbol/value pair.
146   static void AddSymbol(StringRef symbolName, void *symbolValue);
147 
148   class HandleSet;
149 };
150 
151 } // End sys namespace
152 } // End llvm namespace
153 
154 #endif
155