13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "evaluate/debugInfoStorage.h" 173af6ab5fSopenharmony_ci#include "assembler/assembly-type.h" 183af6ab5fSopenharmony_ci#include "generated/signatures.h" 193af6ab5fSopenharmony_ci#include "evaluate/helpers.h" 203af6ab5fSopenharmony_ci 213af6ab5fSopenharmony_ci#include "libpandafile/class_data_accessor-inl.h" 223af6ab5fSopenharmony_ci#include "libpandafile/file-inl.h" 233af6ab5fSopenharmony_ci 243af6ab5fSopenharmony_cinamespace ark::es2panda::evaluate { 253af6ab5fSopenharmony_ci 263af6ab5fSopenharmony_cinamespace { 273af6ab5fSopenharmony_ci 283af6ab5fSopenharmony_cistd::string GetFullRecordName(const panda_file::File &pf, const panda_file::File::EntityId &classId) 293af6ab5fSopenharmony_ci{ 303af6ab5fSopenharmony_ci std::string name = utf::Mutf8AsCString(pf.GetStringData(classId).data); 313af6ab5fSopenharmony_ci 323af6ab5fSopenharmony_ci auto type = pandasm::Type::FromDescriptor(name); 333af6ab5fSopenharmony_ci type = pandasm::Type(type.GetComponentName(), type.GetRank()); 343af6ab5fSopenharmony_ci 353af6ab5fSopenharmony_ci return type.GetPandasmName(); 363af6ab5fSopenharmony_ci} 373af6ab5fSopenharmony_ci 383af6ab5fSopenharmony_cibool EndsWith(std::string_view str, std::string_view suffix) 393af6ab5fSopenharmony_ci{ 403af6ab5fSopenharmony_ci auto pos = str.rfind(suffix); 413af6ab5fSopenharmony_ci return pos != std::string::npos && (str.size() - pos) == suffix.size(); 423af6ab5fSopenharmony_ci} 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_ci} // namespace 453af6ab5fSopenharmony_ci 463af6ab5fSopenharmony_ciImportExportTable::ImportExportTable(ArenaAllocator *allocator) 473af6ab5fSopenharmony_ci : imports_(allocator->Adapter()), exports_(allocator->Adapter()) 483af6ab5fSopenharmony_ci{ 493af6ab5fSopenharmony_ci} 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ciDebugInfoStorage::DebugInfoStorage(const CompilerOptions &options, ArenaAllocator *allocator) 523af6ab5fSopenharmony_ci : allocator_(allocator), sourceFileToDebugInfo_(allocator->Adapter()), moduleNameToDebugInfo_(allocator->Adapter()) 533af6ab5fSopenharmony_ci{ 543af6ab5fSopenharmony_ci for (const auto &pfPath : options.debuggerEvalPandaFiles) { 553af6ab5fSopenharmony_ci LoadFileDebugInfo(pfPath); 563af6ab5fSopenharmony_ci } 573af6ab5fSopenharmony_ci} 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_civoid DebugInfoStorage::LoadFileDebugInfo(std::string_view pfPath) 603af6ab5fSopenharmony_ci{ 613af6ab5fSopenharmony_ci auto pf = panda_file::OpenPandaFile(pfPath); 623af6ab5fSopenharmony_ci if (!pf) { 633af6ab5fSopenharmony_ci LOG(FATAL, ES2PANDA) << "Failed to load a provided abc file: " << pfPath; 643af6ab5fSopenharmony_ci } 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ci for (auto id : pf->GetClasses()) { 673af6ab5fSopenharmony_ci panda_file::File::EntityId classId(id); 683af6ab5fSopenharmony_ci if (pf->IsExternal(classId)) { 693af6ab5fSopenharmony_ci continue; 703af6ab5fSopenharmony_ci } 713af6ab5fSopenharmony_ci 723af6ab5fSopenharmony_ci auto recordName = GetFullRecordName(*pf, classId); 733af6ab5fSopenharmony_ci if (!EndsWith(recordName, compiler::Signatures::ETS_GLOBAL)) { 743af6ab5fSopenharmony_ci continue; 753af6ab5fSopenharmony_ci } 763af6ab5fSopenharmony_ci 773af6ab5fSopenharmony_ci std::string_view moduleName = helpers::SplitRecordName(recordName).first; 783af6ab5fSopenharmony_ci auto *debugInfo = allocator_->New<FileDebugInfo>(std::move(pf), classId, moduleName); 793af6ab5fSopenharmony_ci auto sourceFileId = debugInfo->globalClassAcc.GetSourceFileId(); 803af6ab5fSopenharmony_ci ASSERT(sourceFileId.has_value()); 813af6ab5fSopenharmony_ci std::string_view sourceFileName = utf::Mutf8AsCString(debugInfo->pf->GetStringData(*sourceFileId).data); 823af6ab5fSopenharmony_ci debugInfo->sourceFilePath = sourceFileName; 833af6ab5fSopenharmony_ci 843af6ab5fSopenharmony_ci sourceFileToDebugInfo_.emplace(sourceFileName, debugInfo); 853af6ab5fSopenharmony_ci moduleNameToDebugInfo_.emplace(moduleName, debugInfo); 863af6ab5fSopenharmony_ci return; 873af6ab5fSopenharmony_ci } 883af6ab5fSopenharmony_ci 893af6ab5fSopenharmony_ci LOG(FATAL, ES2PANDA) << "ETSGLOBAL not found in provided file: " << pfPath; 903af6ab5fSopenharmony_ci} 913af6ab5fSopenharmony_ci 923af6ab5fSopenharmony_ciconst panda_file::File *DebugInfoStorage::GetPandaFile(std::string_view filePath) 933af6ab5fSopenharmony_ci{ 943af6ab5fSopenharmony_ci auto iter = sourceFileToDebugInfo_.find(filePath); 953af6ab5fSopenharmony_ci if (iter == sourceFileToDebugInfo_.end()) { 963af6ab5fSopenharmony_ci return nullptr; 973af6ab5fSopenharmony_ci } 983af6ab5fSopenharmony_ci return iter->second->pf.get(); 993af6ab5fSopenharmony_ci} 1003af6ab5fSopenharmony_ci 1013af6ab5fSopenharmony_ciconst ImportExportTable *DebugInfoStorage::GetImportExportTable(std::string_view filePath) 1023af6ab5fSopenharmony_ci{ 1033af6ab5fSopenharmony_ci auto iter = sourceFileToDebugInfo_.find(filePath); 1043af6ab5fSopenharmony_ci if (iter == sourceFileToDebugInfo_.end()) { 1053af6ab5fSopenharmony_ci return nullptr; 1063af6ab5fSopenharmony_ci } 1073af6ab5fSopenharmony_ci return &LazyLoadImportExportTable(iter->second); 1083af6ab5fSopenharmony_ci} 1093af6ab5fSopenharmony_ci 1103af6ab5fSopenharmony_cipanda_file::ClassDataAccessor *DebugInfoStorage::GetGlobalClassAccessor(std::string_view filePath) 1113af6ab5fSopenharmony_ci{ 1123af6ab5fSopenharmony_ci auto iter = sourceFileToDebugInfo_.find(filePath); 1133af6ab5fSopenharmony_ci if (iter == sourceFileToDebugInfo_.end()) { 1143af6ab5fSopenharmony_ci return nullptr; 1153af6ab5fSopenharmony_ci } 1163af6ab5fSopenharmony_ci return &iter->second->globalClassAcc; 1173af6ab5fSopenharmony_ci} 1183af6ab5fSopenharmony_ci 1193af6ab5fSopenharmony_cistd::string_view DebugInfoStorage::GetModuleName(std::string_view filePath) 1203af6ab5fSopenharmony_ci{ 1213af6ab5fSopenharmony_ci auto iter = sourceFileToDebugInfo_.find(filePath); 1223af6ab5fSopenharmony_ci if (iter == sourceFileToDebugInfo_.end()) { 1233af6ab5fSopenharmony_ci return {}; 1243af6ab5fSopenharmony_ci } 1253af6ab5fSopenharmony_ci return iter->second->moduleName; 1263af6ab5fSopenharmony_ci} 1273af6ab5fSopenharmony_ci 1283af6ab5fSopenharmony_cipanda_file::File::EntityId DebugInfoStorage::FindClass(std::string_view filePath, std::string_view className) 1293af6ab5fSopenharmony_ci{ 1303af6ab5fSopenharmony_ci auto iter = sourceFileToDebugInfo_.find(filePath); 1313af6ab5fSopenharmony_ci if (iter == sourceFileToDebugInfo_.end()) { 1323af6ab5fSopenharmony_ci return panda_file::File::EntityId(); 1333af6ab5fSopenharmony_ci } 1343af6ab5fSopenharmony_ci 1353af6ab5fSopenharmony_ci const auto &records = LazyLoadRecords(iter->second); 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_ci auto classIter = records.find(className); 1383af6ab5fSopenharmony_ci return classIter == records.end() ? panda_file::File::EntityId() : classIter->second; 1393af6ab5fSopenharmony_ci} 1403af6ab5fSopenharmony_ci 1413af6ab5fSopenharmony_cibool DebugInfoStorage::FillEvaluateContext(EvaluateContext &context) 1423af6ab5fSopenharmony_ci{ 1433af6ab5fSopenharmony_ci const auto *contextPandaFile = GetPandaFile(context.sourceFilePath.Utf8()); 1443af6ab5fSopenharmony_ci if (contextPandaFile == nullptr) { 1453af6ab5fSopenharmony_ci LOG(WARNING, ES2PANDA) << "Could not find context file: " << context.sourceFilePath << std::endl; 1463af6ab5fSopenharmony_ci return false; 1473af6ab5fSopenharmony_ci } 1483af6ab5fSopenharmony_ci 1493af6ab5fSopenharmony_ci context.file = contextPandaFile; 1503af6ab5fSopenharmony_ci context.extractor = std::make_unique<panda_file::DebugInfoExtractor>(contextPandaFile); 1513af6ab5fSopenharmony_ci 1523af6ab5fSopenharmony_ci for (auto methodId : context.extractor->GetMethodIdList()) { 1533af6ab5fSopenharmony_ci for (const auto &entry : context.extractor->GetLineNumberTable(methodId)) { 1543af6ab5fSopenharmony_ci if (context.lineNumber == entry.line) { 1553af6ab5fSopenharmony_ci context.methodId = methodId; 1563af6ab5fSopenharmony_ci context.bytecodeOffset = entry.offset; 1573af6ab5fSopenharmony_ci util::UString sourceFilePath(std::string_view(context.extractor->GetSourceFile(methodId)), allocator_); 1583af6ab5fSopenharmony_ci context.sourceFilePath = sourceFilePath.View(); 1593af6ab5fSopenharmony_ci return true; 1603af6ab5fSopenharmony_ci } 1613af6ab5fSopenharmony_ci } 1623af6ab5fSopenharmony_ci } 1633af6ab5fSopenharmony_ci LOG(WARNING, ES2PANDA) << "Could not find code at line: " << context.lineNumber << std::endl; 1643af6ab5fSopenharmony_ci return false; 1653af6ab5fSopenharmony_ci} 1663af6ab5fSopenharmony_ci 1673af6ab5fSopenharmony_ciconst ImportExportTable &DebugInfoStorage::LazyLoadImportExportTable(FileDebugInfo *info) 1683af6ab5fSopenharmony_ci{ 1693af6ab5fSopenharmony_ci ASSERT(info); 1703af6ab5fSopenharmony_ci 1713af6ab5fSopenharmony_ci if (info->importExportTable.has_value()) { 1723af6ab5fSopenharmony_ci return *info->importExportTable; 1733af6ab5fSopenharmony_ci } 1743af6ab5fSopenharmony_ci 1753af6ab5fSopenharmony_ci // NOTE: load table after it is implemented in compiler. 1763af6ab5fSopenharmony_ci info->importExportTable.emplace(allocator_); 1773af6ab5fSopenharmony_ci return info->importExportTable.value(); 1783af6ab5fSopenharmony_ci} 1793af6ab5fSopenharmony_ci 1803af6ab5fSopenharmony_ciconst FileDebugInfo::RecordsMap &DebugInfoStorage::LazyLoadRecords(FileDebugInfo *info) 1813af6ab5fSopenharmony_ci{ 1823af6ab5fSopenharmony_ci ASSERT(info); 1833af6ab5fSopenharmony_ci 1843af6ab5fSopenharmony_ci if (info->records.has_value()) { 1853af6ab5fSopenharmony_ci return *info->records; 1863af6ab5fSopenharmony_ci } 1873af6ab5fSopenharmony_ci 1883af6ab5fSopenharmony_ci info->records.emplace(allocator_->Adapter()); 1893af6ab5fSopenharmony_ci auto &records = *info->records; 1903af6ab5fSopenharmony_ci 1913af6ab5fSopenharmony_ci const auto *pf = info->pf.get(); 1923af6ab5fSopenharmony_ci for (auto id : pf->GetClasses()) { 1933af6ab5fSopenharmony_ci panda_file::File::EntityId classId(id); 1943af6ab5fSopenharmony_ci if (pf->IsExternal(classId)) { 1953af6ab5fSopenharmony_ci // Сlass that marked in currect .abc file as <external> should be define in some other .abc file. 1963af6ab5fSopenharmony_ci // Thus we will not lose information about this class. 1973af6ab5fSopenharmony_ci continue; 1983af6ab5fSopenharmony_ci } 1993af6ab5fSopenharmony_ci 2003af6ab5fSopenharmony_ci auto recordName = helpers::SplitRecordName(GetFullRecordName(*pf, classId)).second; 2013af6ab5fSopenharmony_ci auto recordNameView = util::UString(recordName, allocator_).View(); 2023af6ab5fSopenharmony_ci if (!records.emplace(recordNameView, classId).second) { 2033af6ab5fSopenharmony_ci LOG(FATAL, ES2PANDA) << "Failed to emplace class '" << recordNameView << "' in records." 2043af6ab5fSopenharmony_ci << "There should be only one declaration of the same class."; 2053af6ab5fSopenharmony_ci } 2063af6ab5fSopenharmony_ci } 2073af6ab5fSopenharmony_ci 2083af6ab5fSopenharmony_ci return records; 2093af6ab5fSopenharmony_ci} 2103af6ab5fSopenharmony_ci 2113af6ab5fSopenharmony_ciFileDebugInfo *DebugInfoStorage::GetDebugInfoByModuleName(std::string_view moduleName) const 2123af6ab5fSopenharmony_ci{ 2133af6ab5fSopenharmony_ci auto find = moduleNameToDebugInfo_.find(moduleName); 2143af6ab5fSopenharmony_ci if (find != moduleNameToDebugInfo_.end()) { 2153af6ab5fSopenharmony_ci return find->second; 2163af6ab5fSopenharmony_ci } 2173af6ab5fSopenharmony_ci return nullptr; 2183af6ab5fSopenharmony_ci} 2193af6ab5fSopenharmony_ci 2203af6ab5fSopenharmony_ci} // namespace ark::es2panda::evaluate 221