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 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 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 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 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 199 OSCL_EXPORT_REF OsclLibStatus OsclSharedLibrary::LoadLib() 200 { 201 return LoadLib(iLibPath); 202 } 203 204 OSCL_EXPORT_REF void OsclSharedLibrary::SetLibPath(const OSCL_String& aPath) 205 { 206 iLibPath = aPath; 207 } 208 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 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 334 OSCL_EXPORT_REF void OsclSharedLibrary::AddRef() 335 { 336 ++iRefCount; 337 } 338 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 350 OSCL_EXPORT_REF OsclSharedLibraryList::OsclSharedLibraryList() 351 { 352 iLogger = PVLogger::GetLoggerObject("oscllib"); 353 } 354 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 */ 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 */ 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 */ 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 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