• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "plugins/ets/runtime/ets_native_library_provider.h"
17 
18 #include "ets_native_library.h"
19 #include "include/mem/panda_containers.h"
20 #include "include/mem/panda_string.h"
21 #include "plugins/ets/runtime/napi/ets_napi_invoke_interface.h"
22 
23 namespace ark::ets {
24 
25 namespace {
26 
LoadFromPath(const PandaVector<PandaString> & pathes,const PandaString & name)27 Expected<EtsNativeLibrary, os::Error> LoadFromPath(const PandaVector<PandaString> &pathes, const PandaString &name)
28 {
29     if (name.find('/') == std::string::npos) {
30         for (const auto &path : pathes) {
31             if (path.empty()) {
32                 continue;
33             }
34             PandaStringStream s;
35             s << path << '/' << name;
36             if (auto loadRes = EtsNativeLibrary::Load(s.str())) {
37                 return loadRes;
38             }
39         }
40     }
41     return EtsNativeLibrary::Load(name);
42 }
43 
44 }  // namespace
45 
LoadLibrary(EtsEnv * env,const PandaString & name)46 std::optional<std::string> NativeLibraryProvider::LoadLibrary(EtsEnv *env, const PandaString &name)
47 {
48     {
49         os::memory::ReadLockHolder lock(lock_);
50 
51         auto it =
52             std::find_if(libraries_.begin(), libraries_.end(), [&name](auto &lib) { return lib.GetName() == name; });
53         if (it != libraries_.end()) {
54             return {};
55         }
56     }
57 
58     auto loadRes = LoadFromPath(GetLibraryPath(), name);
59     if (!loadRes) {
60         return loadRes.Error().ToString();
61     }
62 
63     const EtsNativeLibrary *lib = nullptr;
64     {
65         os::memory::WriteLockHolder lock(lock_);
66 
67         auto [it, inserted] = libraries_.emplace(std::move(loadRes.Value()));
68         if (!inserted) {
69             return {};
70         }
71 
72         lib = &*it;
73     }
74     ASSERT(lib != nullptr);
75 
76     if (auto onLoadSymbol = lib->FindSymbol("EtsNapiOnLoad")) {
77         using EtsNapiOnLoadHandle = ets_int (*)(EtsEnv *);
78         auto onLoadHandle = reinterpret_cast<EtsNapiOnLoadHandle>(onLoadSymbol.Value());
79         ets_int etsNapiVersion = onLoadHandle(env);
80         if (!napi::CheckVersionEtsNapi(etsNapiVersion)) {
81             return {"Unsupported Ets napi version " + std::to_string(etsNapiVersion)};
82         }
83     }
84 
85     return {};
86 }
87 
ResolveSymbol(const PandaString & name) const88 void *NativeLibraryProvider::ResolveSymbol(const PandaString &name) const
89 {
90     os::memory::ReadLockHolder lock(lock_);
91 
92     for (auto &lib : libraries_) {
93         if (auto ptr = lib.FindSymbol(name)) {
94             return ptr.Value();
95         }
96     }
97 
98     return nullptr;
99 }
100 
GetLibraryPath() const101 PandaVector<PandaString> NativeLibraryProvider::GetLibraryPath() const
102 {
103     os::memory::ReadLockHolder lock(lock_);
104     return libraryPath_;
105 }
106 
SetLibraryPath(const PandaVector<PandaString> & pathes)107 void NativeLibraryProvider::SetLibraryPath(const PandaVector<PandaString> &pathes)
108 {
109     os::memory::WriteLockHolder lock(lock_);
110     libraryPath_ = pathes;
111 }
112 
AddLibraryPath(const PandaString & path)113 void NativeLibraryProvider::AddLibraryPath(const PandaString &path)
114 {
115     os::memory::WriteLockHolder lock(lock_);
116     libraryPath_.emplace_back(path);
117 }
118 
119 }  // namespace ark::ets
120