1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #include "osclconfig_lib.h"
19 #include "oscl_shared_library.h"
20 #include "oscl_string.h"
21 #include "pvlogger.h"
22 #include "oscl_utf8conv.h"
23 #include "oscl_uuid.h"
24 #include "oscl_file_types.h"
25
26 #define BUFFER_SIZE 256
27
28 typedef OsclSharedLibraryInterface*(*PVGetInterface_t)();
29 typedef void (*PVReleaseInterface_t)(OsclSharedLibraryInterface*);
30
OsclSharedLibrary()31 OSCL_EXPORT_REF OsclSharedLibrary::OsclSharedLibrary()
32 {
33 ipLogger = PVLogger::GetLoggerObject("oscllib");
34 #if OSCL_LIBRARY_PERF_LOGGING
35 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.oscllib.osclsharedlibrary");
36 iLibCount = 0;
37 iLibLoadTime = 0;
38 #endif
39 pSharedLibInterface = NULL;
40 iRefCount = 0;
41 ipHandle = NULL;
42
43 }
44
OsclSharedLibrary(const OSCL_String & aPath)45 OSCL_EXPORT_REF OsclSharedLibrary::OsclSharedLibrary(const OSCL_String& aPath)
46 {
47 ipLogger = PVLogger::GetLoggerObject("oscllib");
48 #if OSCL_LIBRARY_PERF_LOGGING
49 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.oscllib.osclsharedlibrary");
50 iLibCount = 0;
51 iLibLoadTime = 0;
52 #endif
53 pSharedLibInterface = NULL;
54
55 iRefCount = 0;
56 ipHandle = NULL;
57 iLibPath = aPath;
58 }
59
~OsclSharedLibrary()60 OSCL_EXPORT_REF OsclSharedLibrary::~OsclSharedLibrary()
61 {
62 #if OSCL_LIBRARY_PERF_LOGGING
63 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
64 (0, "OsclSharedLibrary - Loading %d libraries took %d ticks ...", iLibCount, iLibLoadTime));
65 iDiagnosticsLogger = NULL;
66 #endif
67 ipLogger = NULL;
68
69 if (NULL != ipHandle)
70 {
71 Close();
72 }
73 }
74
LoadLib(const OSCL_String & aPath)75 OSCL_EXPORT_REF OsclLibStatus OsclSharedLibrary::LoadLib(const OSCL_String& aPath)
76 {
77 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, (0, "OsclSharedLibrary::LoadLib %s IN", aPath.get_cstr()));
78 #if OSCL_LIBRARY_PERF_LOGGING
79 iLibCount++;
80 TICK starttime;
81 SET_TICK(starttime);
82 #endif
83 iLibPath = aPath;
84 // First look for debug version of the library ending with _debug
85 int32 dotpos = aPath.get_size() - 1;
86 while (dotpos >= 0)
87 {
88 if (aPath[dotpos] == '.')
89 break;
90 dotpos--;
91 }
92 if (dotpos >= 0 && dotpos != (int32)(aPath.get_size() - 1))
93 { // extension exists
94 #if OSCL_LIB_READ_DEBUG_LIBS
95 OSCL_HeapString<OsclMemAllocator> path1(aPath.get_cstr(), dotpos);
96 OSCL_HeapString<OsclMemAllocator> debugPath(path1);
97 debugPath += "_debug";
98 debugPath += (aPath.get_cstr() + dotpos);
99 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, (0, "OsclSharedLibrary::LoadLib looking for Debug lib %s", debugPath.get_cstr()));
100 // Open the library
101 if (OsclLibSuccess == loadlibrary(debugPath))
102 {
103 #if OSCL_LIBRARY_PERF_LOGGING
104 DIFF_TICK(starttime, delta);
105 iLibLoadTime += delta;
106 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
107 (0, "OsclSharedLibrary - Loading library %s took %d ticks ...", debugPath.get_cstr(), delta));
108 #endif
109 return OsclLibSuccess; // debug dll loaded successfully
110 }
111 // _debug load failed, try original
112 #endif
113 if (OsclLibSuccess == loadlibrary(aPath))
114 {
115 #if OSCL_LIBRARY_PERF_LOGGING
116 DIFF_TICK(starttime, delta);
117 iLibLoadTime += delta;
118 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
119 (0, "OsclSharedLibrary - Loading library %s took %d ticks ...", aPath.get_cstr(), delta));
120 #endif
121 return OsclLibSuccess;
122 }
123 return OsclLibFail;
124 }
125 else if (dotpos == (int32)(aPath.get_size() - 1))
126 { // libname ended with "." no extension
127 OSCL_HeapString<OsclMemAllocator> path1(aPath.get_cstr(), dotpos);
128 OSCL_HeapString<OsclMemAllocator> debugPath(path1);
129 #if OSCL_LIB_READ_DEBUG_LIBS
130 debugPath += "_debug.";
131 debugPath += PV_RUNTIME_LIB_FILENAME_EXTENSION;
132 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, (0, "OsclSharedLibrary::LoadLib looking for Debug lib %s", debugPath.get_cstr()));
133 // Open the library
134 if (OsclLibSuccess == loadlibrary(debugPath))
135 {
136 #if OSCL_LIBRARY_PERF_LOGGING
137 DIFF_TICK(starttime, delta);
138 iLibLoadTime += delta;
139 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
140 (0, "OsclSharedLibrary - Loading library %s took %d ticks ...", debugPath.get_cstr(), delta));
141 #endif
142 return OsclLibSuccess; // debug dll loaded successfully
143 }
144 // _debug load failed, try original
145 debugPath = path1;
146 #endif
147 debugPath += PV_RUNTIME_LIB_FILENAME_EXTENSION;
148 if (OsclLibSuccess == loadlibrary(debugPath))
149 {
150 #if OSCL_LIBRARY_PERF_LOGGING
151 DIFF_TICK(starttime, delta);
152 iLibLoadTime += delta;
153 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
154 (0, "OsclSharedLibrary - Loading library %s took %d ticks ...", debugPath.get_cstr(), delta));
155 #endif
156 return OsclLibSuccess;
157 }
158 return OsclLibFail;
159 }
160 else // libname without extension
161 {
162 OSCL_HeapString<OsclMemAllocator> path1(aPath.get_cstr());
163 OSCL_HeapString<OsclMemAllocator> debugPath(path1);
164 #if OSCL_LIB_READ_DEBUG_LIBS
165 debugPath += "_debug.";
166 debugPath += PV_RUNTIME_LIB_FILENAME_EXTENSION;
167 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, (0, "OsclSharedLibrary::LoadLib looking for Debug lib %s", debugPath.get_cstr()));
168 // Open the library
169 if (OsclLibSuccess == loadlibrary(debugPath))
170 {
171 #if OSCL_LIBRARY_PERF_LOGGING
172 DIFF_TICK(starttime, delta);
173 iLibLoadTime += delta;
174 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
175 (0, "OsclSharedLibrary - Loading library %s took %d ticks ...", debugPath.get_cstr(), delta));
176 #endif
177 return OsclLibSuccess; // debug dll loaded successfully
178 }
179 // _debug load failed, try original
180 debugPath = path1;
181 #endif
182 debugPath += ".";
183 debugPath += PV_RUNTIME_LIB_FILENAME_EXTENSION;
184 if (OsclLibSuccess == loadlibrary(debugPath))
185 {
186 #if OSCL_LIBRARY_PERF_LOGGING
187 DIFF_TICK(starttime, delta);
188 iLibLoadTime += delta;
189 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO,
190 (0, "OsclSharedLibrary - Loading library %s took %d ticks ...", debugPath.get_cstr(), delta));
191 #endif
192 return OsclLibSuccess;
193 }
194 return OsclLibFail;
195 }
196
197 }
198
LoadLib()199 OSCL_EXPORT_REF OsclLibStatus OsclSharedLibrary::LoadLib()
200 {
201 return LoadLib(iLibPath);
202 }
203
SetLibPath(const OSCL_String & aPath)204 OSCL_EXPORT_REF void OsclSharedLibrary::SetLibPath(const OSCL_String& aPath)
205 {
206 iLibPath = aPath;
207 }
208
QueryInterface(const OsclUuid & aInterfaceId,OsclAny * & aInterfacePtr)209 OSCL_EXPORT_REF OsclLibStatus OsclSharedLibrary::QueryInterface(const OsclUuid& aInterfaceId,
210 OsclAny*& aInterfacePtr)
211 {
212 aInterfacePtr = NULL;
213 // Look up the PVGetInterface method
214 if (NULL == ipHandle)
215 {
216 return OsclLibNotLoaded;
217 }
218 PVGetInterface_t getInterface =
219 (PVGetInterface_t)dlsym(ipHandle, "PVGetInterface");
220 // dlsym() returns NULL if there were any issues getting the
221 // address of the symbol
222 if (NULL == getInterface)
223 {
224 // check for errors
225 const char* pErr = dlerror();
226 if (NULL == pErr)
227 {
228 // No error reported, but no symbol was found
229 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_INFO,
230 (0, "OsclLib::QueryInterface: Could not access PVGetInterface "
231 "symbol in library but no error reported"));
232 }
233 else
234 {
235 // Error reported
236 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_INFO,
237 (0, "OsclLib::QueryInterface: Could not access PVGetInterface "
238 "symbol in library: %s", pErr));
239 }
240 return OsclLibFail;
241 }
242
243 // Get the OsclSharedLibraryInterface if needed. There can be multiple calls
244 // to query interface so check whether the interface has already been fetched.
245 if (!pSharedLibInterface)
246 {
247 pSharedLibInterface = (OsclSharedLibraryInterface*)getInterface();
248 }
249 if (NULL == pSharedLibInterface)
250 {
251 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_INFO,
252 (0, "OsclSharedLibrary::QueryInterface: Could not access the "
253 "library pointer function"));
254 return OsclLibFail;
255 }
256 // Lookup the interface ID
257 aInterfacePtr = pSharedLibInterface->SharedLibraryLookup(aInterfaceId);
258 if (NULL == aInterfacePtr)
259 {
260 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_INFO,
261 (0, "OsclLib::QueryInterface: NO library interface found for aInterfaceId."));
262 return OsclLibFail;
263 }
264 return OsclLibSuccess;
265 }
266
Close()267 OSCL_EXPORT_REF OsclLibStatus OsclSharedLibrary::Close()
268 {
269 if (iRefCount > 0)
270 {
271 return OsclLibFail;
272 }
273 if (pSharedLibInterface)
274 {
275 PVReleaseInterface_t releaseInterface =
276 (PVReleaseInterface_t)dlsym(ipHandle, "PVReleaseInterface");
277 // dlsym() returns NULL if there were any issues getting the
278 // address of the symbol
279 if (NULL == releaseInterface)
280 {
281 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_ERR,
282 (0, "OsclLib::Close: Could not access "
283 "PVReleaseInterface symbol in library - Possible memory leak."));
284 // check for errors
285 const char* pErr = dlerror();
286 if (NULL == pErr)
287 {
288 // No error reported, but no symbol was found
289 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_INFO,
290 (0, "OsclLib::Close: Could not access PVReleaseInterface "
291 "symbol in library but no error reported"));
292 }
293 else
294 {
295 // Error reported
296 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_INFO,
297 (0, "OsclLib::Close: Could not access PVReleaseInterface "
298 "symbol in library: %s", pErr));
299 }
300 dlclose(ipHandle);
301 pSharedLibInterface = NULL;
302 }
303 else
304 {
305 releaseInterface(pSharedLibInterface);
306 pSharedLibInterface = NULL;
307 }
308 }
309
310 if (ipHandle)
311 {
312 if (0 != dlclose(ipHandle))
313 {
314 // dlclose() returns non-zero value if close failed, check for errors
315 const char* pErr = dlerror();
316 if (NULL != pErr)
317 {
318 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_WARNING,
319 (0, "OsclSharedLibrary::Close: Error closing library: %s", pErr));
320 }
321 else
322 {
323 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_WARNING,
324 (0, "OsclSharedLibrary::Close: Error closing library, no error reported"
325 ""));
326 }
327 return OsclLibFail;
328 }
329 ipHandle = NULL;
330 }
331 return OsclLibSuccess;
332 }
333
AddRef()334 OSCL_EXPORT_REF void OsclSharedLibrary::AddRef()
335 {
336 ++iRefCount;
337 }
338
RemoveRef()339 OSCL_EXPORT_REF void OsclSharedLibrary::RemoveRef()
340 {
341 --iRefCount;
342 }
343
344 //
345 //OsclSharedLibraryList
346 //
347 #include "oscl_configfile_list.h"
348 #include "oscl_library_list.h"
349
OsclSharedLibraryList()350 OSCL_EXPORT_REF OsclSharedLibraryList::OsclSharedLibraryList()
351 {
352 iLogger = PVLogger::GetLoggerObject("oscllib");
353 }
354
~OsclSharedLibraryList()355 OSCL_EXPORT_REF OsclSharedLibraryList::~OsclSharedLibraryList()
356 {
357 CloseAll();
358 }
359 /*
360 ** Give a config file path, search all config files for libraries that
361 ** support the given interface ID.
362 */
Populate(const OSCL_String & aPath,const OsclUuid & aInterfaceId)363 OSCL_EXPORT_REF void OsclSharedLibraryList::Populate(const OSCL_String& aPath, const OsclUuid& aInterfaceId)
364 {
365 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
366 (0, "OsclSharedLibraryList::Populate '%s' IN", aPath.get_cstr()));
367
368 iInterfaceId = aInterfaceId;
369 OsclConfigFileList configFileList;
370 configFileList.Populate(aPath);
371 for (uint32 i = 0; i < configFileList.Size(); i++)
372 {
373 OsclLibraryList libList;
374 libList.Populate(aInterfaceId, configFileList.GetConfigfileAt(i));
375 for (uint32 j = 0; j < libList.Size(); j++)
376 {
377 OsclSharedLibrary* sharedLib = OSCL_NEW(OsclSharedLibrary, (libList.GetLibraryPathAt(j)));
378 iList.push_back(sharedLib);
379 }
380 }
381 }
382
383 /*
384 ** Query interface for the given library.
385 */
QueryInterfaceAt(uint32 aIndex,OsclAny * & aInterfacePtr)386 OSCL_EXPORT_REF OsclLibStatus OsclSharedLibraryList::QueryInterfaceAt(uint32 aIndex, OsclAny*& aInterfacePtr)
387 {
388 aInterfacePtr = NULL;
389 OsclLibStatus status = OsclLibFail;
390
391 if (aIndex < iList.size())
392 {
393 status = iList[aIndex]->QueryInterface(iInterfaceId, aInterfacePtr);
394 //Load lib if needed & repeat the query.
395 if (status == OsclLibNotLoaded)
396 {
397 status = iList[aIndex]->LoadLib();
398 if (status == OsclLibSuccess)
399 status = iList[aIndex]->QueryInterface(iInterfaceId, aInterfacePtr);
400 }
401 }
402 return status;
403 }
404
405 /*
406 ** Close all open libraries
407 */
CloseAll()408 OSCL_EXPORT_REF void OsclSharedLibraryList::CloseAll()
409 {
410 while (!iList.empty())
411 {
412 iList.front()->Close();
413 OSCL_DELETE(iList.front());
414 iList.erase(&iList.front());
415 }
416 }
417
loadlibrary(const OSCL_String & alib)418 OsclLibStatus OsclSharedLibrary::loadlibrary(const OSCL_String& alib)
419 {
420 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, ipLogger, PVLOGMSG_DEBUG, (0, "OsclSharedLibrary::loadlibrary %s IN", alib.get_cstr()));
421 // Clear any errors
422 dlerror();
423 // Open the library
424 void* library = dlopen(alib.get_cstr(), RTLD_NOW);
425 // dlopen() returns NULL if there were any issues opening the library
426 if (NULL == library)
427 {
428 // check for errors
429 const char* pErr = dlerror();
430 if (NULL == pErr)
431 {
432 // No error reported, but no handle to the library
433 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_WARNING,
434 (0, "OsclLib::loadlibrary: Error opening "
435 "library (%s) but no error reported",
436 alib.get_cstr(), pErr));
437 }
438 else
439 {
440 // Error reported
441 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, ipLogger, PVLOGMSG_WARNING,
442 (0, "OsclLib::loadlibrary: Error opening "
443 "library (%s): %s", alib.get_cstr(), pErr));
444 }
445 return OsclLibFail;
446 }
447 ipHandle = library;
448 return OsclLibSuccess;
449
450 }
451
452