1 /*
2 * Copyright (c) 2025 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 "dynamic_loader.h"
17
18 #include <cstdio>
19 #include <dlfcn.h>
20 #include <securec.h>
21 #include <string>
22 #include <unordered_set>
23
24 #include "hilog_tag_wrapper.h"
25
26 namespace OHOS {
27 namespace EtsEnv {
28 namespace {
29 constexpr int32_t ERROR_BUF_SIZE = 255;
30 static char g_dlError[ERROR_BUF_SIZE];
31 static std::unordered_set<std::string> g_hasInited;
32 static std::string g_sharedLibsSonames = "";
33 constexpr int32_t OUT_OF_MEMORY = 12;
34 constexpr int32_t FILE_EXISTS = 17;
35 constexpr int32_t INVALID_ARGUMENT = 22;
36
ReadDlError()37 static void ReadDlError()
38 {
39 char *errMsg = dlerror();
40 if (!errMsg) {
41 return;
42 }
43 auto ends = sprintf_s(g_dlError, sizeof(g_dlError), "%s", errMsg);
44 if (ends < 0) {
45 return;
46 } else if (ends >= ERROR_BUF_SIZE) {
47 g_dlError[ERROR_BUF_SIZE - 1] = '\0';
48 } else {
49 g_dlError[ends] = '\0';
50 }
51 }
52
InitSharedLibsSonames()53 static void InitSharedLibsSonames()
54 {
55 if (!g_sharedLibsSonames.empty()) {
56 return;
57 }
58 g_sharedLibsSonames =
59 // bionic library
60 "libc.so:"
61 "libdl.so:"
62 "libm.so:"
63 "libz.so:"
64 "libclang_rt.asan.so:"
65 "libclang_rt.tsan.so:"
66 // z library
67 "libace_napi.z.so:"
68 "libace_ndk.z.so:"
69 "libbundle_ndk.z.so:"
70 "libdeviceinfo_ndk.z.so:"
71 "libEGL.so:"
72 "libGLESv3.so:"
73 "libhiappevent_ndk.z.so:"
74 "libhuks_ndk.z.so:"
75 "libhukssdk.z.so:"
76 "libnative_drawing.so:"
77 "libnative_window.so:"
78 "libnative_buffer.so:"
79 "libnative_vsync.so:"
80 "libOpenSLES.so:"
81 "libpixelmap_ndk.z.so:"
82 "libimage_ndk.z.so:"
83 "libimage_receiver_ndk.z.so:"
84 "libimage_source_ndk.z.so:"
85 "librawfile.z.so:"
86 "libuv.so:"
87 "libhilog.so:"
88 "libnative_image.so:"
89 "libnative_media_adec.so:"
90 "libnative_media_aenc.so:"
91 "libnative_media_codecbase.so:"
92 "libnative_media_core.so:"
93 "libnative_media_vdec.so:"
94 "libnative_media_venc.so:"
95 "libnative_media_avmuxer.so:"
96 "libnative_media_avdemuxer.so:"
97 "libnative_media_avsource.so:"
98 "libnative_avscreen_capture.so:"
99 "libavplayer.so:"
100 // adaptor library
101 "libohosadaptor.so:"
102 "libusb_ndk.z.so:"
103 "libvulkan.so:"
104 // runtime library
105 "libarkaotmanager.so:"
106 "libarktarget_options.so:"
107 "libhmicui18n.z.so:"
108 "libes2panda-public.so:"
109 "libes2panda-lib.so:"
110 "libhmicuuc.z.so:"
111 "libarkcompiler.so:"
112 "libarkassembler.so:"
113 "libarkfile.so:"
114 "libarkziparchive.so:"
115 "libarkbase.so:"
116 "libc_secshared.so:"
117 "libhilog_ndk.z.so:"
118 "libarkplatform.so";
119 }
120 } // namespace
121
DynamicInitNamespace(Dl_namespace * ns,void * parent,const char * entries,const char * name)122 void DynamicInitNamespace(Dl_namespace *ns, void *parent, const char *entries, const char *name)
123 {
124 if (ns == nullptr || entries == nullptr || name == nullptr) {
125 TAG_LOGE(AAFwkTag::ETSRUNTIME, "Invaild args for init namespace.");
126 return;
127 }
128 if (g_hasInited.count(std::string(name))) {
129 return;
130 }
131 dlns_init(ns, name);
132 auto status = dlns_create2(ns, entries, 0);
133 std::string errMsg;
134 if (status != 0) {
135 switch (status) {
136 case FILE_EXISTS:
137 errMsg = "dlns_create failed: File exists";
138 break;
139 case INVALID_ARGUMENT:
140 errMsg = "dlns_create failed: Invalid argument";
141 break;
142 case OUT_OF_MEMORY:
143 errMsg = "dlns_create failed: Out of memory";
144 break;
145 default:
146 errMsg = "dlns_create failed, status: " + std::to_string(status);
147 }
148 if (sprintf_s(g_dlError, sizeof(g_dlError), errMsg.c_str()) == -1) {
149 TAG_LOGE(AAFwkTag::ETSRUNTIME, "Fail to generate error msg.");
150 return;
151 }
152 return;
153 }
154 if (parent) {
155 dlns_inherit((Dl_namespace *)parent, ns, "allow_all_shared_libs");
156 }
157 Dl_namespace current;
158 dlns_get(nullptr, ¤t);
159 if (strcmp(name, "ets_app") != 0) {
160 dlns_inherit(ns, ¤t, "allow_all_shared_libs");
161 } else {
162 InitSharedLibsSonames();
163 dlns_inherit(ns, ¤t, g_sharedLibsSonames.c_str());
164 }
165 g_hasInited.insert(std::string(name));
166 }
167
DynamicLoadLibrary(Dl_namespace * ns,const char * dlPath,uint32_t mode)168 void *DynamicLoadLibrary(Dl_namespace *ns, const char *dlPath, uint32_t mode)
169 {
170 if (ns == nullptr) {
171 dlns_get("ets_app", ns);
172 }
173
174 auto result = dlopen_ns(ns, dlPath, mode | RTLD_GLOBAL | RTLD_NOW);
175 if (!result) {
176 ReadDlError();
177 }
178 return result;
179 }
180
DynamicFindSymbol(void * so,const char * symbol)181 void *DynamicFindSymbol(void *so, const char *symbol)
182 {
183 return dlsym(so, symbol);
184 }
185
DynamicFreeLibrary(void * so)186 void DynamicFreeLibrary(void *so)
187 {
188 (void)dlclose(so);
189 }
190
DynamicGetError()191 const char *DynamicGetError()
192 {
193 return g_dlError;
194 }
195 } // namespace EtsEnv
196 } // namespace OHOS