1 /*
2 * Copyright (c) 2021 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 "native_module_manager.h"
17
18 #include <cstring>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include <mutex>
23 #include <sstream>
24 #include <unistd.h>
25
26 #ifdef ENABLE_HITRACE
27 #include "hitrace_meter.h"
28 #endif
29 #include "module_load_checker.h"
30 #include "native_engine/native_engine.h"
31 #include "securec.h"
32 #include "utils/log.h"
33
34 #define NDK "ndk"
35 #define ALLOW_ALL_SHARED_LIBS "allow_all_shared_libs"
36
37 namespace {
38 constexpr static int32_t MODULE_PATH_SECONDARY_INDEX = 2;
39 constexpr static int32_t NATIVE_PATH_NUMBER = 3;
40 constexpr static int32_t IS_APP_MODULE_FLAGS = 100;
41 thread_local bool g_isLoadingModule = false;
42 enum ModuleLoadFailedReason : uint32_t {
43 MODULE_LOAD_SUCCESS = 0,
44 MODULE_NOT_EXIST = 1,
45 };
46 } // namespace
47
48 NativeModuleManager* NativeModuleManager::instance_ = NULL;
49 std::mutex g_instanceMutex;
50
NativeModuleManager()51 NativeModuleManager::NativeModuleManager()
52 {
53 HILOG_DEBUG("enter");
54 pthread_mutex_init(&mutex_, nullptr);
55 moduleLoadChecker_ = std::make_unique<ModuleLoadChecker>();
56 }
57
~NativeModuleManager()58 NativeModuleManager::~NativeModuleManager()
59 {
60 HILOG_INFO("enter");
61 {
62 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
63 NativeModule* nativeModule = headNativeModule_;
64 while (nativeModule != nullptr) {
65 nativeModule = nativeModule->next;
66 if (headNativeModule_->name) {
67 delete[] headNativeModule_->name;
68 }
69 if (headNativeModule_->moduleName) {
70 delete[] headNativeModule_->moduleName;
71 }
72 if (headNativeModule_->jsABCCode) {
73 delete[] headNativeModule_->jsABCCode;
74 }
75 delete headNativeModule_;
76 headNativeModule_ = nativeModule;
77 }
78 headNativeModule_ = nullptr;
79 tailNativeModule_ = nullptr;
80 }
81
82 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
83 !defined(LINUX_PLATFORM)
84 if (sharedLibsSonames_) {
85 delete[] sharedLibsSonames_;
86 }
87 #endif
88 appLibPathMapMutex_.lock();
89 for (const auto& item : appLibPathMap_) {
90 delete[] item.second;
91 }
92 std::map<std::string, char*>().swap(appLibPathMap_);
93 appLibPathMapMutex_.unlock();
94
95 while (nativeEngineList_.size() > 0) {
96 NativeEngine* wraper = nativeEngineList_.begin()->second;
97 if (wraper != nullptr) {
98 delete wraper;
99 wraper = nullptr;
100 }
101 nativeEngineList_.erase(nativeEngineList_.begin());
102 }
103 pthread_mutex_destroy(&mutex_);
104 }
105
GetInstance()106 NativeModuleManager* NativeModuleManager::GetInstance()
107 {
108 if (instance_ == NULL) {
109 std::lock_guard<std::mutex> lock(g_instanceMutex);
110 if (instance_ == NULL) {
111 instance_ = new NativeModuleManager();
112 HILOG_DEBUG("create native module manager instance");
113 }
114 }
115 return instance_;
116 }
117
SetNativeEngine(std::string moduleKey,NativeEngine * nativeEngine)118 void NativeModuleManager::SetNativeEngine(std::string moduleKey, NativeEngine* nativeEngine)
119 {
120 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
121 if (nativeEngine != nullptr) {
122 nativeEngine->SetModuleName(moduleKey);
123 }
124 std::lock_guard<std::mutex> lock(nativeEngineListMutex_);
125 nativeEngineList_.emplace(moduleKey, nativeEngine);
126 }
127
EmplaceModuleLib(std::string moduleKey,const LIBHANDLE lib)128 void NativeModuleManager::EmplaceModuleLib(std::string moduleKey, const LIBHANDLE lib)
129 {
130 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
131 std::lock_guard<std::mutex> lock(moduleLibMutex_);
132 if (lib != nullptr) {
133 moduleLibMap_.emplace(moduleKey, lib);
134 }
135 }
136
RemoveModuleLib(const std::string moduleKey)137 bool NativeModuleManager::RemoveModuleLib(const std::string moduleKey)
138 {
139 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
140 bool deleted = false;
141 std::lock_guard<std::mutex> lock(moduleLibMutex_);
142 auto it = moduleLibMap_.find(moduleKey);
143 if (it != moduleLibMap_.end()) {
144 moduleLibMap_.erase(it);
145 HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
146 deleted = true;
147 }
148 return deleted;
149 }
150
GetNativeModuleHandle(const std::string & moduleKey) const151 LIBHANDLE NativeModuleManager::GetNativeModuleHandle(const std::string& moduleKey) const
152 {
153 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
154 std::lock_guard<std::mutex> lock(moduleLibMutex_);
155 auto it = moduleLibMap_.find(moduleKey);
156 if (it == moduleLibMap_.end()) {
157 return nullptr;
158 }
159 return it->second;
160 }
161
EmplaceModuleBuffer(const std::string moduleKey,const uint8_t * lib)162 void NativeModuleManager::EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib)
163 {
164 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
165 std::lock_guard<std::mutex> lock(moduleBufMutex_);
166 if (lib != nullptr) {
167 moduleBufMap_.emplace(moduleKey, lib);
168 }
169 }
170
RemoveModuleBuffer(const std::string moduleKey)171 bool NativeModuleManager::RemoveModuleBuffer(const std::string moduleKey)
172 {
173 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
174 bool deleted = false;
175 std::lock_guard<std::mutex> lock(moduleBufMutex_);
176 auto it = moduleBufMap_.find(moduleKey);
177 if (it != moduleBufMap_.end()) {
178 moduleBufMap_.erase(it);
179 HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
180 deleted = true;
181 }
182 return deleted;
183 }
184
GetBufferHandle(const std::string & moduleKey) const185 const uint8_t* NativeModuleManager::GetBufferHandle(const std::string& moduleKey) const
186 {
187 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
188 std::lock_guard<std::mutex> lock(moduleBufMutex_);
189 auto it = moduleBufMap_.find(moduleKey);
190 if (it == moduleBufMap_.end()) {
191 return nullptr;
192 }
193 return it->second;
194 }
195
RemoveNativeModule(const std::string & moduleKey)196 bool NativeModuleManager::RemoveNativeModule(const std::string& moduleKey)
197 {
198 bool handleAbcRemoved = RemoveModuleBuffer(moduleKey);
199 bool handleRemoved = RemoveModuleLib(moduleKey);
200 bool moduleRemoved = RemoveNativeModuleByCache(moduleKey);
201
202 HILOG_DEBUG("handleAbcRemoved is %{public}d, handleRemoved is %{public}d, moduleRemoved is %{public}d",
203 handleAbcRemoved, handleRemoved, moduleRemoved);
204 return ((handleRemoved || handleAbcRemoved) && moduleRemoved);
205 }
206
UnloadNativeModule(const std::string & moduleKey)207 bool NativeModuleManager::UnloadNativeModule(const std::string& moduleKey)
208 {
209 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
210 LIBHANDLE handle = GetNativeModuleHandle(moduleKey);
211 if (handle == nullptr) {
212 HILOG_ERROR("failed to get native module handle.");
213 return false;
214 }
215
216 if (RemoveNativeModule(moduleKey) == false) {
217 HILOG_ERROR("remove native module failed.");
218 return false;
219 }
220
221 return UnloadModuleLibrary(handle);
222 }
223
GetModuleFileName(const char * moduleName,bool isAppModule)224 std::string NativeModuleManager::GetModuleFileName(const char* moduleName, bool isAppModule)
225 {
226 if (moduleName == nullptr) {
227 HILOG_ERROR("invalid param. moduleName is nullptr");
228 return "";
229 }
230 HILOG_INFO("moduleName is '%{public}s', isAppModule is %{public}d", moduleName, isAppModule);
231
232 std::string loadPath;
233 std::string name = isAppModule ? (prefix_ + "/" + moduleName) : moduleName;
234 char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
235 const char* pathKey = "default";
236 if (!GetNativeModulePath(moduleName, pathKey, "", isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
237 HILOG_ERROR("get native module path failed");
238 return loadPath;
239 }
240 NativeModule* cacheNativeModule = nullptr;
241 NativeModuleHeadTailStruct cacheHeadTailNativeModule;
242 NativeModule* module =
243 FindNativeModuleByCache(name.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
244 if (module == nullptr) {
245 HILOG_ERROR("get module file name failed");
246 return loadPath;
247 }
248 loadPath = nativeModulePath[0];
249 if (isAppModule && IsExistedPath(pathKey)) {
250 std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
251 loadPath = std::string(appLibPathMap_[pathKey]) + "/" + nativeModulePath[0];
252 }
253 HILOG_ERROR("get module file name failed, moduleName is %{public}s", moduleName);
254 return loadPath;
255 }
256
Register(NativeModule * nativeModule)257 void NativeModuleManager::Register(NativeModule* nativeModule)
258 {
259 if (nativeModule == nullptr) {
260 HILOG_ERROR("nativeModule value is null");
261 return;
262 }
263
264 HILOG_DEBUG("native module name is '%{public}s'", nativeModule->name);
265 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
266 const char *nativeModuleName = nativeModule->name == nullptr ? "" : nativeModule->name;
267 std::string appName = prefix_ + "/" + nativeModuleName;
268 std::string tmpName = isAppModule_ ? appName : nativeModuleName;
269 if (nativeModule->flags == IS_APP_MODULE_FLAGS) {
270 std::string prefix = "default/";
271 tmpName = prefix + nativeModuleName;
272 }
273 char *moduleName = strdup(tmpName.c_str());
274 if (moduleName == nullptr) {
275 HILOG_ERROR("strdup failed. tmpName is %{public}s", tmpName.c_str());
276 return;
277 }
278
279 if (g_isLoadingModule || !strcmp(loadingModuleName_.c_str(), moduleName)) {
280 if (!CreateTailNativeModule()) {
281 HILOG_ERROR("create tail nativeModule failed");
282 free(moduleName);
283 return;
284 }
285 tailNativeModule_->version = nativeModule->version;
286 tailNativeModule_->fileName = nativeModule->fileName;
287 tailNativeModule_->isAppModule = isAppModule_;
288 tailNativeModule_->name = moduleName;
289 tailNativeModule_->moduleName = nullptr; /* we update moduleName latter */
290 tailNativeModule_->refCount = nativeModule->refCount;
291 tailNativeModule_->registerCallback = nativeModule->registerCallback;
292 tailNativeModule_->getJSCode = nativeModule->getJSCode;
293 tailNativeModule_->getABCCode = nativeModule->getABCCode;
294 tailNativeModule_->next = nullptr;
295 tailNativeModule_->moduleLoaded = true;
296 tailNativeModule_->systemFilePath = "";
297 if (isAppModule_) {
298 HILOG_INFO("At tail register module name is '%{public}s'", tailNativeModule_->name);
299 }
300 HILOG_DEBUG("At tail register module name is '%{public}s', isAppModule is %{public}d", tailNativeModule_->name,
301 isAppModule_);
302 } else {
303 if (!CreateHeadNativeModule()) {
304 HILOG_ERROR("create head nativeModule failed");
305 return;
306 }
307 headNativeModule_->version = nativeModule->version;
308 headNativeModule_->fileName = nativeModule->fileName;
309 headNativeModule_->isAppModule = isAppModule_;
310 headNativeModule_->name = moduleName;
311 headNativeModule_->refCount = nativeModule->refCount;
312 headNativeModule_->registerCallback = nativeModule->registerCallback;
313 headNativeModule_->getJSCode = nativeModule->getJSCode;
314 headNativeModule_->getABCCode = nativeModule->getABCCode;
315 headNativeModule_->moduleLoaded = true;
316 headNativeModule_->systemFilePath = "";
317 HILOG_INFO("At head register module name is '%{public}s', isAppModule is %{public}d",
318 headNativeModule_->name, isAppModule_);
319 }
320 }
321
CreateHeadNativeModule()322 bool NativeModuleManager::CreateHeadNativeModule()
323 {
324 if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
325 headNativeModule_ = new NativeModule();
326 if (headNativeModule_ == nullptr) {
327 HILOG_ERROR("first NativeModule create failed");
328 return false;
329 }
330 tailNativeModule_ = headNativeModule_;
331 } else {
332 auto head = new NativeModule();
333 if (head == nullptr) {
334 HILOG_ERROR("head NativeModule create failed");
335 return false;
336 }
337 if (headNativeModule_) {
338 head->next = headNativeModule_;
339 headNativeModule_ = head;
340 }
341 }
342 return true;
343 }
344
CreateTailNativeModule()345 bool NativeModuleManager::CreateTailNativeModule()
346 {
347 if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
348 headNativeModule_ = new NativeModule();
349 if (headNativeModule_ == nullptr) {
350 HILOG_ERROR("first NativeModule create failed");
351 return false;
352 }
353 tailNativeModule_ = headNativeModule_;
354 } else {
355 auto tail = new NativeModule();
356 if (tail == nullptr) {
357 HILOG_ERROR("tail NativeModule create failed");
358 return false;
359 }
360 if (tailNativeModule_) {
361 tailNativeModule_->next = tail;
362 tailNativeModule_ = tailNativeModule_->next;
363 }
364 }
365 return true;
366 }
367
368 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
369 !defined(LINUX_PLATFORM)
CreateSharedLibsSonames()370 void NativeModuleManager::CreateSharedLibsSonames()
371 {
372 HILOG_DEBUG("enter");
373 const char* allowList[] = {
374 // bionic library
375 "libc.so",
376 "libdl.so",
377 "libm.so",
378 "libz.so",
379 "libclang_rt.asan.so",
380 "libclang_rt.tsan.so",
381 "libclang_rt.ubsan_standalone.so",
382 "libclang_rt.ubsan_minimal.so",
383 "libclang_rt.hwasan.so",
384 // z library
385 "libace_napi.z.so",
386 "libace_ndk.z.so",
387 "libcj_environment.z.so",
388 "libbundle_ndk.z.so",
389 "libdeviceinfo_ndk.z.so",
390 "libEGL.so",
391 "libGLESv3.so",
392 "libhiappevent_ndk.z.so",
393 "libhuks_ndk.z.so",
394 "libhukssdk.z.so",
395 "libnative_drawing.so",
396 "libnative_window.so",
397 "libnative_buffer.so",
398 "libnative_vsync.so",
399 "libOpenSLES.so",
400 "libpixelmap_ndk.z.so",
401 "libimage_ndk.z.so",
402 "libimage_receiver_ndk.z.so",
403 "libimage_source_ndk.z.so",
404 "librawfile.z.so",
405 "libuv.so",
406 "libhilog.so",
407 "libnative_image.so",
408 "libnative_media_adec.so",
409 "libnative_media_aenc.so",
410 "libnative_media_codecbase.so",
411 "libnative_media_core.so",
412 "libnative_media_vdec.so",
413 "libnative_media_venc.so",
414 "libnative_media_avmuxer.so",
415 "libnative_media_avdemuxer.so",
416 "libnative_media_avsource.so",
417 "libnative_avscreen_capture.so",
418 "libavplayer.so",
419 "libavrecorder.so",
420 // adaptor library
421 "libohosadaptor.so",
422 "libusb_ndk.z.so",
423 "libvulkan.so",
424 };
425
426 size_t allowListLength = sizeof(allowList) / sizeof(char*);
427 int32_t sharedLibsSonamesLength = 1;
428 for (size_t i = 0; i < allowListLength; i++) {
429 sharedLibsSonamesLength += strlen(allowList[i]) + 1;
430 }
431 sharedLibsSonames_ = new char[sharedLibsSonamesLength];
432 int32_t cursor = 0;
433 for (size_t i = 0; i < allowListLength; i++) {
434 if (sprintf_s(sharedLibsSonames_ + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
435 delete[] sharedLibsSonames_;
436 sharedLibsSonames_ = nullptr;
437 return;
438 }
439 cursor += strlen(allowList[i]) + 1;
440 }
441 sharedLibsSonames_[cursor] = '\0';
442 }
443 #endif
444
CreateLdNamespace(const std::string moduleName,const char * lib_ld_path,const bool & isSystemApp)445 void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const char* lib_ld_path,
446 [[maybe_unused]] const bool& isSystemApp)
447 {
448 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
449 !defined(LINUX_PLATFORM)
450 Dl_namespace current_ns;
451 Dl_namespace ns;
452
453 // Create module ns.
454 std::string nsName = "moduleNs_" + moduleName;
455 dlns_init(&ns, nsName.c_str());
456 dlns_get(nullptr, ¤t_ns);
457
458 Dl_namespace ndk_ns;
459 dlns_get(NDK, &ndk_ns);
460
461 if (isSystemApp) {
462 /*
463 * The app's so may have the same name as the system library, LOCAL_NS_PREFERED means linker will check
464 * and use the app's so first.
465 */
466 dlns_create2(&ns, lib_ld_path, LOCAL_NS_PREFERED);
467 // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
468 dlns_set_namespace_separated(nsName.c_str(), true);
469 // Allows access to subdirectories of this directory for shared objects (so).
470 dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
471 // System app can visit all ndk and default ns libs.
472 if (strlen(ndk_ns.name) > 0) {
473 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
474 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
475 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
476 dlns_inherit(&ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
477 }
478 } else {
479 dlns_create2(&ns, lib_ld_path, 0);
480 // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
481 dlns_set_namespace_separated(nsName.c_str(), true);
482 // Allows access to subdirectories of this directory for shared objects (so).
483 dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
484 // Non-system app can visit all ndk ns libs and default ns shared libs.
485 if (!sharedLibsSonames_) {
486 CreateSharedLibsSonames();
487 }
488 dlns_inherit(&ns, ¤t_ns, sharedLibsSonames_);
489 if (strlen(ndk_ns.name) > 0) {
490 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
491 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
492 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
493 }
494 }
495
496 nsMap_[moduleName] = ns;
497
498 HILOG_DEBUG("end. moduleName: %{public}s, path: %{public}s", moduleName.c_str(), lib_ld_path);
499 #endif
500 }
501
SetAppLibPath(const std::string & moduleName,const std::vector<std::string> & appLibPath,const bool & isSystemApp)502 void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
503 const bool& isSystemApp)
504 {
505 HILOG_DEBUG("moduleName is %{public}s, isisSystemApp is %{public}d", moduleName.c_str(), isSystemApp);
506
507 std::string tmpPath = "";
508 for (size_t i = 0; i < appLibPath.size(); i++) {
509 if (appLibPath[i].empty()) {
510 continue;
511 }
512 tmpPath += appLibPath[i];
513 tmpPath += ":";
514 }
515 if (tmpPath.back() == ':') {
516 tmpPath.pop_back();
517 }
518
519 char *tmp = strdup(tmpPath.c_str());
520 if (tmp == nullptr) {
521 HILOG_ERROR("strdup failed. tmpPath is %{public}s", tmpPath.c_str());
522 return;
523 }
524
525 std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
526 if (appLibPathMap_[moduleName] != nullptr) {
527 delete[] appLibPathMap_[moduleName];
528 }
529 appLibPathMap_[moduleName] = tmp;
530 CreateLdNamespace(moduleName, tmp, isSystemApp);
531 HILOG_DEBUG("path: %{public}s", appLibPathMap_[moduleName]);
532 }
533
MoveApiAllowListCheckerPtr(std::unique_ptr<ApiAllowListChecker> & apiAllowListChecker,NativeModule * nativeModule)534 void NativeModuleManager::MoveApiAllowListCheckerPtr(
535 std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule)
536 {
537 if (apiAllowListChecker != nullptr) {
538 nativeModule->apiAllowListChecker.reset(apiAllowListChecker.release());
539 }
540 }
541
LoadNativeModule(const char * moduleName,const char * path,bool isAppModule,std::string & errInfo,bool internal,const char * relativePath)542 NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, const char* path, bool isAppModule,
543 std::string& errInfo, bool internal, const char* relativePath)
544 {
545 if (moduleName == nullptr) {
546 errInfo = "load native module failed. moduleName is nullptr";
547 HILOG_ERROR("%{public}s", errInfo.c_str());
548 return nullptr;
549 }
550
551 if (relativePath == nullptr) {
552 errInfo = "load native module failed. relativePath is nullptr";
553 HILOG_ERROR("%{public}s", errInfo.c_str());
554 return nullptr;
555 }
556
557 std::string relativePathStr(relativePath);
558 if (relativePathStr.find("..") != std::string::npos) {
559 HILOG_ERROR("get relativePath error,relativePath contains .., moduleName:%{public}s", moduleName);
560 return nullptr;
561 }
562
563 HILOG_DEBUG("moduleName is %{public}s, path is %{public}s, relativePath is %{public}s",
564 moduleName, path, relativePath);
565
566 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
567 if (moduleLoadChecker_ && !moduleLoadChecker_->DiskCheckOnly() &&
568 !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker, isAppModule)) {
569 errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
570 HILOG_ERROR("%{public}s", errInfo.c_str());
571 return nullptr;
572 }
573 std::string prefixTmp;
574 #if defined(ANDROID_PLATFORM)
575 std::string strModule(moduleName);
576 std::string strCutName = strModule;
577 if (path != nullptr) {
578 if (IsExistedPath(path)) {
579 strModule = path;
580 }
581 prefixTmp = "default";
582 strModule = prefixTmp + '/' + moduleName;
583 } else {
584 path = "default";
585 if (strModule.find(".") != std::string::npos) {
586 char* temp = const_cast<char*>(strCutName.c_str());
587 for (char* p = strchr(temp, '.'); p != nullptr; p = strchr(p + 1, '.')) {
588 *p = '_';
589 }
590 }
591 }
592 #endif
593
594 char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
595 nativeModulePath[0][0] = 0;
596 nativeModulePath[1][0] = 0;
597 nativeModulePath[2][0] = 0; // 2 : Element index value
598 NativeModule* cacheNativeModule = nullptr;
599 NativeModuleHeadTailStruct cacheHeadTailNativeModule;
600 #if defined(ANDROID_PLATFORM)
601 if (!GetNativeModulePath(strCutName.c_str(), path, relativePath, isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
602 errInfo = "failed to get native file path of module " + std::string(moduleName);
603 HILOG_WARN("%{public}s", errInfo.c_str());
604 return nullptr;
605 }
606 NativeModule* nativeModule =
607 FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
608 #else
609 std::string key(moduleName);
610 if (isAppModule) {
611 prefixTmp = "default";
612 if (path && IsExistedPath(path)) {
613 prefixTmp = path;
614 }
615 key = prefixTmp + '/' + moduleName;
616 HILOG_INFO("key is %{public}s", key.c_str());
617 }
618 if (!GetNativeModulePath(moduleName, prefixTmp.c_str(), relativePath, isAppModule, nativeModulePath,
619 NAPI_PATH_MAX)) {
620 errInfo = "failed to get native file path of module " + std::string(moduleName);
621 HILOG_WARN("%{public}s", errInfo.c_str());
622 return nullptr;
623 }
624 #ifdef ENABLE_HITRACE
625 StartTrace(HITRACE_TAG_ACE, moduleName);
626 #endif
627 NativeModule* nativeModule =
628 FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
629 #endif
630 if (nativeModule == nullptr) {
631 (void)pthread_mutex_lock(&mutex_);
632 #ifndef IOS_PLATFORM
633 if (CheckNativeListChanged(cacheHeadTailNativeModule.headNativeModule,
634 cacheHeadTailNativeModule.tailNativeModule)) {
635 #ifdef ANDROID_PLATFORM
636 nativeModule = FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule,
637 cacheHeadTailNativeModule);
638 #else
639 nativeModule =
640 FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
641 #endif
642 }
643 #else
644 #endif
645 if (nativeModule == nullptr) {
646 prefix_ = prefixTmp;
647 isAppModule_ = isAppModule;
648 g_isLoadingModule = true;
649 #ifdef ANDROID_PLATFORM
650 HILOG_DEBUG("module '%{public}s' does not in cache", strCutName.c_str());
651 nativeModule = FindNativeModuleByDisk(strCutName.c_str(), path, relativePath, internal, isAppModule,
652 errInfo, nativeModulePath, cacheNativeModule);
653 #elif defined(IOS_PLATFORM)
654 nativeModule =
655 FindNativeModuleByCache(moduleName, nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
656 if (nativeModule == nullptr) {
657 HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
658 nativeModule = FindNativeModuleByDisk(moduleName, path, relativePath, internal, isAppModule, errInfo,
659 nativeModulePath, cacheNativeModule);
660 }
661 #else
662 HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
663 nativeModule = FindNativeModuleByDisk(moduleName, prefix_.c_str(), relativePath, internal, isAppModule,
664 errInfo, nativeModulePath, cacheNativeModule);
665 #endif
666 g_isLoadingModule = false;
667 }
668
669 (void)pthread_mutex_unlock(&mutex_);
670 }
671 MoveApiAllowListCheckerPtr(apiAllowListChecker, nativeModule);
672 #ifdef ENABLE_HITRACE
673 FinishTrace(HITRACE_TAG_ACE);
674 #endif
675 HILOG_DEBUG("load native module %{public}s", (nativeModule == nullptr) ? "failed" : "success");
676 return nativeModule;
677 }
678
CheckNativeListChanged(const NativeModule * cacheHeadNativeModule,const NativeModule * cacheTailNativeModule)679 bool NativeModuleManager::CheckNativeListChanged(
680 const NativeModule* cacheHeadNativeModule, const NativeModule* cacheTailNativeModule)
681 {
682 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
683 if (!cacheHeadNativeModule || !cacheTailNativeModule || !headNativeModule_ || !tailNativeModule_) {
684 return true;
685 }
686 if (strcmp(cacheHeadNativeModule->name, headNativeModule_->name) != 0 ||
687 strcmp(cacheTailNativeModule->name, tailNativeModule_->name) != 0) {
688 return true;
689 }
690
691 return false;
692 }
GetNativeModulePath(const char * moduleName,const char * path,const char * relativePath,bool isAppModule,char nativeModulePath[][NAPI_PATH_MAX],int32_t pathLength)693 bool NativeModuleManager::GetNativeModulePath(const char* moduleName, const char* path,
694 const char* relativePath, bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength)
695 {
696 #ifdef WINDOWS_PLATFORM
697 const char* soPostfix = ".dll";
698 const char* zfix = "";
699 std::string sysPrefix("./module");
700 const char* abcfix = ".abc";
701 std::string sysAbcPrefix("./module");
702 #elif defined(MAC_PLATFORM)
703 const char* soPostfix = ".dylib";
704 const char* zfix = "";
705 std::string sysPrefix("./module");
706 const char* abcfix = ".abc";
707 std::string sysAbcPrefix("./module");
708 #elif defined(_ARM64_) || defined(SIMULATOR)
709 const char* soPostfix = ".so";
710 const char* zfix = ".z";
711 std::string sysPrefix("/system/lib64/module");
712 const char* abcfix = ".abc";
713 std::string sysAbcPrefix("/system/etc/abc");
714 #elif defined(LINUX_PLATFORM)
715 const char* soPostfix = ".so";
716 const char* zfix = "";
717 std::string sysPrefix("./module");
718 const char* abcfix = ".abc";
719 std::string sysAbcPrefix("./module");
720 #else
721 const char* soPostfix = ".so";
722 const char* zfix = ".z";
723 std::string sysPrefix("/system/lib/module");
724 const char* abcfix = ".abc";
725 std::string sysAbcPrefix("/system/etc/abc");
726 #endif
727
728 #ifdef ANDROID_PLATFORM
729 isAppModule = true;
730 #endif
731 int32_t lengthOfModuleName = strlen(moduleName);
732 char dupModuleName[NAPI_PATH_MAX] = { 0 };
733 if (strcpy_s(dupModuleName, NAPI_PATH_MAX, moduleName) != 0) {
734 HILOG_ERROR("strcpy_s moduleName '%{public}s' failed", moduleName);
735 return false;
736 }
737
738 const char* prefix = nullptr;
739 if (isAppModule && IsExistedPath(path)) {
740 appLibPathMapMutex_.lock();
741 prefix = appLibPathMap_[path];
742 appLibPathMapMutex_.unlock();
743 #ifdef ANDROID_PLATFORM
744 for (int32_t i = 0; i < lengthOfModuleName; i++) {
745 dupModuleName[i] = tolower(dupModuleName[i]);
746 }
747 if (prefix == nullptr) {
748 return false;
749 }
750 /*
751 * The requirement is to ensure the abc format file is placed in the path
752 * /data/user/0/com.example.myapplication/files/arkui-x/systemres/abc.
753 * Steps to follow:
754 * 1. First, check if the /files/arkui-x directory exists.
755 * 2. Verify that the original path consists of two paths separated by a colon (:).
756 * 3. Identify whether /files/arkui-x is located in the portion before or after the colon.
757 * 4. Extract and concatenate the appropriate part of the path to construct
758 * the full abc file path for subsequent logic to access the file
759 */
760 std::string prefixStr(prefix);
761 const std::string arkuiKey = "/files/arkui-x";
762 std::size_t arkuiPos = prefixStr.find(arkuiKey);
763 if (arkuiPos != std::string::npos) {
764 std::size_t endPos = arkuiPos + arkuiKey.length();
765 std::size_t delimiterPos = prefixStr.find(':');
766 if (delimiterPos != std::string::npos) {
767 sysAbcPrefix = (arkuiPos < delimiterPos)
768 ? prefixStr.substr(0, endPos) + "/systemres/abc"
769 : prefixStr.substr(delimiterPos + 1, endPos - (delimiterPos + 1)) +
770 "/systemres/abc";
771 } else {
772 sysAbcPrefix = prefixStr.substr(0, endPos) + "/systemres/abc";
773 }
774 }
775 #endif
776 } else {
777 if (relativePath[0]) {
778 if (previewSearchPath_.empty()) {
779 sysPrefix = sysPrefix + "/" + relativePath;
780 } else {
781 sysPrefix = previewSearchPath_ + "/module";
782 }
783 }
784 prefix = sysPrefix.c_str();
785 for (int32_t i = 0; i < lengthOfModuleName; i++) {
786 dupModuleName[i] = tolower(dupModuleName[i]);
787 }
788 #ifdef IOS_PLATFORM
789 if (appLibPathMap_.find("default") != appLibPathMap_.end()) {
790 std::string sandboxPath(appLibPathMap_["default"]);
791 sysAbcPrefix = sandboxPath + "/systemres/abc";
792 }
793 #endif
794 }
795
796 int32_t lengthOfPostfix = strlen(soPostfix);
797 if ((lengthOfModuleName > lengthOfPostfix) &&
798 (strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
799 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s", prefix, dupModuleName) == -1) {
800 return false;
801 }
802 return true;
803 }
804
805 char* lastDot = strrchr(dupModuleName, '.');
806 if (lastDot == nullptr) {
807 if (!isAppModule || !IsExistedPath(path)) {
808 #ifdef ANDROID_PLATFORM
809 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
810 return false;
811 }
812 #else
813 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s%s",
814 prefix, dupModuleName, zfix, soPostfix) == -1) {
815 return false;
816 }
817 #endif
818 if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s_napi%s%s",
819 prefix, dupModuleName, zfix, soPostfix) == -1) {
820 return false;
821 }
822
823 if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
824 sysAbcPrefix.c_str(), dupModuleName, abcfix) == -1) {
825 return false;
826 }
827 } else {
828 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
829 !defined(LINUX_PLATFORM)
830 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
831 return false;
832 }
833 #elif defined(ANDROID_PLATFORM)
834 std::string libPath;
835 int sprintfResult = 0;
836 std::string prefixStr = std::string(prefix);
837 std::size_t pos = prefixStr.find(':');
838 if (pos != std::string::npos) {
839 sprintfResult = sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s%s",
840 prefixStr.substr(0, pos).c_str(), dupModuleName, soPostfix);
841 libPath = prefixStr.substr(pos + 1);
842 } else {
843 sprintfResult = sprintf_s(nativeModulePath[1], pathLength, "lib%s%s", dupModuleName, soPostfix);
844 libPath = prefixStr;
845 }
846 if (sprintfResult == -1) {
847 return false;
848 }
849 #else
850 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", prefix, dupModuleName, soPostfix) == -1) {
851 return false;
852 }
853 #endif
854 #ifdef ANDROID_PLATFORM
855 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", libPath.c_str(),
856 dupModuleName, soPostfix) == -1) {
857 return false;
858 }
859 char* lastUnderScore = strrchr(dupModuleName, '_');
860 const char* moduleNamePart = (lastUnderScore != nullptr) ? (lastUnderScore + 1) : dupModuleName;
861 if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
862 sysAbcPrefix.c_str(), moduleNamePart, abcfix) == -1) {
863 return false;
864 }
865 #endif
866 }
867 } else {
868 char* afterDot = lastDot + 1;
869 if (*afterDot == '\0') {
870 return false;
871 }
872 *lastDot = '\0';
873 lengthOfModuleName = strlen(dupModuleName);
874 for (int32_t i = 0; i < lengthOfModuleName; i++) {
875 if (*(dupModuleName + i) == '.') {
876 *(dupModuleName + i) = '/';
877 }
878 }
879 if (!isAppModule || !IsExistedPath(path)) {
880 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s%s",
881 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
882 return false;
883 }
884 if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s_napi%s%s",
885 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
886 return false;
887 }
888 #ifdef IOS_PLATFORM
889 if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
890 sysAbcPrefix.c_str(), afterDot, abcfix) == -1) {
891 return false;
892 }
893 #else
894 if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s/%s%s", // 2 : Element index value
895 sysAbcPrefix.c_str(), dupModuleName, afterDot, abcfix) == -1) {
896 return false;
897 }
898 #endif
899 } else {
900 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
901 !defined(LINUX_PLATFORM)
902 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", afterDot, soPostfix) == -1) {
903 return false;
904 }
905 #else
906 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s",
907 prefix, dupModuleName, afterDot, soPostfix) == -1) {
908 return false;
909 }
910 #endif
911 #ifdef ANDROID_PLATFORM
912 if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s%s",
913 prefix, moduleName, afterDot, soPostfix) == -1) {
914 return false;
915 }
916 #endif
917 }
918 }
919 return true;
920 }
921
LoadModuleLibrary(std::string & moduleKey,const char * path,const char * pathKey,const bool isAppModule,std::string & errInfo,uint32_t & errReason)922 LIBHANDLE NativeModuleManager::LoadModuleLibrary(std::string& moduleKey, const char* path,
923 const char* pathKey, const bool isAppModule, std::string& errInfo, uint32_t& errReason)
924 {
925 if (strlen(path) == 0) {
926 errInfo += "load module " + moduleKey + " failed. module path is empty";
927 HILOG_ERROR("%{public}s", errInfo.c_str());
928 return nullptr;
929 }
930
931 LIBHANDLE lib = nullptr;
932
933 HILOG_DEBUG("path: %{public}s, pathKey: %{public}s, isAppModule: %{public}d", path, pathKey, isAppModule);
934 #ifdef ENABLE_HITRACE
935 StartTrace(HITRACE_TAG_ACE, path);
936 #endif
937 #if defined(WINDOWS_PLATFORM)
938 if (CheckModuleExist(path) == false) {
939 errReason = MODULE_NOT_EXIST;
940 return nullptr;
941 }
942 lib = LoadLibrary(path);
943 if (lib == nullptr) {
944 errInfo += "load module failed. " + std::to_string(GetLastError());
945 HILOG_WARN("%{public}s", errInfo.c_str());
946 }
947 #elif defined(MAC_PLATFORM) || defined(__BIONIC__) || defined(LINUX_PLATFORM)
948 #ifndef ANDROID_PLATFORM
949 if (CheckModuleExist(path) == false) {
950 errReason = MODULE_NOT_EXIST;
951 return nullptr;
952 }
953 #endif
954 lib = dlopen(path, RTLD_LAZY);
955 if (lib == nullptr) {
956 char* dlerr = dlerror();
957 auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
958 errInfo += "load module failed. " + std::string(dlerrMsg);
959 }
960
961 #elif defined(IOS_PLATFORM)
962 lib = nullptr;
963 #else
964 if (isAppModule && IsExistedPath(pathKey)) {
965 Dl_namespace ns = nsMap_[pathKey];
966 lib = dlopen_ns(&ns, path, RTLD_LAZY);
967 } else if (access(path, F_OK) == 0) {
968 lib = dlopen(path, RTLD_LAZY);
969 }
970 if (lib == nullptr) {
971 char* dlerr = dlerror();
972 auto dlerrMsg = dlerr != nullptr ? dlerr :
973 "Error loading path " + std::string(path) + ":No such file or directory";
974 errInfo += "load app module failed. " + std::string(dlerrMsg);
975 }
976 #endif
977 #ifdef ENABLE_HITRACE
978 FinishTrace(HITRACE_TAG_ACE);
979 #endif
980 EmplaceModuleLib(moduleKey, lib);
981
982 return lib;
983 }
984
GetFileBuffer(const std::string & filePath,const std::string & moduleKey,size_t & len)985 const uint8_t* NativeModuleManager::GetFileBuffer(const std::string& filePath,
986 const std::string& moduleKey, size_t &len)
987 {
988 const uint8_t* lib = nullptr;
989 std::ifstream inFile(filePath, std::ios::ate | std::ios::binary);
990 if (!inFile.is_open()) {
991 HILOG_ERROR("%{public}s is not existed.", filePath.c_str());
992 return lib;
993 }
994 len = static_cast<size_t>(inFile.tellg());
995 std::string abcModuleKey = moduleKey;
996 lib = GetBufferHandle(abcModuleKey);
997 if (lib != nullptr) {
998 HILOG_DEBUG("get native abc handle success. moduleKey is %{public}s", moduleKey.c_str());
999 inFile.close();
1000 return lib;
1001 }
1002
1003 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
1004 inFile.seekg(0);
1005 inFile.read(reinterpret_cast<char*>(buffer.get()), len);
1006 inFile.close();
1007 lib = buffer.release();
1008 EmplaceModuleBuffer(abcModuleKey, lib);
1009 return lib;
1010 }
1011
UnloadModuleLibrary(LIBHANDLE handle)1012 bool NativeModuleManager::UnloadModuleLibrary(LIBHANDLE handle)
1013 {
1014 if (handle == nullptr) {
1015 HILOG_WARN("handle is nullptr");
1016 return false;
1017 }
1018 #if !defined(WINDOWS_PLATFORM) && !defined(IOS_PLATFORM)
1019 if (!dlclose(handle)) {
1020 return true;
1021 }
1022 char* dlerr = dlerror();
1023 auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
1024 HILOG_WARN("dlclose failed: %{public}s", dlerrMsg);
1025 #endif
1026 return false;
1027 }
1028
CheckModuleExist(const char * modulePath)1029 bool NativeModuleManager::CheckModuleExist(const char* modulePath)
1030 {
1031 if (modulePath) {
1032 std::ifstream inFile(modulePath, std::ios::ate | std::ios::binary);
1033 if (inFile.is_open()) {
1034 inFile.close();
1035 return true;
1036 }
1037 }
1038 return false;
1039 }
1040
FindNativeModuleByDisk(const char * moduleName,const char * path,const char * relativePath,bool internal,const bool isAppModule,std::string & errInfo,char nativeModulePath[][NAPI_PATH_MAX],NativeModule * cacheNativeModule)1041 NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, const char* path,
1042 const char* relativePath, bool internal, const bool isAppModule, std::string& errInfo,
1043 char nativeModulePath[][NAPI_PATH_MAX], NativeModule* cacheNativeModule)
1044 {
1045 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
1046 if (moduleLoadChecker_ && !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker, isAppModule)) {
1047 errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
1048 HILOG_WARN("%{public}s", errInfo.c_str());
1049 return nullptr;
1050 }
1051
1052 std::string moduleKey(moduleName);
1053 if (isAppModule) {
1054 moduleKey = path;
1055 moduleKey = moduleKey + '/' + moduleName;
1056 }
1057 loadingModuleName_ = moduleKey;
1058
1059 // load primary module path first
1060 char* loadPath = nativeModulePath[0];
1061 HILOG_DEBUG("moduleName is %{public}s. get primary module path is %{public}s", moduleName, loadPath);
1062 uint32_t errReason0 = MODULE_LOAD_SUCCESS;
1063 errInfo = "First attempt: ";
1064 LIBHANDLE lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason0);
1065 if (lib == nullptr) {
1066 errInfo += "\nSecond attempt: ";
1067 loadPath = nativeModulePath[1];
1068 HILOG_DEBUG("try to load secondary module path: %{public}s", loadPath);
1069 uint32_t errReason1 = MODULE_LOAD_SUCCESS;
1070 lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason1);
1071 if (lib == nullptr && errReason0 == MODULE_NOT_EXIST && errReason1 == MODULE_NOT_EXIST) {
1072 HILOG_ERROR("%{public}s does not exist, errMsg %{public}s", nativeModulePath[0], errInfo.c_str());
1073 }
1074 }
1075
1076 //Maintain compatibility
1077 if (lib == nullptr && cacheNativeModule != nullptr) {
1078 HILOG_DEBUG("Maintain compatibility.");
1079 return cacheNativeModule;
1080 }
1081
1082 const uint8_t* abcBuffer = nullptr;
1083 size_t len = 0;
1084 if (lib == nullptr) {
1085 loadPath = nativeModulePath[2]; // 2 : Element index value
1086 HILOG_DEBUG("try to load abc module path: %{public}s", loadPath);
1087 abcBuffer = GetFileBuffer(loadPath, moduleKey, len);
1088 if (!abcBuffer) {
1089 errInfo += "\ntry to load abc file from " + std::string(loadPath) + " failed";
1090 HILOG_ERROR("%{public}s", errInfo.c_str());
1091 return nullptr;
1092 }
1093 }
1094
1095 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1096 if (tailNativeModule_ && !abcBuffer) {
1097 const char* moduleName = strdup(moduleKey.c_str());
1098 if (moduleName == nullptr) {
1099 HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1100 return nullptr;
1101 }
1102
1103 tailNativeModule_->moduleName = moduleName;
1104 tailNativeModule_->systemFilePath = strdup(loadPath);
1105 if (strcmp(tailNativeModule_->moduleName, tailNativeModule_->name)) {
1106 HILOG_WARN("mismatch: moduleName is %{public}s, name is %{public}s",
1107 tailNativeModule_->moduleName, tailNativeModule_->name);
1108 HILOG_WARN("suggestion: keep .nm_modname the same as moduleName imported or required");
1109 }
1110 }
1111
1112 if (!internal) {
1113 char symbol[NAPI_PATH_MAX] = { 0 };
1114 if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetABCCode", moduleKey.c_str()) == -1) {
1115 if (lib != nullptr) {
1116 LIBFREE(lib);
1117 }
1118 errInfo = "sprintf symbol NAPI_" + moduleKey + "_GetABCCode failed";
1119 HILOG_ERROR("%{public}s", errInfo.c_str());
1120 return nullptr;
1121 }
1122
1123 // replace '.' and '/' with '_'
1124 for (char* p = strchr(symbol, '.'); p != nullptr; p = strchr(p + 1, '.')) {
1125 *p = '_';
1126 }
1127 for (char* p = strchr(symbol, '/'); p != nullptr; p = strchr(p + 1, '/')) {
1128 *p = '_';
1129 }
1130
1131 if (lib != nullptr) {
1132 auto getJSCode = reinterpret_cast<GetJSCodeCallback>(LIBSYM(lib, symbol));
1133 if (getJSCode == nullptr) {
1134 HILOG_DEBUG("ignore: no %{public}s in %{public}s", symbol, loadPath);
1135 MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1136 return tailNativeModule_;
1137 }
1138 const char* buf = nullptr;
1139 int bufLen = 0;
1140 getJSCode(&buf, &bufLen);
1141 if (tailNativeModule_) {
1142 HILOG_DEBUG("get js code from module: bufLen: %{public}d", bufLen);
1143 tailNativeModule_->jsCode = buf;
1144 tailNativeModule_->jsCodeLen = bufLen;
1145 }
1146 } else {
1147 RegisterByBuffer(moduleKey, abcBuffer, len);
1148 tailNativeModule_->systemFilePath = strdup(loadPath);
1149 }
1150 }
1151 if (tailNativeModule_) {
1152 tailNativeModule_->moduleLoaded = true;
1153 if (tailNativeModule_->name && tailNativeModule_->moduleName) {
1154 HILOG_DEBUG("last native info: name is %{public}s, moduleName is %{public}s",
1155 tailNativeModule_->name, tailNativeModule_->moduleName);
1156 }
1157 MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1158 }
1159 return tailNativeModule_;
1160 }
1161
RegisterByBuffer(const std::string & moduleKey,const uint8_t * abcBuffer,size_t len)1162 void NativeModuleManager::RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len)
1163 {
1164 HILOG_DEBUG("native module name is '%{public}s'", moduleKey.c_str());
1165 if (!CreateTailNativeModule()) {
1166 HILOG_ERROR("create tail nativeModule failed");
1167 return;
1168 }
1169
1170 char *moduleName = strdup(moduleKey.c_str());
1171 if (moduleName == nullptr) {
1172 HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1173 return;
1174 }
1175 tailNativeModule_->moduleName = moduleName;
1176 tailNativeModule_->name = strdup(moduleName);
1177 if (tailNativeModule_->name == nullptr) {
1178 HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleName);
1179 free(moduleName);
1180 tailNativeModule_->moduleName = nullptr;
1181 return;
1182 }
1183 tailNativeModule_->jsABCCode = abcBuffer;
1184 tailNativeModule_->jsCodeLen = static_cast<int32_t>(len);
1185 tailNativeModule_->next = nullptr;
1186
1187 HILOG_INFO("Register by buffer success. module name is '%{public}s'", tailNativeModule_->moduleName);
1188 }
1189
RemoveNativeModuleByCache(const std::string & moduleKey)1190 bool NativeModuleManager::RemoveNativeModuleByCache(const std::string& moduleKey)
1191 {
1192 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1193
1194 if (headNativeModule_ == nullptr) {
1195 HILOG_WARN("NativeModule list is empty");
1196 return false;
1197 }
1198
1199 NativeModule* nativeModule = headNativeModule_;
1200 if (!strcasecmp(nativeModule->moduleName, moduleKey.c_str())) {
1201 if (headNativeModule_ == tailNativeModule_) {
1202 tailNativeModule_ = nullptr;
1203 }
1204 headNativeModule_ = headNativeModule_->next;
1205 delete[] nativeModule->name;
1206 if (nativeModule->moduleName) {
1207 delete[] nativeModule->moduleName;
1208 }
1209 if (headNativeModule_->jsABCCode) {
1210 delete[] headNativeModule_->jsABCCode;
1211 }
1212 delete nativeModule;
1213 HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1214 return true;
1215 }
1216
1217 bool moduleDeleted = false;
1218 NativeModule* prev = headNativeModule_;
1219 NativeModule* curr = prev->next;
1220 while (curr != nullptr) {
1221 if (!strcasecmp(curr->moduleName, moduleKey.c_str())) {
1222 if (curr == tailNativeModule_) {
1223 tailNativeModule_ = prev;
1224 }
1225 prev->next = curr->next;
1226 delete[] curr->name;
1227 if (curr->moduleName) {
1228 delete[] curr->moduleName;
1229 }
1230 if (curr->jsABCCode) {
1231 delete[] curr->jsABCCode;
1232 }
1233 delete curr;
1234 HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1235 moduleDeleted = true;
1236 break;
1237 }
1238 prev = prev->next;
1239 curr = prev->next;
1240 }
1241
1242 return moduleDeleted;
1243 }
1244
FindNativeModuleByCache(const char * moduleName,char nativeModulePath[][NAPI_PATH_MAX],NativeModule * & cacheNativeModule,NativeModuleHeadTailStruct & cacheHeadTailStruct)1245 NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName,
1246 char nativeModulePath[][NAPI_PATH_MAX],
1247 NativeModule*& cacheNativeModule,
1248 NativeModuleHeadTailStruct& cacheHeadTailStruct)
1249 {
1250 NativeModule* result = nullptr;
1251
1252 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1253 cacheNativeModule = nullptr;
1254 for (NativeModule* temp = headNativeModule_; temp != nullptr; temp = temp->next) {
1255 if ((temp->moduleName && !strcmp(temp->moduleName, moduleName))
1256 || !strcasecmp(temp->name, moduleName)) {
1257 int label = 0;
1258 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1259 while (label < NATIVE_PATH_NUMBER && strcmp(temp->systemFilePath, nativeModulePath[label])) {
1260 label++;
1261 }
1262 #endif
1263 if (label < NATIVE_PATH_NUMBER || !strcmp(temp->systemFilePath, "")) {
1264 result = temp;
1265 break;
1266 } else {
1267 HILOG_WARN("moduleName '%{public}s' is in different path", moduleName);
1268 cacheNativeModule = temp;
1269 }
1270 }
1271 }
1272 cacheHeadTailStruct.headNativeModule = headNativeModule_;
1273 cacheHeadTailStruct.tailNativeModule = tailNativeModule_;
1274
1275 return result;
1276 }
1277
IsExistedPath(const char * pathKey) const1278 bool NativeModuleManager::IsExistedPath(const char* pathKey) const
1279 {
1280 HILOG_DEBUG("pathKey is '%{public}s'", pathKey);
1281 std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
1282 return pathKey && appLibPathMap_.find(pathKey) != appLibPathMap_.end();
1283 }
1284
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> & moduleCheckerDelegate)1285 void NativeModuleManager::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
1286 {
1287 HILOG_DEBUG("enter");
1288 if (!moduleLoadChecker_) {
1289 HILOG_ERROR("SetModuleLoadChecker failed, moduleLoadChecker_ is nullptr");
1290 return;
1291 }
1292 moduleLoadChecker_->SetDelegate(moduleCheckerDelegate);
1293 }
1294
SetPreviewSearchPath(const std::string & previewSearchPath)1295 void NativeModuleManager::SetPreviewSearchPath(const std::string& previewSearchPath)
1296 {
1297 HILOG_DEBUG("previewSearchPath is '%{public}s'", previewSearchPath.c_str());
1298 previewSearchPath_ = previewSearchPath;
1299 }
1300