• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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