• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "abc_method_processor.h"
17 #include "abc_code_processor.h"
18 
19 namespace panda::abc2program {
20 
AbcMethodProcessor(panda_file::File::EntityId entity_id,Abc2ProgramEntityContainer & entity_container)21 AbcMethodProcessor::AbcMethodProcessor(panda_file::File::EntityId entity_id,
22                                        Abc2ProgramEntityContainer &entity_container)
23     : AbcFileEntityProcessor(entity_id, entity_container),
24       type_converter_(entity_container),
25       function_(pandasm::Function(entity_container_.GetFullMethodNameById(entity_id_), DEFUALT_SOURCE_LANG)),
26       debug_info_extractor_(entity_container.GetDebugInfoExtractor())
27 {
28     method_data_accessor_ = std::make_unique<panda_file::MethodDataAccessor>(*file_, entity_id_);
29     function_.language = method_data_accessor_->GetSourceLang().value_or(DEFUALT_SOURCE_LANG);
30 }
31 
FillProgramData()32 void AbcMethodProcessor::FillProgramData()
33 {
34     FillFunctionData();
35     program_->function_table.emplace(function_.name, std::move(function_));
36 }
37 
FillFunctionData()38 void AbcMethodProcessor::FillFunctionData()
39 {
40     FillProto();
41     FillFunctionKind();
42     FillFunctionMetaData();
43     FillCodeData();
44     FillDebugInfo();
45     FillFuncAnnotation();
46     FillAnnotationData();
47 }
48 
FillProto()49 void AbcMethodProcessor::FillProto()
50 {
51     static const uint32_t maxArgNum = 0xFFFF;
52     uint32_t params_num = GetNumArgs();
53     if (params_num > maxArgNum) {
54         LOG(ERROR, ABC2PROGRAM) << "> error encountered at " << entity_id_.GetOffset() << " (0x" << std::hex
55                                 << entity_id_.GetOffset() << "). number of function's arguments (" << std::dec
56                                 << params_num << ") exceeds maxArgNum (" << maxArgNum << ") !";
57         return;
58     }
59 
60     pandasm::Type any_type = pandasm::Type(ANY_TYPE_NAME, 0);
61     function_.return_type = any_type;
62     for (uint32_t i = 0; i < params_num; i++) {
63         function_.params.emplace_back(
64             pandasm::Function::Parameter(any_type, function_.language)
65         );
66     }
67 }
68 
GetNumArgs() const69 uint32_t AbcMethodProcessor::GetNumArgs() const
70 {
71     std::optional<panda_file::File::EntityId> code_id = method_data_accessor_->GetCodeId();
72     if (!code_id.has_value()) {
73         return 0;
74     }
75     panda_file::File::EntityId code_id_value = code_id.value();
76     panda_file::CodeDataAccessor code_data_accessor(*file_, code_id_value);
77     return code_data_accessor.GetNumArgs();
78 }
79 
FillFunctionKind()80 void AbcMethodProcessor::FillFunctionKind()
81 {
82     uint32_t method_acc_flags = method_data_accessor_->GetAccessFlags();
83     uint32_t func_kind_u32 = ((method_acc_flags & panda_file::FUNCTION_KIND_MASK) >> panda_file::FLAG_WIDTH);
84     panda_file::FunctionKind func_kind = static_cast<panda_file::FunctionKind>(func_kind_u32);
85     function_.SetFunctionKind(func_kind);
86 }
87 
FillFunctionMetaData()88 void AbcMethodProcessor::FillFunctionMetaData()
89 {
90     FillFunctionAttributes();
91     FillAccessFlags();
92 }
93 
FillFunctionAttributes()94 void AbcMethodProcessor::FillFunctionAttributes()
95 {
96     if (method_data_accessor_->IsStatic()) {
97         function_.metadata->SetAttribute(ABC_ATTR_STATIC);
98     }
99     if (file_->IsExternal(method_data_accessor_->GetMethodId())) {
100         function_.metadata->SetAttribute(ABC_ATTR_EXTERNAL);
101     }
102 }
103 
FillAccessFlags()104 void AbcMethodProcessor::FillAccessFlags()
105 {
106     uint32_t access_flags = method_data_accessor_->GetAccessFlags();
107     access_flags = (access_flags & panda_file::FLAG_MASK);
108     function_.metadata->SetAccessFlags(access_flags);
109 }
110 
FillCodeData()111 void AbcMethodProcessor::FillCodeData()
112 {
113     std::optional<panda_file::File::EntityId> code_id = method_data_accessor_->GetCodeId();
114     if (code_id.has_value()) {
115         AbcCodeProcessor code_processor(code_id.value(), entity_container_, entity_id_, function_);
116         code_processor.FillProgramData();
117     }
118 }
119 
FillDebugInfo()120 void AbcMethodProcessor::FillDebugInfo()
121 {
122     FillSourceFile();
123     FillSourceCode();
124 }
125 
FillSourceFile()126 void AbcMethodProcessor::FillSourceFile()
127 {
128     function_.source_file = debug_info_extractor_.GetSourceFile(entity_id_);
129 }
130 
FillSourceCode()131 void AbcMethodProcessor::FillSourceCode()
132 {
133     function_.source_code = debug_info_extractor_.GetSourceCode(entity_id_);
134 }
135 
FillFuncAnnotation()136 void AbcMethodProcessor::FillFuncAnnotation()
137 {
138     method_data_accessor_->EnumerateAnnotations([&](panda_file::File::EntityId annotation_id) {
139         AbcAnnotationProcessor annotation_processor(annotation_id, entity_container_, function_);
140         annotation_processor.FillProgramData();
141     });
142 }
143 
FillAnnotationData()144 void AbcMethodProcessor::FillAnnotationData()
145 {
146     for (auto annotation : function_.metadata->GetAnnotations()) {
147         const auto& name = annotation.GetName();
148         const auto& elements = annotation.GetElements();
149 
150         if (name == SLOT_NUMBER_RECORD_NAME && !elements.empty()) {
151             uint32_t slots_num = elements[0].GetValue()->GetAsScalar()->GetValue<uint32_t>();
152             function_.SetSlotsNum(static_cast<size_t>(slots_num));
153         } else if (name == CONCURRENT_MODULE_REQUEST_RECORD_NAME) {
154             for (auto &elem : elements) {
155                 function_.concurrent_module_requests.emplace_back(
156                     elem.GetValue()->GetAsScalar()->GetValue<uint32_t>());
157             }
158         } else if (name == EXPECTED_PROPERTY_COUNT_RECORD_NAME && !elements.empty()) {
159             uint32_t expected_property = elements[0].GetValue()->GetAsScalar()->GetValue<uint32_t>();
160             function_.SetExpectedPropertyCount(static_cast<size_t>(expected_property));
161         }
162     }
163 }
164 } // namespace panda::abc2program