LCOV - code coverage report
Current view: top level - core/core/utils - SPDso.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 57 63 90.5 %
Date: 2024-05-12 00:16:13 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "SPDso.h"
      24             : #include "SPMemory.h"
      25             : 
      26             : #if LINUX || ANDROID
      27             : 
      28             : #include <dlfcn.h>
      29             : 
      30             : namespace STAPPLER_VERSIONIZED stappler::dso {
      31             : 
      32         375 : static void * dso_open(StringView name, DsoFlags flags, const char **err) {
      33         375 :         void *h = nullptr;
      34         375 :         int f = 0;
      35         375 :         if ((flags & DsoFlags::Lazy) != DsoFlags::None) {
      36         325 :                 f |= RTLD_LAZY;
      37             :         }
      38         375 :         if ((flags & DsoFlags::Global) != DsoFlags::None) {
      39           0 :                 f |= RTLD_GLOBAL;
      40             :         }
      41         375 :         if ((flags & DsoFlags::Self) != DsoFlags::None) {
      42          50 :                 h = ::dlopen(nullptr, RTLD_LAZY);
      43             :         } else {
      44         325 :                 h = ::dlopen(name.terminated() ? name.data() : name.str<mem_std::Interface>().data(), f);
      45             :         }
      46         375 :         if (!h) {
      47          50 :                 *err = ::dlerror();
      48             :         }
      49         375 :         return h;
      50             : }
      51             : 
      52         300 : static void dso_close(DsoFlags flags, void *handle) {
      53         300 :         if (handle) {
      54         300 :                 ::dlclose(handle);
      55             :         }
      56         300 : }
      57             : 
      58        5700 : static void * dso_sym(void *h, StringView name, const char **err) {
      59        5700 :         auto s = ::dlsym(h, name.terminated() ? name.data() : name.str<mem_std::Interface>().data());
      60        5700 :         if (!s) {
      61           0 :                 *err = ::dlerror();
      62             :         }
      63        5700 :         return s;
      64             : }
      65             : 
      66             : }
      67             : 
      68             : #endif
      69             : 
      70             : #if WIN32
      71             : 
      72             : #include "SPPlatformUnistd.h"
      73             : #include <libloaderapi.h>
      74             : 
      75             : namespace STAPPLER_VERSIONIZED stappler::dso {
      76             : 
      77             : static constexpr const char *WIN_FAIL_TO_LOAD = "Fail to load dynamic object";
      78             : static constexpr const char *WIN_SYMBOL_NOT_FOUND = "Fail to find symbol in dynamic object";
      79             : 
      80             : static void * dso_open(StringView name, DsoFlags flags, const char **err) {
      81             :         HMODULE h = NULL;
      82             :         if ((flags & DsoFlags::Self) != DsoFlags::None) {
      83             :                 h = GetModuleHandleA(nullptr);
      84             :         } else {
      85             :                 h = LoadLibraryA(LPCSTR(name.terminated() ? name.data() : name.str<mem_std::Interface>().data()));
      86             :         }
      87             : 
      88             :         if (!h) {
      89             :                 *err = WIN_FAIL_TO_LOAD;
      90             :         }
      91             :         return (void *)h;
      92             : }
      93             : 
      94             : static void dso_close(DsoFlags flags, void *handle) {
      95             :         if (handle) {
      96             :                 if ((flags & DsoFlags::Self) == DsoFlags::None) {
      97             :                         FreeLibrary(HMODULE(handle));
      98             :                 }
      99             :         }
     100             : }
     101             : 
     102             : static void * dso_sym(void *h, StringView name, const char **err) {
     103             :         auto s = GetProcAddress(HMODULE(h), name.terminated() ? name.data() : name.str<mem_std::Interface>().data());
     104             :         if (!s) {
     105             :                 *err = WIN_SYMBOL_NOT_FOUND;
     106             :         }
     107             :         return (void *)s;
     108             : }
     109             : 
     110             : }
     111             : 
     112             : #endif
     113             : 
     114             : namespace STAPPLER_VERSIONIZED stappler {
     115             : 
     116             : static constexpr const char *ERROR_MOVED_OUT = "Object was moved out";
     117             : static constexpr const char *ERROR_NOT_LOADED = "Object was not loaded";
     118             : 
     119         675 : Dso::~Dso() {
     120         675 :         if (_handle) {
     121         300 :                 close();
     122             :         }
     123         675 : }
     124             : 
     125         225 : Dso::Dso() { }
     126             : 
     127         325 : Dso::Dso(StringView name) : Dso(name, DsoFlags::Lazy) { }
     128             : 
     129         375 : Dso::Dso(StringView name, DsoFlags flags) {
     130         375 :         _handle = dso::dso_open(name, flags, &_error);
     131         375 : }
     132             : 
     133         100 : Dso::Dso(Dso &&other) {
     134         100 :         _flags = other._flags;
     135         100 :         _handle = other._handle;
     136         100 :         _error = other._error;
     137             : 
     138         100 :         other._flags = DsoFlags::None;
     139         100 :         other._handle = nullptr;
     140         100 :         other._error = ERROR_MOVED_OUT;
     141         100 : }
     142             : 
     143         225 : Dso & Dso::operator=(Dso &&other) {
     144         225 :         if (_handle) {
     145           0 :                 close();
     146             :         }
     147             : 
     148         225 :         _flags = other._flags;
     149         225 :         _handle = other._handle;
     150         225 :         _error = other._error;
     151             : 
     152         225 :         other._flags = DsoFlags::None;
     153         225 :         other._handle = nullptr;
     154         225 :         other._error = ERROR_MOVED_OUT;
     155         225 :         return *this;
     156             : }
     157             : 
     158         300 : void Dso::close() {
     159         300 :         if (_handle) {
     160         300 :                 dso::dso_close(_flags, _handle);
     161         300 :                 _handle = nullptr;
     162         300 :                 _flags = DsoFlags::None;
     163             :         } else {
     164           0 :                 _error = ERROR_NOT_LOADED;
     165             :         }
     166         300 : }
     167             : 
     168        5700 : void *Dso::loadSym(StringView name) {
     169        5700 :         if (_handle) {
     170        5700 :                 if (auto s = dso::dso_sym(_handle, name, &_error)) {
     171        5700 :                         _error = nullptr;
     172        5700 :                         return s;
     173             :                 }
     174             :         } else {
     175           0 :                 _error = ERROR_NOT_LOADED;
     176             :         }
     177           0 :         return nullptr;
     178             : }
     179             : 
     180             : }

Generated by: LCOV version 1.14