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