LCOV - code coverage report
Current view: top level - port - cplgetsymbol.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 6 10 60.0 %
Date: 2024-11-21 22:18:42 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Common Portability Library
       4             :  * Purpose:  Fetch a function pointer from a shared library / DLL.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam
       9             :  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "cpl_conv.h"
      16             : 
      17             : #include <cstddef>
      18             : 
      19             : #include "cpl_config.h"
      20             : #include "cpl_error.h"
      21             : #include "cpl_string.h"
      22             : 
      23             : /* ==================================================================== */
      24             : /*                  Unix Implementation                                 */
      25             : /* ==================================================================== */
      26             : 
      27             : /* MinGW32 might define HAVE_DLFCN_H, so skip the unix implementation */
      28             : #if defined(HAVE_DLFCN_H) && !defined(_WIN32)
      29             : 
      30             : #define GOT_GETSYMBOL
      31             : 
      32             : #include <dlfcn.h>
      33             : 
      34             : /************************************************************************/
      35             : /*                            CPLGetSymbol()                            */
      36             : /************************************************************************/
      37             : 
      38             : /**
      39             :  * Fetch a function pointer from a shared library / DLL.
      40             :  *
      41             :  * This function is meant to abstract access to shared libraries and
      42             :  * DLLs and performs functions similar to dlopen()/dlsym() on Unix and
      43             :  * LoadLibrary() / GetProcAddress() on Windows.
      44             :  *
      45             :  * If no support for loading entry points from a shared library is available
      46             :  * this function will always return NULL.   Rules on when this function
      47             :  * issues a CPLError() or not are not currently well defined, and will have
      48             :  * to be resolved in the future.
      49             :  *
      50             :  * Currently CPLGetSymbol() doesn't try to:
      51             :  * <ul>
      52             :  *  <li> prevent the reference count on the library from going up
      53             :  *    for every request, or given any opportunity to unload
      54             :  *    the library.
      55             :  *  <li> Attempt to look for the library in non-standard
      56             :  *    locations.
      57             :  *  <li> Attempt to try variations on the symbol name, like
      58             :  *    pre-pending or post-pending an underscore.
      59             :  * </ul>
      60             :  *
      61             :  * Some of these issues may be worked on in the future.
      62             :  *
      63             :  * @param pszLibrary the name of the shared library or DLL containing
      64             :  * the function.  May contain path to file.  If not system supplies search
      65             :  * paths will be used.
      66             :  * @param pszSymbolName the name of the function to fetch a pointer to.
      67             :  * @return A pointer to the function if found, or NULL if the function isn't
      68             :  * found, or the shared library can't be loaded.
      69             :  */
      70             : 
      71         485 : void *CPLGetSymbol(const char *pszLibrary, const char *pszSymbolName)
      72             : 
      73             : {
      74         485 :     void *pLibrary = dlopen(pszLibrary, RTLD_LAZY);
      75         485 :     if (pLibrary == nullptr)
      76             :     {
      77           0 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", dlerror());
      78           0 :         return nullptr;
      79             :     }
      80             : 
      81         485 :     void *pSymbol = dlsym(pLibrary, pszSymbolName);
      82             : 
      83             : #if (defined(__APPLE__) && defined(__MACH__))
      84             :     /* On mach-o systems, C symbols have a leading underscore and depending
      85             :      * on how dlcompat is configured it may or may not add the leading
      86             :      * underscore.  If dlsym() fails, add an underscore and try again.
      87             :      */
      88             :     if (pSymbol == nullptr)
      89             :     {
      90             :         char withUnder[256] = {};
      91             :         snprintf(withUnder, sizeof(withUnder), "_%s", pszSymbolName);
      92             :         pSymbol = dlsym(pLibrary, withUnder);
      93             :     }
      94             : #endif
      95             : 
      96         485 :     if (pSymbol == nullptr)
      97             :     {
      98           0 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", dlerror());
      99             :         // Do not call dlclose here.  misc.py:misc_6() demonstrates the crash.
     100             :         // coverity[leaked_storage]
     101           0 :         return nullptr;
     102             :     }
     103             : 
     104             :     // coverity[leaked_storage]  It is not safe to call dlclose.
     105         485 :     return (pSymbol);
     106             : }
     107             : 
     108             : #endif /* def __unix__ && defined(HAVE_DLFCN_H) */
     109             : 
     110             : /* ==================================================================== */
     111             : /*                 Windows Implementation                               */
     112             : /* ==================================================================== */
     113             : #if defined(_WIN32)
     114             : 
     115             : #define GOT_GETSYMBOL
     116             : 
     117             : #include <windows.h>
     118             : 
     119             : /************************************************************************/
     120             : /*                            CPLGetSymbol()                            */
     121             : /************************************************************************/
     122             : 
     123             : void *CPLGetSymbol(const char *pszLibrary, const char *pszSymbolName)
     124             : 
     125             : {
     126             :     void *pLibrary = nullptr;
     127             :     void *pSymbol = nullptr;
     128             : 
     129             :     // Avoid error boxes to pop up (#5211, #5525).
     130             :     UINT uOldErrorMode =
     131             :         SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
     132             : 
     133             : #if defined(_MSC_VER) || __MSVCRT_VERSION__ >= 0x0601
     134             :     if (CPLTestBool(CPLGetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")))
     135             :     {
     136             :         wchar_t *pwszFilename =
     137             :             CPLRecodeToWChar(pszLibrary, CPL_ENC_UTF8, CPL_ENC_UCS2);
     138             :         pLibrary = LoadLibraryW(pwszFilename);
     139             :         CPLFree(pwszFilename);
     140             :     }
     141             :     else
     142             : #endif
     143             :     {
     144             :         pLibrary = LoadLibraryA(pszLibrary);
     145             :     }
     146             : 
     147             :     if (pLibrary <= (void *)HINSTANCE_ERROR)
     148             :     {
     149             :         LPVOID lpMsgBuf = nullptr;
     150             :         int nLastError = GetLastError();
     151             : 
     152             :         // Restore old error mode.
     153             :         SetErrorMode(uOldErrorMode);
     154             : 
     155             :         FormatMessage(
     156             :             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
     157             :                 FORMAT_MESSAGE_IGNORE_INSERTS,
     158             :             nullptr, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     159             :             reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
     160             : 
     161             :         CPLError(CE_Failure, CPLE_AppDefined,
     162             :                  "Can't load requested DLL: %s\n%d: %s", pszLibrary, nLastError,
     163             :                  static_cast<const char *>(lpMsgBuf));
     164             :         return nullptr;
     165             :     }
     166             : 
     167             :     // Restore old error mode.
     168             :     SetErrorMode(uOldErrorMode);
     169             : 
     170             :     pSymbol = reinterpret_cast<void *>(
     171             :         GetProcAddress(static_cast<HINSTANCE>(pLibrary), pszSymbolName));
     172             : 
     173             :     if (pSymbol == nullptr)
     174             :     {
     175             :         CPLError(CE_Failure, CPLE_AppDefined,
     176             :                  "Can't find requested entry point: %s", pszSymbolName);
     177             :         return nullptr;
     178             :     }
     179             : 
     180             :     return (pSymbol);
     181             : }
     182             : 
     183             : #endif  // def _WIN32
     184             : 
     185             : /* ==================================================================== */
     186             : /*      Dummy implementation.                                           */
     187             : /* ==================================================================== */
     188             : 
     189             : #ifndef GOT_GETSYMBOL
     190             : 
     191             : /************************************************************************/
     192             : /*                            CPLGetSymbol()                            */
     193             : /*                                                                      */
     194             : /*      Dummy implementation.                                           */
     195             : /************************************************************************/
     196             : 
     197             : void *CPLGetSymbol(const char *pszLibrary, const char *pszEntryPoint)
     198             : 
     199             : {
     200             :     CPLDebug("CPL",
     201             :              "CPLGetSymbol(%s,%s) called.  Failed as this is stub"
     202             :              " implementation.",
     203             :              pszLibrary, pszEntryPoint);
     204             :     return nullptr;
     205             : }
     206             : #endif

Generated by: LCOV version 1.14