1 // sharedlib.cpp: Shared Library support, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20
21
22 #ifdef HAVE_CONFIG_H
23 #include "gnashconfig.h"
24 #endif
25
26 #include "log.h"
27 #include "sharedlib.h"
28
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #include <string>
33 #include <cstdlib>
34
35 #if defined(WIN32) || defined(_WIN32)
36 # define LIBLTDL_DLL_IMPORT 1
37 #endif
38 #ifdef HAVE_DLFCN_H
39 # include <dlfcn.h>
40 #endif
41 #ifdef HAVE_LIBGEN_H
42 # include <libgen.h>
43 #endif
44
45 #include <ltdl.h>
46 #include <mutex>
47
48 #if defined(WIN32) || defined(_WIN32)
49 int lt_dlsetsearchpath (const char *search_path);
50 int lt_dlinit (void);
51 void * lt_dlsym (lt_dlhandle handle, const char *name);
52 const char *lt_dlerror (void);
53 int lt_dlclose (lt_dlhandle handle);
54 int lt_dlmakeresident (lt_dlhandle handle);
55 lt_dlhandle lt_dlopenext (const char *filename);
56 #endif
57
58 namespace gnash {
59
SharedLib(const std::string & filespec)60 SharedLib::SharedLib(const std::string& filespec)
61 #ifdef HAVE_LTDL
62 : _dlhandle(nullptr)
63 #endif
64 {
65 _filespec = filespec;
66 scoped_lock lock(_libMutex);
67
68 // Initialize libtool's dynamic library loader
69 #ifdef HAVE_LTDL
70 int errors = lt_dlinit ();
71 if (errors) {
72 log_error(_("Couldn't initialize ltdl: %s"), lt_dlerror());
73 }
74 #else
75 # warning "libltdl not enabled in build".
76 #endif
77 }
78
79 bool
closeLib()80 SharedLib::closeLib()
81 {
82 #ifdef HAVE_LTDL
83 return lt_dlclose(_dlhandle);
84 #else
85 return true;
86 #endif
87 }
88
89 bool
openLib()90 SharedLib::openLib()
91 {
92 return openLib(_filespec);
93 }
94
95 bool
openLib(const std::string & filespec)96 SharedLib::openLib (const std::string& filespec)
97 {
98
99 scoped_lock lock(_libMutex);
100
101 log_debug(_("Trying to open shared library \"%s\""), filespec);
102
103 #ifdef HAVE_LTDL
104 _dlhandle = lt_dlopenext (filespec.c_str());
105
106 if (_dlhandle == nullptr) {
107 log_error("lt_dlopenext(\"%s\") failed: %s", filespec.c_str(), lt_dlerror());
108 return false;
109 }
110
111 // Make this module unloadable
112 lt_dlmakeresident(_dlhandle);
113 #endif
114
115 log_debug (_("Opened dynamic library \"%s\""), filespec);
116
117 _filespec = filespec;
118
119 return true;
120 }
121
122 SharedLib::initentry *
getInitEntry(const std::string & symbol)123 SharedLib::getInitEntry (const std::string& symbol)
124 {
125 // GNASH_REPORT_FUNCTION;
126 lt_ptr run = nullptr;
127
128 scoped_lock lock(_libMutex);
129
130 #ifdef HAVE_LTDL
131 run = lt_dlsym (_dlhandle, symbol.c_str());
132
133 if (run == nullptr) {
134 log_error(_("Couldn't find symbol: %s"), symbol);
135 return nullptr;
136 } else {
137 log_debug(_("Found symbol %s @ %p"), symbol, (void *)run);
138 }
139 #else
140 (void)symbol;
141 #endif
142
143 return (initentry*)(run);
144 }
145
146 SharedLib::entrypoint *
getDllSymbol(const std::string & symbol)147 SharedLib::getDllSymbol(const std::string& symbol)
148 {
149 GNASH_REPORT_FUNCTION;
150
151 lt_ptr run = nullptr;
152
153 scoped_lock lock(_libMutex);
154
155 #ifdef HAVE_LTDL
156 run = lt_dlsym (_dlhandle, symbol.c_str());
157 #endif
158
159 /*
160 Realistically, we should never get a valid pointer with a value of 0
161 Markus: 'Id est NULL.'
162 */
163 if (run == nullptr) {
164 log_error("Couldn't find symbol: %s", symbol);
165 return nullptr;
166 } else {
167 log_debug("Found symbol %s @ %p", symbol, (void *)run);
168 }
169
170 return (entrypoint*)(run);
171 }
172
173 } // end of gnash namespace
174