1b1994897Sopenharmony_ci/* 2b1994897Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#include "collect_util.h" 17b1994897Sopenharmony_ci 18b1994897Sopenharmony_ci#include <codecvt> 19b1994897Sopenharmony_ci#include <locale> 20b1994897Sopenharmony_ci 21b1994897Sopenharmony_cinamespace panda::libpandafile { 22b1994897Sopenharmony_ci 23b1994897Sopenharmony_ci/** 24b1994897Sopenharmony_ci * processed_ids: The literal array ids are collected from field and ins, needn't process nest. 25b1994897Sopenharmony_ci * nest_unprocessed_ids: The literal array ids are collected from ins, need process nest. 26b1994897Sopenharmony_ci */ 27b1994897Sopenharmony_civoid CollectUtil::CollectLiteralArray(const panda_file::File &file_, std::unordered_set<uint32_t> &processed_ids) 28b1994897Sopenharmony_ci{ 29b1994897Sopenharmony_ci std::unordered_set<uint32_t> nest_unprocessed_ids; 30b1994897Sopenharmony_ci 31b1994897Sopenharmony_ci for (uint32_t id : file_.GetClasses()) { 32b1994897Sopenharmony_ci panda_file::File::EntityId class_id(id); 33b1994897Sopenharmony_ci if (file_.IsExternal(class_id)) { 34b1994897Sopenharmony_ci continue; 35b1994897Sopenharmony_ci } 36b1994897Sopenharmony_ci panda_file::ClassDataAccessor class_data_accessor(file_, class_id); 37b1994897Sopenharmony_ci CollectClassLiteralArray(class_data_accessor, processed_ids, nest_unprocessed_ids); 38b1994897Sopenharmony_ci } 39b1994897Sopenharmony_ci ProcessNestLiteralArray(file_, processed_ids, nest_unprocessed_ids); 40b1994897Sopenharmony_ci} 41b1994897Sopenharmony_ci 42b1994897Sopenharmony_civoid CollectUtil::CollectClassLiteralArray(panda_file::ClassDataAccessor &class_data_accessor, 43b1994897Sopenharmony_ci std::unordered_set<uint32_t> &processed_ids, 44b1994897Sopenharmony_ci std::unordered_set<uint32_t> &nest_unprocessed_ids) 45b1994897Sopenharmony_ci{ 46b1994897Sopenharmony_ci panda_file::File::StringData csd = class_data_accessor.GetName(); 47b1994897Sopenharmony_ci const char *cn = utf::Mutf8AsCString(csd.data); 48b1994897Sopenharmony_ci class_data_accessor.EnumerateFields([&](panda_file::FieldDataAccessor &field_accessor) -> void { 49b1994897Sopenharmony_ci panda_file::File::EntityId field_name_id = field_accessor.GetNameId(); 50b1994897Sopenharmony_ci panda_file::File::StringData fsd = class_data_accessor.GetPandaFile().GetStringData(field_name_id); 51b1994897Sopenharmony_ci const char *fn = utf::Mutf8AsCString(fsd.data); 52b1994897Sopenharmony_ci if (std::strcmp(cn, ES_MODULE_RECORD.data()) != 0 && 53b1994897Sopenharmony_ci std::strcmp(cn, ES_SCOPE_NAMES_RECORD.data()) != 0 && 54b1994897Sopenharmony_ci std::strcmp(fn, SCOPE_NAMES.data()) != 0 && 55b1994897Sopenharmony_ci std::strcmp(fn, MODULE_RECORD_IDX.data()) != 0) { 56b1994897Sopenharmony_ci return; 57b1994897Sopenharmony_ci } 58b1994897Sopenharmony_ci auto module_offset = field_accessor.GetValue<uint32_t>().value(); 59b1994897Sopenharmony_ci processed_ids.emplace(module_offset); 60b1994897Sopenharmony_ci }); 61b1994897Sopenharmony_ci class_data_accessor.EnumerateMethods([&](panda_file::MethodDataAccessor &method_accessor) -> void { 62b1994897Sopenharmony_ci if (!method_accessor.GetCodeId().has_value()) { 63b1994897Sopenharmony_ci return; 64b1994897Sopenharmony_ci } 65b1994897Sopenharmony_ci panda_file::File::EntityId method_id = method_accessor.GetMethodId(); 66b1994897Sopenharmony_ci panda_file::File::EntityId code_id = method_accessor.GetCodeId().value(); 67b1994897Sopenharmony_ci panda_file::CodeDataAccessor code_data_accessor {class_data_accessor.GetPandaFile(), code_id}; 68b1994897Sopenharmony_ci uint32_t ins_size_ = code_data_accessor.GetCodeSize(); 69b1994897Sopenharmony_ci const uint8_t *ins_arr = code_data_accessor.GetInstructions(); 70b1994897Sopenharmony_ci auto bc_ins = panda::BytecodeInst<BytecodeInstMode::FAST>(ins_arr); 71b1994897Sopenharmony_ci const auto bc_ins_last = bc_ins.JumpTo(ins_size_); 72b1994897Sopenharmony_ci while (bc_ins.GetAddress() < bc_ins_last.GetAddress()) { 73b1994897Sopenharmony_ci if (!bc_ins.IsPrimaryOpcodeValid()) { 74b1994897Sopenharmony_ci LOG(FATAL, PANDAFILE) << "Fail to verify primary opcode!"; 75b1994897Sopenharmony_ci } 76b1994897Sopenharmony_ci if (bc_ins.HasFlag(panda::BytecodeInst<BytecodeInstMode::FAST>::Flags::LITERALARRAY_ID)) { 77b1994897Sopenharmony_ci const auto literal_id = 78b1994897Sopenharmony_ci GetLiteralArrayIdInBytecodeInst(class_data_accessor.GetPandaFile(), method_id, bc_ins); 79b1994897Sopenharmony_ci nest_unprocessed_ids.insert(literal_id.GetOffset()); 80b1994897Sopenharmony_ci } 81b1994897Sopenharmony_ci bc_ins = bc_ins.GetNext(); 82b1994897Sopenharmony_ci } 83b1994897Sopenharmony_ci }); 84b1994897Sopenharmony_ci} 85b1994897Sopenharmony_ci 86b1994897Sopenharmony_civoid CollectUtil::ProcessNestLiteralArray(const panda_file::File &file_, std::unordered_set<uint32_t> &processed_ids, 87b1994897Sopenharmony_ci std::unordered_set<uint32_t> &nest_unprocessed_ids) 88b1994897Sopenharmony_ci{ 89b1994897Sopenharmony_ci if (nest_unprocessed_ids.empty()) { 90b1994897Sopenharmony_ci return; 91b1994897Sopenharmony_ci } 92b1994897Sopenharmony_ci 93b1994897Sopenharmony_ci panda_file::File::EntityId lit_array_invalid(panda_file::INVALID_OFFSET); 94b1994897Sopenharmony_ci panda_file::LiteralDataAccessor literal_data_accessor {file_, lit_array_invalid}; 95b1994897Sopenharmony_ci while (!nest_unprocessed_ids.empty()) { 96b1994897Sopenharmony_ci auto nest_unprocess_id_iterator = nest_unprocessed_ids.begin(); 97b1994897Sopenharmony_ci uint32_t nest_unprocess_id = *nest_unprocess_id_iterator; 98b1994897Sopenharmony_ci processed_ids.emplace(nest_unprocess_id); 99b1994897Sopenharmony_ci panda_file::File::EntityId nest_unprocess_id_entity_id(nest_unprocess_id); 100b1994897Sopenharmony_ci literal_data_accessor.EnumerateLiteralVals( 101b1994897Sopenharmony_ci nest_unprocess_id_entity_id, 102b1994897Sopenharmony_ci [processed_ids, &nest_unprocessed_ids](const panda_file::LiteralDataAccessor::LiteralValue &value, 103b1994897Sopenharmony_ci const panda_file::LiteralTag &tag) { 104b1994897Sopenharmony_ci if (tag != panda_file::LiteralTag::LITERALARRAY) { 105b1994897Sopenharmony_ci return; 106b1994897Sopenharmony_ci } 107b1994897Sopenharmony_ci uint32_t idx = std::get<uint32_t>(value); 108b1994897Sopenharmony_ci if ((processed_ids.find(idx) != processed_ids.end()) || 109b1994897Sopenharmony_ci (nest_unprocessed_ids.find(idx) != nest_unprocessed_ids.end())) { 110b1994897Sopenharmony_ci return; 111b1994897Sopenharmony_ci } 112b1994897Sopenharmony_ci nest_unprocessed_ids.emplace(idx); 113b1994897Sopenharmony_ci }); 114b1994897Sopenharmony_ci nest_unprocessed_ids.erase(nest_unprocess_id); 115b1994897Sopenharmony_ci } 116b1994897Sopenharmony_ci} 117b1994897Sopenharmony_ci 118b1994897Sopenharmony_cipanda_file::File::EntityId CollectUtil::GetLiteralArrayIdInBytecodeInst( 119b1994897Sopenharmony_ci const panda_file::File &file_, panda_file::File::EntityId method_id, 120b1994897Sopenharmony_ci panda::BytecodeInst<BytecodeInstMode::FAST> bc_ins) 121b1994897Sopenharmony_ci{ 122b1994897Sopenharmony_ci size_t idx = bc_ins.GetLiteralIndex(); 123b1994897Sopenharmony_ci if (idx < 0) { 124b1994897Sopenharmony_ci LOG(FATAL, PANDAFILE) << "Fail to verify ID Index!"; 125b1994897Sopenharmony_ci } 126b1994897Sopenharmony_ci const auto arg_literal_idx = bc_ins.GetId(idx).AsIndex(); 127b1994897Sopenharmony_ci const auto literal_id = file_.ResolveMethodIndex(method_id, arg_literal_idx); 128b1994897Sopenharmony_ci return literal_id; 129b1994897Sopenharmony_ci} 130b1994897Sopenharmony_ci 131b1994897Sopenharmony_ci} // namespace panda::libpandafile