blocxx
dlSharedLibrary.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
38 #include "blocxx/BLOCXX_config.h"
39 #if defined(BLOCXX_USE_DL)
41 #include "blocxx/Format.hpp"
42 #include "blocxx/Mutex.hpp"
43 #include "blocxx/MutexLock.hpp"
44 #include "blocxx/GlobalMutex.hpp"
45 #include <dlfcn.h>
46 #ifdef BLOCXX_HAVE_FCNTL_H
47 // For O_RDONLY
48 #include <fcntl.h>
49 #endif
50 
51 #include "blocxx/Types.hpp"
52 
53 #if defined(BLOCXX_USE_FAKE_LIBS)
54 
55 #include "blocxx/FileSystem.hpp"
56 #include "blocxx/File.hpp"
57 #include "blocxx/Array.hpp"
58 
59 #define BLOCXX_FAKELIB_HEADING "FAKE"
60 #define BLOCXX_FAKELIB_HEADING_LENGTH 4
61 
62 #endif
63 
64 #include <iostream>
65 
66 namespace BLOCXX_NAMESPACE
67 {
68 
69 // static
70 bool dlSharedLibrary::s_call_dlclose = true;
71 
72 GlobalMutex dlSharedLibrary_guard = BLOCXX_GLOBAL_MUTEX_INIT();
73 
74 dlSharedLibrary::dlSharedLibrary(void * libhandle, const String& libName)
75  : SharedLibrary(), m_libhandle( libhandle ), m_libName(libName)
76 {
77 #if defined(BLOCXX_USE_FAKE_LIBS)
78  // Find out if it is a fake library.
79  m_fakeLibrary = dlSharedLibrary::isFakeLibrary(libName);
80 
81  if ( m_fakeLibrary )
82  {
83  initializeSymbolMap();
84  }
85 #endif /* defined(BLOCXX_USE_FAKE_LIBS) */
86 }
87 
88 dlSharedLibrary::~dlSharedLibrary()
89 {
90 #if !defined(BLOCXX_VALGRIND_SUPPORT) // dlclose()ing shared libs make it impossible to see where memory leaks occurred with valgrind.
91  if (s_call_dlclose)
92  {
93  dlclose( m_libhandle );
94  }
95 #endif
96 }
97 bool dlSharedLibrary::doGetFunctionPointer(const String& functionName,
98  void** fp) const
99 {
100  MutexLock l(dlSharedLibrary_guard);
101 #if defined(BLOCXX_USE_FAKE_LIBS)
102  String realFunctionName = functionName;
103  // If this is a fake library, extract convert the requested function
104  // name into the proper function name for the main executable.
105  if ( m_fakeLibrary )
106  {
107  Map<String,String>::const_iterator symIter = m_symbolMap.find(functionName);
108  if ( symIter == m_symbolMap.end() )
109  {
110  return false;
111  }
112  realFunctionName = symIter->second;
113  }
114  *fp = dlsym( m_libhandle, realFunctionName.c_str() );
115 #else
116  *fp = dlsym( m_libhandle, functionName.c_str() );
117 #endif /* defined(BLOCXX_USE_FAKE_LIBS) */
118 
119  if (!*fp)
120  {
121  return false;
122  }
123  return true;
124 }
125 
126 bool dlSharedLibrary::isFakeLibrary(const String& library_path)
127 {
128  bool fake = false;
129 #if defined(BLOCXX_USE_FAKE_LIBS)
130  if ( FileSystem::canRead(library_path) )
131  {
132  // Read the beginning of the file and see if it
133  // contains the fake library heading.
134  int libfd = open(library_path.c_str(), O_RDONLY);
135 
136  if ( libfd )
137  {
138  char buffer[(BLOCXX_FAKELIB_HEADING_LENGTH) + 1];
139  size_t num_read = read(libfd, buffer,(BLOCXX_FAKELIB_HEADING_LENGTH));
140  if ( num_read == (BLOCXX_FAKELIB_HEADING_LENGTH) )
141  {
142  // Null terminate it.
143  buffer[BLOCXX_FAKELIB_HEADING_LENGTH] = '\0';
144  if ( String(BLOCXX_FAKELIB_HEADING) == buffer )
145  {
146  // Yes, it's a fake library.
147  fake = true;
148  }
149  }
150  close(libfd);
151  }
152  }
153 #endif
154  return fake;
155 }
156 
157 #if defined(BLOCXX_USE_FAKE_LIBS)
158 void dlSharedLibrary::initializeSymbolMap()
159 {
160  if ( ! m_fakeLibrary )
161  {
162  return;
163  }
164  // Read the contents of the file to find out what the function names
165  // (normally available from dlsym) are mapped to functions in the main
166  // program.
167  StringArray lines = FileSystem::getFileLines(m_libName);
168 
169  for ( StringArray::const_iterator iter = lines.begin();
170  iter != lines.end();
171  ++iter )
172  {
173  // Skip commented lines.
174  if ( iter->startsWith('#') )
175  {
176  continue;
177  }
178  StringArray current_line = iter->tokenize("=");
179  // Skip invalid lines.
180  if ( current_line.size() != 2 )
181  {
182  continue;
183  }
184  // Add the data into the map.
185  String option = String(current_line[0]).trim();
186  String value = String(current_line[1]).trim();
187  m_symbolMap[option] = value;
188  }
189 }
190 #endif /* defined(BLOCXX_USE_FAKE_LIBS) */
191 
192 } // end namespace BLOCXX_NAMESPACE
193 
194 #endif
195