• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 "plugins/ets/runtime/ets_utils.h"
17 #include "plugins/ets/runtime/types/ets_class.h"
18 #include "plugins/ets/runtime/types/ets_field.h"
19 #include "plugins/ets/runtime/types/ets_method.h"
20 
21 namespace ark::ets {
22 
IsEtsGlobalClassName(const std::string & descriptor)23 bool IsEtsGlobalClassName(const std::string &descriptor)
24 {
25     ASSERT(descriptor.length() >= 2U);  // L...;
26     ASSERT('L' == descriptor[0]);
27     ASSERT(';' == descriptor[descriptor.size() - 1]);
28 
29     constexpr size_t ETSGLOBAL_SEMICOLON_LENGTH = sizeof(ETSGLOBAL_CLASS_NAME);
30 
31     const auto etsGlobalSubstringPos = descriptor.rfind(ETSGLOBAL_CLASS_NAME);
32     if (etsGlobalSubstringPos == std::string::npos) {
33         return false;
34     }
35     const bool etsGlobalClass = (1 == etsGlobalSubstringPos) && descriptor.length() == 1 + ETSGLOBAL_SEMICOLON_LENGTH;
36     const bool endsWithETSGLOBAL = descriptor.length() - ETSGLOBAL_SEMICOLON_LENGTH == etsGlobalSubstringPos;
37     const bool etsGlobalClassInPackage = endsWithETSGLOBAL && '/' == descriptor[etsGlobalSubstringPos - 1];
38 
39     return etsGlobalClass || etsGlobalClassInPackage;
40 }
41 
InvokeVoid(EtsCoroutine * coro,EtsObject * lambda)42 void LambdaUtils::InvokeVoid(EtsCoroutine *coro, EtsObject *lambda)
43 {
44     ASSERT(lambda != nullptr);
45     EtsMethod *invoke = lambda->GetClass()->GetInstanceMethod(INVOKE_METHOD_NAME, nullptr);
46     if (invoke == nullptr) {
47         LOG(FATAL, RUNTIME) << "No method '$_invoke' found";
48         return;
49     }
50     Value arg(lambda->GetCoreType());
51     invoke->GetPandaMethod()->InvokeVoid(coro, &arg);
52 }
53 
GetDisplayNameStringFromField(EtsField * field)54 EtsString *ManglingUtils::GetDisplayNameStringFromField(EtsField *field)
55 {
56     auto fieldNameData = field->GetCoreType()->GetName();
57     auto fieldNameLength = fieldNameData.utf16Length;
58     std::string_view fieldName(utf::Mutf8AsCString(fieldNameData.data), fieldNameLength);
59     if (fieldName.rfind(PROPERTY, 0) == 0) {
60         ASSERT(fieldNameLength >= PROPERTY_PREFIX_LENGTH);
61         return EtsString::Resolve(
62             fieldNameData.data + PROPERTY_PREFIX_LENGTH,  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
63             fieldNameLength - PROPERTY_PREFIX_LENGTH);
64     }
65     return EtsString::Resolve(fieldNameData.data, fieldNameData.utf16Length);
66 }
67 
GetFieldIDByDisplayName(EtsClass * klass,const PandaString & name,const char * sig)68 EtsField *ManglingUtils::GetFieldIDByDisplayName(EtsClass *klass, const PandaString &name, const char *sig)
69 {
70     auto u8name = utf::CStringAsMutf8(name.c_str());
71     auto *field = EtsField::FromRuntimeField(klass->GetRuntimeClass()->GetInstanceFieldByName(u8name));
72     if (field == nullptr && !klass->GetRuntimeClass()->GetInterfaces().empty()) {
73         auto mangledName = PandaString(PROPERTY) + name;
74         u8name = utf::CStringAsMutf8(mangledName.c_str());
75         field = EtsField::FromRuntimeField(klass->GetRuntimeClass()->GetInstanceFieldByName(u8name));
76     }
77 
78     if (sig != nullptr && field != nullptr) {
79         auto fieldTypeDescriptor = reinterpret_cast<const uint8_t *>(field->GetTypeDescriptor());
80         if (utf::CompareMUtf8ToMUtf8(fieldTypeDescriptor, reinterpret_cast<const uint8_t *>(sig)) != 0) {
81             return nullptr;
82         }
83     }
84 
85     return field;
86 }
87 
ExtractClassDescriptorsFromArray(const panda_file::File * pfile,const panda_file::ArrayValue & classesArray,std::vector<std::string> & outDescriptors)88 static void ExtractClassDescriptorsFromArray(const panda_file::File *pfile, const panda_file::ArrayValue &classesArray,
89                                              std::vector<std::string> &outDescriptors)
90 {
91     const uint32_t valCount = classesArray.GetCount();
92     outDescriptors.resize(valCount);
93     for (uint32_t j = 0; j < valCount; j++) {
94         auto entityId = classesArray.Get<panda_file::File::EntityId>(j);
95         panda_file::ClassDataAccessor classData(*pfile, entityId);
96         outDescriptors[j] = utf::Mutf8AsCString(classData.GetDescriptor());
97     }
98 }
99 
100 // NOLINT(clang-analyzer-core) // false positive: this is a function, not a global var
GetExportedClassDescriptorsFromModule(ark::ets::EtsClass * etsGlobalClass,std::vector<std::string> & outDescriptors)101 bool GetExportedClassDescriptorsFromModule(ark::ets::EtsClass *etsGlobalClass, std::vector<std::string> &outDescriptors)
102 {
103     ASSERT(etsGlobalClass != nullptr);
104 
105     const auto *runtimeClass = etsGlobalClass->GetRuntimeClass();
106     const panda_file::File *pfile = runtimeClass->GetPandaFile();
107     panda_file::ClassDataAccessor cda(*pfile, runtimeClass->GetFileId());
108 
109     bool found = false;
110     cda.EnumerateAnnotation(panda_file_items::class_descriptors::ANNOTATION_MODULE.data(),
111                             [&outDescriptors, &found, pfile](panda_file::AnnotationDataAccessor &annotationAccessor) {
112                                 const uint32_t count = annotationAccessor.GetCount();
113                                 for (uint32_t i = 0; i < count; i++) {
114                                     auto elem = annotationAccessor.GetElement(i);
115                                     std::string nameStr =
116                                         utf::Mutf8AsCString(pfile->GetStringData(elem.GetNameId()).data);
117                                     if (nameStr == panda_file_items::class_descriptors::ANNOTATION_MODULE_EXPORTED) {
118                                         auto classesArray = elem.GetArrayValue();
119                                         ExtractClassDescriptorsFromArray(pfile, classesArray, outDescriptors);
120                                         found = true;
121                                         break;
122                                     }
123                                 }
124                                 return true;
125                             });
126 
127     return found;
128 }
129 
130 }  // namespace ark::ets
131