• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "file.h"
17 #include "include/object_header.h"
18 #include "include/thread_scopes.h"
19 #include "intrinsics.h"
20 #include "libpandabase/utils/logger.h"
21 #include "libpandabase/utils/utf.h"
22 #include "libziparchive/extractortool/extractor.h"
23 #include "runtime/handle_scope-inl.h"
24 #include "plugins/ets/runtime/ets_class_linker_extension.h"
25 #include "plugins/ets/runtime/ets_coroutine.h"
26 #include "plugins/ets/runtime/ets_exceptions.h"
27 #include "plugins/ets/runtime/ets_stubs-inl.h"
28 #include "plugins/ets/runtime/types/ets_abc_file.h"
29 #include "plugins/ets/runtime/types/ets_primitives.h"
30 #include "plugins/ets/runtime/types/ets_runtime_linker.h"
31 #include "plugins/ets/runtime/types/ets_string.h"
32 #include "runtime/mem/local_object_handle.h"
33 
34 namespace ark::ets::intrinsics {
35 
CreateAbcFile(EtsCoroutine * coro,ClassLinkerContext * ctx,std::unique_ptr<const panda_file::File> && pf)36 static EtsAbcFile *CreateAbcFile(EtsCoroutine *coro, ClassLinkerContext *ctx,
37                                  std::unique_ptr<const panda_file::File> &&pf)
38 {
39     auto *abcFile = EtsAbcFile::FromEtsObject(EtsObject::Create(coro, PlatformTypes(coro)->coreAbcFile));
40     abcFile->SetPandaFile(pf.get());
41 
42     Runtime::GetCurrent()->GetClassLinker()->AddPandaFile(std::move(pf), ctx);
43     return abcFile;
44 }
45 
EtsAbcFileLoadAbcFile(EtsRuntimeLinker * runtimeLinker,EtsString * filePath)46 EtsAbcFile *EtsAbcFileLoadAbcFile(EtsRuntimeLinker *runtimeLinker, EtsString *filePath)
47 {
48     ASSERT(filePath != nullptr);
49     ASSERT(runtimeLinker != nullptr);
50     auto *ctx = runtimeLinker->GetClassLinkerContext();
51     auto *coro = EtsCoroutine::GetCurrent();
52 
53     const auto path = filePath->GetMutf8();
54     std::unique_ptr<const panda_file::File> pf {nullptr};
55     {
56         // Loading panda-file might be time-consuming, which would affect GC
57         // unless being executed in native scope
58         ScopedNativeCodeThread etsNativeScope(coro);
59         pf = panda_file::OpenPandaFileOrZip(path);
60     }
61 
62     if (pf == nullptr) {
63         // get hap path
64         auto pathStr = std::string(path.begin(), path.end());
65         size_t pos = pathStr.rfind("/ets/");
66         if (pos == std::string::npos) {
67             ets::ThrowEtsException(coro, panda_file_items::class_descriptors::ABC_FILE_NOT_FOUND_ERROR,
68                                    PandaString("Open failed, file: ") + path);
69             return nullptr;
70         }
71         std::string hapPath = pathStr.substr(0, pos);
72         hapPath += ".hap";
73 
74         std::shared_ptr<ark::extractor::Extractor> extractor = std::make_shared<ark::extractor::Extractor>(hapPath);
75         if (!extractor || !extractor->Init()) {
76             ets::ThrowEtsException(coro, panda_file_items::class_descriptors::ABC_FILE_NOT_FOUND_ERROR,
77                                    PandaString("Open failed, file: ") + path);
78             return nullptr;
79         }
80         auto safeData = extractor->GetSafeData(pathStr);
81         ASSERT(safeData != nullptr);
82         pf = panda_file::OpenPandaFileFromSecureMemory(safeData->GetDataPtr(), safeData->GetDataLen(), pathStr);
83     }
84 
85     if (pf == nullptr) {
86         ets::ThrowEtsException(coro, panda_file_items::class_descriptors::ABC_FILE_NOT_FOUND_ERROR,
87                                PandaString("Abc file not found: ") + path);
88         return nullptr;
89     }
90     return CreateAbcFile(coro, ctx, std::move(pf));
91 }
92 
EtsAbcFileLoadFromMemory(EtsRuntimeLinker * runtimeLinker,ObjectHeader * rawFileArray)93 EtsAbcFile *EtsAbcFileLoadFromMemory(EtsRuntimeLinker *runtimeLinker, ObjectHeader *rawFileArray)
94 {
95     ASSERT(rawFileArray != nullptr);
96     ASSERT(runtimeLinker != nullptr);
97 
98     auto *ctx = runtimeLinker->GetClassLinkerContext();
99     auto *coro = EtsCoroutine::GetCurrent();
100     [[maybe_unused]] EtsHandleScope hs(coro);
101     EtsHandle arrayHandle(coro, reinterpret_cast<EtsByteArray *>(rawFileArray));
102 
103     std::unique_ptr<const panda_file::File> pf {nullptr};
104     {
105         // Loading panda-file might be time-consuming, which would affect GC
106         // unless being executed in native scope
107         ScopedNativeCodeThread etsNativeScope(coro);
108         pf = panda_file::OpenPandaFileFromMemory(arrayHandle->GetData<void>(), arrayHandle->GetLength());
109     }
110 
111     if (pf == nullptr) {
112         ets::ThrowEtsException(coro, panda_file_items::class_descriptors::ERROR,
113                                PandaString("Failed to load abc file from memory"));
114         return nullptr;
115     }
116     return CreateAbcFile(coro, ctx, std::move(pf));
117 }
118 
EtsAbcFileLoadClass(EtsAbcFile * abcFile,EtsRuntimeLinker * runtimeLinker,EtsString * clsName,EtsBoolean init)119 EtsClass *EtsAbcFileLoadClass(EtsAbcFile *abcFile, EtsRuntimeLinker *runtimeLinker, EtsString *clsName, EtsBoolean init)
120 {
121     const auto name = clsName->GetMutf8();
122     PandaString descriptor;
123     const auto *classDescriptor = ClassHelper::GetDescriptor(utf::CStringAsMutf8(name.c_str()), &descriptor);
124 
125     const auto *pf = abcFile->GetPandaFile();
126     const auto classId = pf->GetClassId(classDescriptor);
127     if (!classId.IsValid() || pf->IsExternal(classId)) {
128         return nullptr;
129     }
130 
131     auto *coro = EtsCoroutine::GetCurrent();
132     auto *classLinker = Runtime::GetCurrent()->GetClassLinker();
133     auto *ctx = runtimeLinker->GetClassLinkerContext();
134     auto *linkerErrorHandler = PandaEtsVM::GetCurrent()->GetEtsClassLinkerExtension()->GetErrorHandler();
135     auto *klass = classLinker->LoadClass(*pf, classId, ctx, linkerErrorHandler, true);
136     if (UNLIKELY(klass == nullptr)) {
137         ASSERT(coro->HasPendingException());
138         return nullptr;
139     }
140 
141     if (UNLIKELY(init != 0 && !klass->IsInitialized())) {
142         if (UNLIKELY(!classLinker->InitializeClass(coro, klass))) {
143             ASSERT(coro->HasPendingException());
144             return nullptr;
145         }
146     }
147     return EtsClass::FromRuntimeClass(klass);
148 }
149 
EtsAbcFileGetFilename(EtsAbcFile * abcFile)150 EtsString *EtsAbcFileGetFilename(EtsAbcFile *abcFile)
151 {
152     auto filename = abcFile->GetPandaFile()->GetFilename();
153     return EtsString::CreateFromMUtf8(filename.c_str());
154 }
155 
156 }  // namespace ark::ets::intrinsics
157