1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-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 <algorithm> 17b1994897Sopenharmony_ci#include <cerrno> 18b1994897Sopenharmony_ci#include <cstdio> 19b1994897Sopenharmony_ci#include <cstring> 20b1994897Sopenharmony_ci#include <map> 21b1994897Sopenharmony_ci#include <memory> 22b1994897Sopenharmony_ci#include <string> 23b1994897Sopenharmony_ci#include <variant> 24b1994897Sopenharmony_ci 25b1994897Sopenharmony_ci#include "data_protect.h" 26b1994897Sopenharmony_ci#include "file_format_version.h" 27b1994897Sopenharmony_ci#include "file-inl.h" 28b1994897Sopenharmony_ci#include "file_items.h" 29b1994897Sopenharmony_ci#include "mem/mem.h" 30b1994897Sopenharmony_ci#include "os/file.h" 31b1994897Sopenharmony_ci#include "os/filesystem.h" 32b1994897Sopenharmony_ci#include "os/mem.h" 33b1994897Sopenharmony_ci#include "panda_cache.h" 34b1994897Sopenharmony_ci#include "securec.h" 35b1994897Sopenharmony_ci#include "trace/trace.h" 36b1994897Sopenharmony_ci#include "utils/hash.h" 37b1994897Sopenharmony_ci#include "utils/logger.h" 38b1994897Sopenharmony_ci#include "utils/utf.h" 39b1994897Sopenharmony_ci#include "utils/span.h" 40b1994897Sopenharmony_ci#include "zip_archive.h" 41b1994897Sopenharmony_ci#include "zlib.h" 42b1994897Sopenharmony_ci 43b1994897Sopenharmony_cinamespace panda::panda_file { 44b1994897Sopenharmony_ci// NOLINTNEXTLINE(readability-identifier-naming, modernize-avoid-c-arrays) 45b1994897Sopenharmony_ciconst char *ARCHIVE_FILENAME = "classes.abc"; 46b1994897Sopenharmony_ci// NOLINTNEXTLINE(readability-identifier-naming, modernize-avoid-c-arrays) 47b1994897Sopenharmony_ciconst char *ARCHIVE_SPLIT = "!/"; 48b1994897Sopenharmony_ci 49b1994897Sopenharmony_ciconst std::array<uint8_t, File::MAGIC_SIZE> File::MAGIC {'P', 'A', 'N', 'D', 'A', '\0', '\0', '\0'}; 50b1994897Sopenharmony_ci 51b1994897Sopenharmony_ci// Name anonymous maps for perfing tools finding symbol file correctly. 52b1994897Sopenharmony_ci// NOLINTNEXTLINE(readability-identifier-naming, modernize-avoid-c-arrays) 53b1994897Sopenharmony_ciconst char *ANONMAPNAME_PERFIX = "panda-"; 54b1994897Sopenharmony_ci 55b1994897Sopenharmony_cios::file::Mode GetMode(panda_file::File::OpenMode open_mode) 56b1994897Sopenharmony_ci{ 57b1994897Sopenharmony_ci switch (open_mode) { 58b1994897Sopenharmony_ci case File::READ_ONLY: { 59b1994897Sopenharmony_ci return os::file::Mode::READONLY; 60b1994897Sopenharmony_ci } 61b1994897Sopenharmony_ci case File::READ_WRITE: { 62b1994897Sopenharmony_ci#ifdef PANDA_TARGET_WINDOWS 63b1994897Sopenharmony_ci return os::file::Mode::READWRITE; 64b1994897Sopenharmony_ci#else 65b1994897Sopenharmony_ci return os::file::Mode::READONLY; 66b1994897Sopenharmony_ci#endif 67b1994897Sopenharmony_ci } 68b1994897Sopenharmony_ci case File::WRITE_ONLY: { 69b1994897Sopenharmony_ci return os::file::Mode::WRITEONLY; 70b1994897Sopenharmony_ci } 71b1994897Sopenharmony_ci default: { 72b1994897Sopenharmony_ci break; 73b1994897Sopenharmony_ci } 74b1994897Sopenharmony_ci } 75b1994897Sopenharmony_ci 76b1994897Sopenharmony_ci UNREACHABLE(); 77b1994897Sopenharmony_ci} 78b1994897Sopenharmony_ci 79b1994897Sopenharmony_cistatic uint32_t GetProt(panda_file::File::OpenMode mode) 80b1994897Sopenharmony_ci{ 81b1994897Sopenharmony_ci uint32_t prot = os::mem::MMAP_PROT_READ; 82b1994897Sopenharmony_ci if (mode == File::READ_WRITE) { 83b1994897Sopenharmony_ci prot |= os::mem::MMAP_PROT_WRITE; 84b1994897Sopenharmony_ci } 85b1994897Sopenharmony_ci return prot; 86b1994897Sopenharmony_ci} 87b1994897Sopenharmony_ci 88b1994897Sopenharmony_ciclass AnonMemSet { 89b1994897Sopenharmony_cipublic: 90b1994897Sopenharmony_ci using MemNameSet = std::map<std::string, std::string>; 91b1994897Sopenharmony_ci using InsertResult = std::map<std::string, std::string>::iterator; 92b1994897Sopenharmony_ci 93b1994897Sopenharmony_ci static AnonMemSet &GetInstance() 94b1994897Sopenharmony_ci { 95b1994897Sopenharmony_ci static AnonMemSet anon_mem_set; 96b1994897Sopenharmony_ci return anon_mem_set; 97b1994897Sopenharmony_ci } 98b1994897Sopenharmony_ci 99b1994897Sopenharmony_ci InsertResult Insert(const std::string &file_name, const std::string &anon_mem_name) 100b1994897Sopenharmony_ci { 101b1994897Sopenharmony_ci return mem_name_set_.emplace(file_name, anon_mem_name).first; 102b1994897Sopenharmony_ci } 103b1994897Sopenharmony_ci 104b1994897Sopenharmony_ci void Remove(const std::string &file_name) 105b1994897Sopenharmony_ci { 106b1994897Sopenharmony_ci auto it = mem_name_set_.find(file_name); 107b1994897Sopenharmony_ci if (it != mem_name_set_.end()) { 108b1994897Sopenharmony_ci mem_name_set_.erase(it); 109b1994897Sopenharmony_ci } 110b1994897Sopenharmony_ci } 111b1994897Sopenharmony_ci 112b1994897Sopenharmony_ciprivate: 113b1994897Sopenharmony_ci MemNameSet mem_name_set_; 114b1994897Sopenharmony_ci}; 115b1994897Sopenharmony_ci 116b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFileOrZip(std::string_view location, panda_file::File::OpenMode open_mode) 117b1994897Sopenharmony_ci{ 118b1994897Sopenharmony_ci std::string_view archive_filename = ARCHIVE_FILENAME; 119b1994897Sopenharmony_ci std::size_t archive_split_index = location.find(ARCHIVE_SPLIT); 120b1994897Sopenharmony_ci if (archive_split_index != std::string::npos) { 121b1994897Sopenharmony_ci archive_filename = location.substr(archive_split_index + 2); // 2 - archive split size 122b1994897Sopenharmony_ci location = location.substr(0, archive_split_index); 123b1994897Sopenharmony_ci } 124b1994897Sopenharmony_ci 125b1994897Sopenharmony_ci return OpenPandaFile(location, archive_filename, open_mode); 126b1994897Sopenharmony_ci} 127b1994897Sopenharmony_ci 128b1994897Sopenharmony_ci// NOLINTNEXTLINE(google-runtime-references) 129b1994897Sopenharmony_civoid OpenPandaFileFromZipErrorHandler(ZipArchiveHandle &handle) 130b1994897Sopenharmony_ci{ 131b1994897Sopenharmony_ci if (handle != nullptr) { 132b1994897Sopenharmony_ci if (panda::CloseArchiveFile(handle) != ZIPARCHIVE_OK) { 133b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "CloseArchiveFile failed!"; 134b1994897Sopenharmony_ci } 135b1994897Sopenharmony_ci } 136b1994897Sopenharmony_ci} 137b1994897Sopenharmony_ci 138b1994897Sopenharmony_cistd::unique_ptr<const panda_file::File> OpenPandaFileFromZipFile(ZipArchiveHandle &handle, std::string_view location, 139b1994897Sopenharmony_ci EntryFileStat &entry, 140b1994897Sopenharmony_ci const std::string_view &archive_name) 141b1994897Sopenharmony_ci{ 142b1994897Sopenharmony_ci uint32_t uncompressed_length = entry.GetUncompressedSize(); 143b1994897Sopenharmony_ci ASSERT(uncompressed_length != 0U); 144b1994897Sopenharmony_ci 145b1994897Sopenharmony_ci size_t size_to_mmap = AlignUp(uncompressed_length, panda::os::mem::GetPageSize()); 146b1994897Sopenharmony_ci void *mem = os::mem::MapRWAnonymousRaw(size_to_mmap, false); 147b1994897Sopenharmony_ci if (mem == nullptr) { 148b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't mmap anonymous!"; 149b1994897Sopenharmony_ci return nullptr; 150b1994897Sopenharmony_ci } 151b1994897Sopenharmony_ci os::mem::BytePtr ptr(reinterpret_cast<std::byte *>(mem), size_to_mmap, os::mem::MmapDeleter); 152b1994897Sopenharmony_ci std::stringstream ss; 153b1994897Sopenharmony_ci ss << ANONMAPNAME_PERFIX << archive_name << " extracted in memory from " << location; 154b1994897Sopenharmony_ci auto it = AnonMemSet::GetInstance().Insert(std::string(location), ss.str()); 155b1994897Sopenharmony_ci auto ret = os::mem::TagAnonymousMemory(reinterpret_cast<void *>(ptr.Get()), size_to_mmap, it->second.c_str()); 156b1994897Sopenharmony_ci if (ret.has_value()) { 157b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't tag mmap anonymous!"; 158b1994897Sopenharmony_ci return nullptr; 159b1994897Sopenharmony_ci } 160b1994897Sopenharmony_ci 161b1994897Sopenharmony_ci auto extract_error = ExtractToMemory(handle, reinterpret_cast<uint8_t *>(ptr.Get()), size_to_mmap); 162b1994897Sopenharmony_ci if (extract_error != 0) { 163b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't extract!"; 164b1994897Sopenharmony_ci return nullptr; 165b1994897Sopenharmony_ci } 166b1994897Sopenharmony_ci 167b1994897Sopenharmony_ci os::mem::ConstBytePtr ConstPtr = ptr.ToConst(); 168b1994897Sopenharmony_ci return panda_file::File::OpenFromMemory(std::move(ConstPtr), location); 169b1994897Sopenharmony_ci} 170b1994897Sopenharmony_ci 171b1994897Sopenharmony_ci// NOLINTNEXTLINE(google-runtime-references) 172b1994897Sopenharmony_cistd::unique_ptr<const panda_file::File> HandleArchive(ZipArchiveHandle &handle, FILE *fp, std::string_view location, 173b1994897Sopenharmony_ci EntryFileStat &entry, const std::string_view &archive_filename, 174b1994897Sopenharmony_ci panda_file::File::OpenMode open_mode) 175b1994897Sopenharmony_ci{ 176b1994897Sopenharmony_ci std::unique_ptr<const panda_file::File> file; 177b1994897Sopenharmony_ci // compressed or not 4 aligned, use anonymous memory 178b1994897Sopenharmony_ci if (entry.IsCompressed() || (entry.GetOffset() & 0x3U) != 0) { 179b1994897Sopenharmony_ci file = OpenPandaFileFromZipFile(handle, location, entry, archive_filename); 180b1994897Sopenharmony_ci } else { 181b1994897Sopenharmony_ci LOG(INFO, PANDAFILE) << "Pandafile is uncompressed and 4 bytes aligned"; 182b1994897Sopenharmony_ci file = panda_file::File::OpenUncompressedArchive(fileno(fp), location, entry.GetUncompressedSize(), 183b1994897Sopenharmony_ci entry.GetOffset(), open_mode); 184b1994897Sopenharmony_ci } 185b1994897Sopenharmony_ci return file; 186b1994897Sopenharmony_ci} 187b1994897Sopenharmony_ci 188b1994897Sopenharmony_cistd::unique_ptr<const panda_file::File> OpenPandaFileFromZip(FILE *fp, std::string_view location, 189b1994897Sopenharmony_ci std::string_view archive_filename, 190b1994897Sopenharmony_ci panda_file::File::OpenMode open_mode) 191b1994897Sopenharmony_ci{ 192b1994897Sopenharmony_ci // Open Zipfile and do the extraction. 193b1994897Sopenharmony_ci ZipArchiveHandle zipfile = nullptr; 194b1994897Sopenharmony_ci if (OpenArchiveFile(zipfile, fp) != ZIPARCHIVE_OK) { 195b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't open archive " << location; 196b1994897Sopenharmony_ci return nullptr; 197b1994897Sopenharmony_ci } 198b1994897Sopenharmony_ci bool try_default = archive_filename.empty(); 199b1994897Sopenharmony_ci if (!try_default && LocateFile(zipfile, archive_filename.data()) != ZIPARCHIVE_OK) { 200b1994897Sopenharmony_ci LOG(INFO, PANDAFILE) << "Can't find entry with name '" << 201b1994897Sopenharmony_ci archive_filename << "', will try " << ARCHIVE_FILENAME; 202b1994897Sopenharmony_ci try_default = true; 203b1994897Sopenharmony_ci } 204b1994897Sopenharmony_ci if (try_default && LocateFile(zipfile, ARCHIVE_FILENAME) != ZIPARCHIVE_OK) { 205b1994897Sopenharmony_ci OpenPandaFileFromZipErrorHandler(zipfile); 206b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't find entry with " << ARCHIVE_FILENAME; 207b1994897Sopenharmony_ci return nullptr; 208b1994897Sopenharmony_ci } 209b1994897Sopenharmony_ci 210b1994897Sopenharmony_ci EntryFileStat entry = EntryFileStat(); 211b1994897Sopenharmony_ci if (GetCurrentFileInfo(zipfile, &entry) != ZIPARCHIVE_OK) { 212b1994897Sopenharmony_ci OpenPandaFileFromZipErrorHandler(zipfile); 213b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "GetCurrentFileInfo error"; 214b1994897Sopenharmony_ci return nullptr; 215b1994897Sopenharmony_ci } 216b1994897Sopenharmony_ci // check that file is not empty, otherwise crash at CloseArchiveFile 217b1994897Sopenharmony_ci if (entry.GetUncompressedSize() == 0) { 218b1994897Sopenharmony_ci OpenPandaFileFromZipErrorHandler(zipfile); 219b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file '" << (try_default ? ARCHIVE_FILENAME : archive_filename) << "'"; 220b1994897Sopenharmony_ci return nullptr; 221b1994897Sopenharmony_ci } 222b1994897Sopenharmony_ci if (OpenCurrentFile(zipfile) != ZIPARCHIVE_OK) { 223b1994897Sopenharmony_ci CloseCurrentFile(zipfile); 224b1994897Sopenharmony_ci OpenPandaFileFromZipErrorHandler(zipfile); 225b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't OpenCurrentFile!"; 226b1994897Sopenharmony_ci return nullptr; 227b1994897Sopenharmony_ci } 228b1994897Sopenharmony_ci GetCurrentFileOffset(zipfile, &entry); 229b1994897Sopenharmony_ci std::unique_ptr<const panda_file::File> file = HandleArchive(zipfile, fp, location, entry, 230b1994897Sopenharmony_ci archive_filename, open_mode); 231b1994897Sopenharmony_ci CloseCurrentFile(zipfile); 232b1994897Sopenharmony_ci OpenPandaFileFromZipErrorHandler(zipfile); 233b1994897Sopenharmony_ci return file; 234b1994897Sopenharmony_ci} 235b1994897Sopenharmony_ci 236b1994897Sopenharmony_cistd::unique_ptr<const panda_file::File> OpenPandaFile(std::string_view location, std::string_view archive_filename, 237b1994897Sopenharmony_ci panda_file::File::OpenMode open_mode) 238b1994897Sopenharmony_ci{ 239b1994897Sopenharmony_ci trace::ScopedTrace scoped_trace("Open panda file " + std::string(location)); 240b1994897Sopenharmony_ci uint32_t magic; 241b1994897Sopenharmony_ci 242b1994897Sopenharmony_ci#ifdef PANDA_TARGET_WINDOWS 243b1994897Sopenharmony_ci constexpr char const *mode = "rb"; 244b1994897Sopenharmony_ci#else 245b1994897Sopenharmony_ci constexpr char const *mode = "rbe"; 246b1994897Sopenharmony_ci#endif 247b1994897Sopenharmony_ci 248b1994897Sopenharmony_ci FILE *fp = fopen(std::string(location).c_str(), mode); 249b1994897Sopenharmony_ci if (fp == nullptr) { 250b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't fopen location: " << location; 251b1994897Sopenharmony_ci return nullptr; 252b1994897Sopenharmony_ci } 253b1994897Sopenharmony_ci (void)fseek(fp, 0, SEEK_SET); 254b1994897Sopenharmony_ci if (fread(&magic, sizeof(magic), 1, fp) != 1) { 255b1994897Sopenharmony_ci fclose(fp); 256b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can't read from file!(magic) " << location; 257b1994897Sopenharmony_ci return nullptr; 258b1994897Sopenharmony_ci } 259b1994897Sopenharmony_ci (void)fseek(fp, 0, SEEK_SET); 260b1994897Sopenharmony_ci std::unique_ptr<const panda_file::File> file; 261b1994897Sopenharmony_ci if (IsZipMagic(magic)) { 262b1994897Sopenharmony_ci file = OpenPandaFileFromZip(fp, location, archive_filename, open_mode); 263b1994897Sopenharmony_ci } else { 264b1994897Sopenharmony_ci file = panda_file::File::Open(location, open_mode); 265b1994897Sopenharmony_ci } 266b1994897Sopenharmony_ci fclose(fp); 267b1994897Sopenharmony_ci return file; 268b1994897Sopenharmony_ci} 269b1994897Sopenharmony_ci 270b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFileFromMemory(const void *buffer, size_t size, std::string tag) 271b1994897Sopenharmony_ci{ 272b1994897Sopenharmony_ci size_t size_to_mmap = AlignUp(size, panda::os::mem::GetPageSize()); 273b1994897Sopenharmony_ci void *mem = os::mem::MapRWAnonymousRaw(size_to_mmap, false); 274b1994897Sopenharmony_ci if (mem == nullptr) { 275b1994897Sopenharmony_ci return nullptr; 276b1994897Sopenharmony_ci } 277b1994897Sopenharmony_ci 278b1994897Sopenharmony_ci if (memcpy_s(mem, size_to_mmap, buffer, size) != 0) { 279b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to copy buffer into mem'"; 280b1994897Sopenharmony_ci } 281b1994897Sopenharmony_ci 282b1994897Sopenharmony_ci if (!tag.empty()) { 283b1994897Sopenharmony_ci if (tag == "ArkTS Code") { 284b1994897Sopenharmony_ci std::string memAddr = std::to_string(ToUintPtr(mem)); 285b1994897Sopenharmony_ci tag = tag + ":" + memAddr; 286b1994897Sopenharmony_ci } 287b1994897Sopenharmony_ci auto ret = os::mem::TagAnonymousMemory(mem, size_to_mmap, tag.c_str()); 288b1994897Sopenharmony_ci if (ret.has_value()) { 289b1994897Sopenharmony_ci PLOG(DEBUG, PANDAFILE) << "Can't tag mmap anonymous, errno: " << errno; 290b1994897Sopenharmony_ci } 291b1994897Sopenharmony_ci } 292b1994897Sopenharmony_ci 293b1994897Sopenharmony_ci os::mem::ConstBytePtr ptr(reinterpret_cast<std::byte *>(mem), size_to_mmap, os::mem::MmapDeleter); 294b1994897Sopenharmony_ci if (ptr.Get() == nullptr) { 295b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to open panda file from memory'"; 296b1994897Sopenharmony_ci return nullptr; 297b1994897Sopenharmony_ci } 298b1994897Sopenharmony_ci std::hash<void *> hash; 299b1994897Sopenharmony_ci return panda_file::File::OpenFromMemory(std::move(ptr), std::to_string(hash(mem))); 300b1994897Sopenharmony_ci} 301b1994897Sopenharmony_ci 302b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFileFromSecureMemory(uint8_t *buffer, size_t size) 303b1994897Sopenharmony_ci{ 304b1994897Sopenharmony_ci if (buffer == nullptr) { 305b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "OpenPandaFileFromSecureMemory buffer is nullptr'"; 306b1994897Sopenharmony_ci return nullptr; 307b1994897Sopenharmony_ci } 308b1994897Sopenharmony_ci 309b1994897Sopenharmony_ci if (!CheckSecureMem(reinterpret_cast<uintptr_t>(buffer), size)) { 310b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Secure memory check failed, please execute in secure memory."; 311b1994897Sopenharmony_ci return nullptr; 312b1994897Sopenharmony_ci } 313b1994897Sopenharmony_ci 314b1994897Sopenharmony_ci std::byte *mem = reinterpret_cast<std::byte *>(buffer); 315b1994897Sopenharmony_ci os::mem::ConstBytePtr ptr(mem, size, nullptr); 316b1994897Sopenharmony_ci if (ptr.Get() == nullptr) { 317b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to open panda file from secure memory'"; 318b1994897Sopenharmony_ci return nullptr; 319b1994897Sopenharmony_ci } 320b1994897Sopenharmony_ci 321b1994897Sopenharmony_ci std::hash<std::byte *> hash; 322b1994897Sopenharmony_ci return panda_file::File::OpenFromMemory(std::move(ptr), std::to_string(hash(mem))); 323b1994897Sopenharmony_ci} 324b1994897Sopenharmony_ci 325b1994897Sopenharmony_ciinline bool CheckSecureMem(uintptr_t mem, size_t size) 326b1994897Sopenharmony_ci{ 327b1994897Sopenharmony_ci static bool has_open = false; 328b1994897Sopenharmony_ci static DataProtect start = DataProtect(); 329b1994897Sopenharmony_ci static DataProtect end = DataProtect(); 330b1994897Sopenharmony_ci uintptr_t secure_mem_start; 331b1994897Sopenharmony_ci uintptr_t secure_mem_end; 332b1994897Sopenharmony_ci if (!has_open) { 333b1994897Sopenharmony_ci int fd = open(PROC_SELF_XPM_REGION_PATH, O_RDONLY); 334b1994897Sopenharmony_ci if (fd < 0) { 335b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Can not open xpm proc file, do not check secure memory anymore."; 336b1994897Sopenharmony_ci // No verification is performed when a file fails to be opened. 337b1994897Sopenharmony_ci has_open = true; 338b1994897Sopenharmony_ci return true; 339b1994897Sopenharmony_ci } 340b1994897Sopenharmony_ci char xpm_validate_region[XPM_PROC_LENGTH] = {0}; 341b1994897Sopenharmony_ci int ret = read(fd, xpm_validate_region, sizeof(xpm_validate_region)); 342b1994897Sopenharmony_ci if (ret <= 0) { 343b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Read xpm proc file failed"; 344b1994897Sopenharmony_ci close(fd); 345b1994897Sopenharmony_ci return false; 346b1994897Sopenharmony_ci } 347b1994897Sopenharmony_ci close(fd); 348b1994897Sopenharmony_ci if (sscanf_s(xpm_validate_region, "%lx-%lx", &secure_mem_start, &secure_mem_end) <= 0) { 349b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "sscanf_s xpm validate region failed"; 350b1994897Sopenharmony_ci return false; 351b1994897Sopenharmony_ci } 352b1994897Sopenharmony_ci // The check is not performed when the file is already opened. 353b1994897Sopenharmony_ci has_open = true; 354b1994897Sopenharmony_ci LOG(DEBUG, PANDAFILE) << "Successfully open xpm region."; 355b1994897Sopenharmony_ci start.Update(secure_mem_start); 356b1994897Sopenharmony_ci end.Update(secure_mem_end); 357b1994897Sopenharmony_ci } 358b1994897Sopenharmony_ci secure_mem_start = start.GetOriginPointer(); 359b1994897Sopenharmony_ci secure_mem_end = end.GetOriginPointer(); 360b1994897Sopenharmony_ci // xpm proc does not exist, the read value is 0, and the check is not performed. 361b1994897Sopenharmony_ci if (secure_mem_start == 0 && secure_mem_end == 0) { 362b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Secure memory check: xpm proc does not exist, do not check secure memory anymore."; 363b1994897Sopenharmony_ci return true; 364b1994897Sopenharmony_ci } 365b1994897Sopenharmony_ci if (mem < secure_mem_start || (size > (std::numeric_limits<uintptr_t>::max() - mem)) || 366b1994897Sopenharmony_ci (mem + size) > secure_mem_end) { 367b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Secure memory check failed, mem out of secure memory region."; 368b1994897Sopenharmony_ci return false; 369b1994897Sopenharmony_ci } 370b1994897Sopenharmony_ci return true; 371b1994897Sopenharmony_ci} 372b1994897Sopenharmony_ci 373b1994897Sopenharmony_ciclass ClassIdxIterator { 374b1994897Sopenharmony_cipublic: 375b1994897Sopenharmony_ci using value_type = const uint8_t *; 376b1994897Sopenharmony_ci using difference_type = std::ptrdiff_t; 377b1994897Sopenharmony_ci using pointer = uint32_t *; 378b1994897Sopenharmony_ci using reference = uint32_t &; 379b1994897Sopenharmony_ci using iterator_category = std::random_access_iterator_tag; 380b1994897Sopenharmony_ci 381b1994897Sopenharmony_ci ClassIdxIterator(const File &file, const Span<const uint32_t> &span, size_t idx) 382b1994897Sopenharmony_ci : file_(file), span_(span), idx_(idx) 383b1994897Sopenharmony_ci { 384b1994897Sopenharmony_ci } 385b1994897Sopenharmony_ci 386b1994897Sopenharmony_ci ClassIdxIterator(const ClassIdxIterator &other) = default; 387b1994897Sopenharmony_ci ClassIdxIterator(ClassIdxIterator &&other) = default; 388b1994897Sopenharmony_ci ~ClassIdxIterator() = default; 389b1994897Sopenharmony_ci 390b1994897Sopenharmony_ci ClassIdxIterator &operator=(const ClassIdxIterator &other) 391b1994897Sopenharmony_ci { 392b1994897Sopenharmony_ci if (&other != this) { 393b1994897Sopenharmony_ci idx_ = other.idx_; 394b1994897Sopenharmony_ci } 395b1994897Sopenharmony_ci 396b1994897Sopenharmony_ci return *this; 397b1994897Sopenharmony_ci } 398b1994897Sopenharmony_ci 399b1994897Sopenharmony_ci ClassIdxIterator &operator=(ClassIdxIterator &&other) noexcept 400b1994897Sopenharmony_ci { 401b1994897Sopenharmony_ci idx_ = other.idx_; 402b1994897Sopenharmony_ci return *this; 403b1994897Sopenharmony_ci } 404b1994897Sopenharmony_ci 405b1994897Sopenharmony_ci ClassIdxIterator &operator+=(size_t n) 406b1994897Sopenharmony_ci { 407b1994897Sopenharmony_ci idx_ += n; 408b1994897Sopenharmony_ci return *this; 409b1994897Sopenharmony_ci } 410b1994897Sopenharmony_ci 411b1994897Sopenharmony_ci ClassIdxIterator &operator-=(size_t n) 412b1994897Sopenharmony_ci { 413b1994897Sopenharmony_ci idx_ -= n; 414b1994897Sopenharmony_ci return *this; 415b1994897Sopenharmony_ci } 416b1994897Sopenharmony_ci 417b1994897Sopenharmony_ci ClassIdxIterator &operator++() 418b1994897Sopenharmony_ci { 419b1994897Sopenharmony_ci ++idx_; 420b1994897Sopenharmony_ci return *this; 421b1994897Sopenharmony_ci } 422b1994897Sopenharmony_ci 423b1994897Sopenharmony_ci ClassIdxIterator &operator--() 424b1994897Sopenharmony_ci { 425b1994897Sopenharmony_ci --idx_; 426b1994897Sopenharmony_ci return *this; 427b1994897Sopenharmony_ci } 428b1994897Sopenharmony_ci 429b1994897Sopenharmony_ci difference_type operator-(const ClassIdxIterator &other) 430b1994897Sopenharmony_ci { 431b1994897Sopenharmony_ci return idx_ - other.idx_; 432b1994897Sopenharmony_ci } 433b1994897Sopenharmony_ci 434b1994897Sopenharmony_ci value_type operator*() const 435b1994897Sopenharmony_ci { 436b1994897Sopenharmony_ci uint32_t id = span_[idx_]; 437b1994897Sopenharmony_ci return file_.GetStringData(File::EntityId(id)).data; 438b1994897Sopenharmony_ci } 439b1994897Sopenharmony_ci 440b1994897Sopenharmony_ci bool IsValid() const 441b1994897Sopenharmony_ci { 442b1994897Sopenharmony_ci return idx_ < span_.Size(); 443b1994897Sopenharmony_ci } 444b1994897Sopenharmony_ci 445b1994897Sopenharmony_ci uint32_t GetId() const 446b1994897Sopenharmony_ci { 447b1994897Sopenharmony_ci return span_[idx_]; 448b1994897Sopenharmony_ci } 449b1994897Sopenharmony_ci 450b1994897Sopenharmony_ci static ClassIdxIterator Begin(const File &file, const Span<const uint32_t> &span) 451b1994897Sopenharmony_ci { 452b1994897Sopenharmony_ci return ClassIdxIterator(file, span, 0); 453b1994897Sopenharmony_ci } 454b1994897Sopenharmony_ci 455b1994897Sopenharmony_ci static ClassIdxIterator End(const File &file, const Span<const uint32_t> &span) 456b1994897Sopenharmony_ci { 457b1994897Sopenharmony_ci return ClassIdxIterator(file, span, span.Size()); 458b1994897Sopenharmony_ci } 459b1994897Sopenharmony_ci 460b1994897Sopenharmony_ciprivate: 461b1994897Sopenharmony_ci const File &file_; 462b1994897Sopenharmony_ci const Span<const uint32_t> &span_; 463b1994897Sopenharmony_ci size_t idx_; 464b1994897Sopenharmony_ci}; 465b1994897Sopenharmony_ci 466b1994897Sopenharmony_ciFile::File(std::string filename, os::mem::ConstBytePtr &&base) 467b1994897Sopenharmony_ci : base_(std::forward<os::mem::ConstBytePtr>(base)), 468b1994897Sopenharmony_ci FILENAME(std::move(filename)), 469b1994897Sopenharmony_ci FILENAME_HASH(CalcFilenameHash(FILENAME)), 470b1994897Sopenharmony_ci#ifdef ENABLE_FULL_FILE_FIELDS 471b1994897Sopenharmony_ci FULL_FILENAME(os::GetAbsolutePath(FILENAME)), 472b1994897Sopenharmony_ci panda_cache_(std::make_unique<PandaCache>()), 473b1994897Sopenharmony_ci#endif 474b1994897Sopenharmony_ci UNIQ_ID(merge_hashes(FILENAME_HASH, GetHash32(reinterpret_cast<const uint8_t *>(GetHeader()), sizeof(Header)))) 475b1994897Sopenharmony_ci{ 476b1994897Sopenharmony_ci} 477b1994897Sopenharmony_ci 478b1994897Sopenharmony_ciFile::~File() 479b1994897Sopenharmony_ci{ 480b1994897Sopenharmony_ci AnonMemSet::GetInstance().Remove(FILENAME); 481b1994897Sopenharmony_ci} 482b1994897Sopenharmony_ci 483b1994897Sopenharmony_ciinline std::string VersionToString(const std::array<uint8_t, File::VERSION_SIZE> &array) 484b1994897Sopenharmony_ci{ 485b1994897Sopenharmony_ci std::stringstream ss; 486b1994897Sopenharmony_ci 487b1994897Sopenharmony_ci for (size_t i = 0; i < File::VERSION_SIZE - 1; ++i) { 488b1994897Sopenharmony_ci ss << static_cast<int>(array[i]); 489b1994897Sopenharmony_ci ss << "."; 490b1994897Sopenharmony_ci } 491b1994897Sopenharmony_ci ss << static_cast<int>(array[File::VERSION_SIZE - 1]); 492b1994897Sopenharmony_ci 493b1994897Sopenharmony_ci return ss.str(); 494b1994897Sopenharmony_ci} 495b1994897Sopenharmony_ci 496b1994897Sopenharmony_ci// We can't use default std::array's comparision operators and need to implement 497b1994897Sopenharmony_ci// own ones due to the bug in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189 498b1994897Sopenharmony_ciinline int CompareVersions(const std::array<uint8_t, File::VERSION_SIZE> &lhs, 499b1994897Sopenharmony_ci const std::array<uint8_t, File::VERSION_SIZE> &rhs) 500b1994897Sopenharmony_ci{ 501b1994897Sopenharmony_ci for (size_t i = 0; i < File::VERSION_SIZE; i++) { 502b1994897Sopenharmony_ci if (lhs[i] == rhs[i]) { 503b1994897Sopenharmony_ci continue; 504b1994897Sopenharmony_ci } 505b1994897Sopenharmony_ci return lhs[i] - rhs[i]; 506b1994897Sopenharmony_ci } 507b1994897Sopenharmony_ci return 0; 508b1994897Sopenharmony_ci} 509b1994897Sopenharmony_ci 510b1994897Sopenharmony_ciinline bool operator<(const std::array<uint8_t, File::VERSION_SIZE> &lhs, 511b1994897Sopenharmony_ci const std::array<uint8_t, File::VERSION_SIZE> &rhs) 512b1994897Sopenharmony_ci{ 513b1994897Sopenharmony_ci return CompareVersions(lhs, rhs) < 0; 514b1994897Sopenharmony_ci} 515b1994897Sopenharmony_ci 516b1994897Sopenharmony_ciinline bool operator>(const std::array<uint8_t, File::VERSION_SIZE> &lhs, 517b1994897Sopenharmony_ci const std::array<uint8_t, File::VERSION_SIZE> &rhs) 518b1994897Sopenharmony_ci{ 519b1994897Sopenharmony_ci return CompareVersions(lhs, rhs) > 0; 520b1994897Sopenharmony_ci} 521b1994897Sopenharmony_ci 522b1994897Sopenharmony_ci/* static */ 523b1994897Sopenharmony_cistd::unique_ptr<const File> File::Open(std::string_view filename, OpenMode open_mode) 524b1994897Sopenharmony_ci{ 525b1994897Sopenharmony_ci trace::ScopedTrace scoped_trace("Open panda file " + std::string(filename)); 526b1994897Sopenharmony_ci os::file::Mode mode = GetMode(open_mode); 527b1994897Sopenharmony_ci os::file::File file = os::file::Open(filename, mode); 528b1994897Sopenharmony_ci if (!file.IsValid()) { 529b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to open panda file '" << filename << "'"; 530b1994897Sopenharmony_ci return nullptr; 531b1994897Sopenharmony_ci } 532b1994897Sopenharmony_ci 533b1994897Sopenharmony_ci os::file::FileHolder fh_holder(file); 534b1994897Sopenharmony_ci 535b1994897Sopenharmony_ci auto res = file.GetFileSize(); 536b1994897Sopenharmony_ci if (!res) { 537b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to get size of panda file '" << filename << "'"; 538b1994897Sopenharmony_ci return nullptr; 539b1994897Sopenharmony_ci } 540b1994897Sopenharmony_ci 541b1994897Sopenharmony_ci size_t size = res.Value(); 542b1994897Sopenharmony_ci if (size < sizeof(File::Header)) { 543b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file '" << filename << "' - missing or incomplete header" << 544b1994897Sopenharmony_ci ". Abc file is corrupted"; 545b1994897Sopenharmony_ci return nullptr; 546b1994897Sopenharmony_ci } 547b1994897Sopenharmony_ci 548b1994897Sopenharmony_ci os::mem::ConstBytePtr ptr = os::mem::MapFile(file, GetProt(open_mode), os::mem::MMAP_FLAG_PRIVATE, size).ToConst(); 549b1994897Sopenharmony_ci if (ptr.Get() == nullptr) { 550b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to map panda file '" << filename << "'"; 551b1994897Sopenharmony_ci return nullptr; 552b1994897Sopenharmony_ci } 553b1994897Sopenharmony_ci 554b1994897Sopenharmony_ci if (!CheckHeader(ptr, filename)) { 555b1994897Sopenharmony_ci return nullptr; 556b1994897Sopenharmony_ci } 557b1994897Sopenharmony_ci 558b1994897Sopenharmony_ci return std::unique_ptr<File>(new File(filename.data(), std::move(ptr))); 559b1994897Sopenharmony_ci} 560b1994897Sopenharmony_ci 561b1994897Sopenharmony_cistd::unique_ptr<const File> File::OpenUncompressedArchive(int fd, const std::string_view &filename, size_t size, 562b1994897Sopenharmony_ci uint32_t offset, OpenMode open_mode) 563b1994897Sopenharmony_ci{ 564b1994897Sopenharmony_ci trace::ScopedTrace scoped_trace("Open panda file " + std::string(filename)); 565b1994897Sopenharmony_ci auto file = os::file::File(fd); 566b1994897Sopenharmony_ci if (!file.IsValid()) { 567b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "OpenUncompressedArchive: Failed to open panda file '" << filename << "'"; 568b1994897Sopenharmony_ci return nullptr; 569b1994897Sopenharmony_ci } 570b1994897Sopenharmony_ci 571b1994897Sopenharmony_ci if (size < sizeof(File::Header)) { 572b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file size '" << filename << "'" << ". Abc file is corrupted"; 573b1994897Sopenharmony_ci return nullptr; 574b1994897Sopenharmony_ci } 575b1994897Sopenharmony_ci LOG(DEBUG, PANDAFILE) << " size=" << size << " offset=" << offset << " " << filename; 576b1994897Sopenharmony_ci 577b1994897Sopenharmony_ci os::mem::ConstBytePtr ptr = 578b1994897Sopenharmony_ci os::mem::MapFile(file, GetProt(open_mode), os::mem::MMAP_FLAG_PRIVATE, size, offset).ToConst(); 579b1994897Sopenharmony_ci if (ptr.Get() == nullptr) { 580b1994897Sopenharmony_ci PLOG(ERROR, PANDAFILE) << "Failed to map panda file '" << filename << "'"; 581b1994897Sopenharmony_ci return nullptr; 582b1994897Sopenharmony_ci } 583b1994897Sopenharmony_ci if (!CheckHeader(ptr, filename)) { 584b1994897Sopenharmony_ci return nullptr; 585b1994897Sopenharmony_ci } 586b1994897Sopenharmony_ci 587b1994897Sopenharmony_ci return std::unique_ptr<File>(new File(filename.data(), std::move(ptr))); 588b1994897Sopenharmony_ci} 589b1994897Sopenharmony_ci 590b1994897Sopenharmony_citemplate <typename T = uint32_t> 591b1994897Sopenharmony_cibool CheckHeaderElementOffset(size_t offset, size_t number, size_t file_size) 592b1994897Sopenharmony_ci{ 593b1994897Sopenharmony_ci auto number_size = number * sizeof(T); 594b1994897Sopenharmony_ci if (offset > file_size || number_size > file_size || offset > file_size - number_size) { 595b1994897Sopenharmony_ci return false; 596b1994897Sopenharmony_ci } 597b1994897Sopenharmony_ci return true; 598b1994897Sopenharmony_ci} 599b1994897Sopenharmony_ci 600b1994897Sopenharmony_cibool CheckHeader(const os::mem::ConstBytePtr &ptr, const std::string_view &filename) 601b1994897Sopenharmony_ci{ 602b1994897Sopenharmony_ci if (ptr.Get() == nullptr || ptr.GetSize() < sizeof(File::Header)) { 603b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file '" << filename << "'" << ". Abc file is corrupted"; 604b1994897Sopenharmony_ci return false; 605b1994897Sopenharmony_ci } 606b1994897Sopenharmony_ci auto header = reinterpret_cast<const File::Header *>(reinterpret_cast<uintptr_t>(ptr.Get())); 607b1994897Sopenharmony_ci if (header->magic != File::MAGIC) { 608b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid magic number" << ". Abc file is corrupted"; 609b1994897Sopenharmony_ci return false; 610b1994897Sopenharmony_ci } 611b1994897Sopenharmony_ci 612b1994897Sopenharmony_ci CheckFileVersion(header->version, filename); 613b1994897Sopenharmony_ci 614b1994897Sopenharmony_ci if (header->file_size < sizeof(File::Header) || header->file_size > ptr.GetSize()) { 615b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file size " << header->file_size << ". Abc file is corrupted"; 616b1994897Sopenharmony_ci return false; 617b1994897Sopenharmony_ci } 618b1994897Sopenharmony_ci 619b1994897Sopenharmony_ci if (!CheckHeaderElementOffset<uint8_t>(header->foreign_off, header->foreign_size, header->file_size)) { 620b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file foreign_off " << header->foreign_off << 621b1994897Sopenharmony_ci " or foreign_size " << header->foreign_size << ". Abc file is corrupted"; 622b1994897Sopenharmony_ci return false; 623b1994897Sopenharmony_ci } 624b1994897Sopenharmony_ci 625b1994897Sopenharmony_ci if (!CheckHeaderElementOffset(header->class_idx_off, header->num_classes, header->file_size)) { 626b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file class_idx_off " << header->class_idx_off << 627b1994897Sopenharmony_ci " or num_classes " << header->num_classes << ". Abc file is corrupted"; 628b1994897Sopenharmony_ci return false; 629b1994897Sopenharmony_ci } 630b1994897Sopenharmony_ci 631b1994897Sopenharmony_ci if (!CheckHeaderElementOffset(header->lnp_idx_off, header->num_lnps, header->file_size)) { 632b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file lnp_idx_off " << header->lnp_idx_off << 633b1994897Sopenharmony_ci " or num_lnps " << header->num_lnps << ". Abc file is corrupted"; 634b1994897Sopenharmony_ci return false; 635b1994897Sopenharmony_ci } 636b1994897Sopenharmony_ci 637b1994897Sopenharmony_ci if (ContainsLiteralArrayInHeader(header->version)) { 638b1994897Sopenharmony_ci if (!CheckHeaderElementOffset(header->literalarray_idx_off, header->num_literalarrays, header->file_size)) { 639b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file literalarray_idx_off " << header->literalarray_idx_off << 640b1994897Sopenharmony_ci " or num_literalarrays " << header->num_literalarrays << 641b1994897Sopenharmony_ci ". Abc file is corrupted"; 642b1994897Sopenharmony_ci return false; 643b1994897Sopenharmony_ci } 644b1994897Sopenharmony_ci } else { 645b1994897Sopenharmony_ci if (header->literalarray_idx_off != INVALID_INDEX || header->num_literalarrays != INVALID_OFFSET) { 646b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file literalarray_idx_off " << header->literalarray_idx_off << 647b1994897Sopenharmony_ci " or num_literalarrays " << header->num_literalarrays << 648b1994897Sopenharmony_ci ", The literalarray_idx_off and num_literalarrays should be reserved." << 649b1994897Sopenharmony_ci " Abc file is corrupted"; 650b1994897Sopenharmony_ci return false; 651b1994897Sopenharmony_ci } 652b1994897Sopenharmony_ci } 653b1994897Sopenharmony_ci 654b1994897Sopenharmony_ci if (!CheckHeaderElementOffset<File::IndexHeader>(header->index_section_off, header->num_indexes, 655b1994897Sopenharmony_ci header->file_size)) { 656b1994897Sopenharmony_ci LOG(ERROR, PANDAFILE) << "Invalid panda file index_section_off " << header->index_section_off << 657b1994897Sopenharmony_ci " or num_indexes " << header->num_indexes << ". Abc file is corrupted"; 658b1994897Sopenharmony_ci return false; 659b1994897Sopenharmony_ci } 660b1994897Sopenharmony_ci 661b1994897Sopenharmony_ci return true; 662b1994897Sopenharmony_ci} 663b1994897Sopenharmony_ci 664b1994897Sopenharmony_civoid CheckFileVersion(const std::array<uint8_t, File::VERSION_SIZE> &file_version, const std::string_view &filename) 665b1994897Sopenharmony_ci{ 666b1994897Sopenharmony_ci#ifdef ERROR_AS_FATAL 667b1994897Sopenharmony_ci#define LOG_LEVEL FATAL 668b1994897Sopenharmony_ci#else 669b1994897Sopenharmony_ci#define LOG_LEVEL ERROR 670b1994897Sopenharmony_ci#endif 671b1994897Sopenharmony_ci if (file_version == version) { 672b1994897Sopenharmony_ci return; 673b1994897Sopenharmony_ci } 674b1994897Sopenharmony_ci if (file_version < minVersion) { 675b1994897Sopenharmony_ci LOG(LOG_LEVEL, PANDAFILE) << "Unable to open file '" << filename << "' with abc file version " 676b1994897Sopenharmony_ci << VersionToString(file_version) 677b1994897Sopenharmony_ci << ". Minimum supported abc file version on the current system image is " << VersionToString(minVersion) 678b1994897Sopenharmony_ci << ". Please upgrade the sdk tools to generate supported version of abc files " 679b1994897Sopenharmony_ci << "or execute the abc file on former version of system image"; 680b1994897Sopenharmony_ci } else if (file_version > version) { 681b1994897Sopenharmony_ci LOG(LOG_LEVEL, PANDAFILE) << "Unable to open file '" << filename << "' with abc file version " 682b1994897Sopenharmony_ci << VersionToString(file_version) 683b1994897Sopenharmony_ci << ". Maximum supported abc file version on the current system image is " << VersionToString(version) 684b1994897Sopenharmony_ci << ". Please upgrade the system image or use former version of SDK tools to generate abc files"; 685b1994897Sopenharmony_ci } else if (incompatibleVersion.count(file_version) != 0) { 686b1994897Sopenharmony_ci LOG(LOG_LEVEL, PANDAFILE) << "Unable to open file '" << filename << "' with abc file version " 687b1994897Sopenharmony_ci << VersionToString(file_version) << ". Current system image version is " 688b1994897Sopenharmony_ci << VersionToString(version) << ", while abc file version is " << VersionToString(file_version) 689b1994897Sopenharmony_ci << ". The version "<< VersionToString(file_version) 690b1994897Sopenharmony_ci << " is not a compatible version, can't run on system image of version " << VersionToString(version) 691b1994897Sopenharmony_ci << ". Please use sdk tools and system image in pairs " 692b1994897Sopenharmony_ci << "and make the version of sdk tools and system image consistent"; 693b1994897Sopenharmony_ci } 694b1994897Sopenharmony_ci#undef LOG_LEVEL 695b1994897Sopenharmony_ci} 696b1994897Sopenharmony_ci/* static */ 697b1994897Sopenharmony_cistd::unique_ptr<const File> File::OpenFromMemory(os::mem::ConstBytePtr &&ptr) 698b1994897Sopenharmony_ci{ 699b1994897Sopenharmony_ci if (!CheckHeader(ptr, std::string_view())) { 700b1994897Sopenharmony_ci return nullptr; 701b1994897Sopenharmony_ci } 702b1994897Sopenharmony_ci 703b1994897Sopenharmony_ci return std::unique_ptr<File>(new File("", std::forward<os::mem::ConstBytePtr>(ptr))); 704b1994897Sopenharmony_ci} 705b1994897Sopenharmony_ci 706b1994897Sopenharmony_ci/* static */ 707b1994897Sopenharmony_cistd::unique_ptr<const File> File::OpenFromMemory(os::mem::ConstBytePtr &&ptr, std::string_view filename) 708b1994897Sopenharmony_ci{ 709b1994897Sopenharmony_ci trace::ScopedTrace scoped_trace("Open panda file from RAM " + std::string(filename)); 710b1994897Sopenharmony_ci 711b1994897Sopenharmony_ci if (!CheckHeader(ptr, filename)) { 712b1994897Sopenharmony_ci return nullptr; 713b1994897Sopenharmony_ci } 714b1994897Sopenharmony_ci 715b1994897Sopenharmony_ci return std::unique_ptr<File>(new File(filename.data(), std::forward<os::mem::ConstBytePtr>(ptr))); 716b1994897Sopenharmony_ci} 717b1994897Sopenharmony_ci 718b1994897Sopenharmony_ciFile::EntityId File::GetClassId(const uint8_t *mutf8_name) const 719b1994897Sopenharmony_ci{ 720b1994897Sopenharmony_ci auto class_hash_table = GetClassHashTable(); 721b1994897Sopenharmony_ci if (!class_hash_table.empty()) { 722b1994897Sopenharmony_ci return GetClassIdFromClassHashTable(mutf8_name); 723b1994897Sopenharmony_ci } 724b1994897Sopenharmony_ci 725b1994897Sopenharmony_ci auto class_idx = GetClasses(); 726b1994897Sopenharmony_ci 727b1994897Sopenharmony_ci auto it = std::lower_bound(ClassIdxIterator::Begin(*this, class_idx), ClassIdxIterator::End(*this, class_idx), 728b1994897Sopenharmony_ci mutf8_name, utf::Mutf8Less()); 729b1994897Sopenharmony_ci if (!it.IsValid()) { 730b1994897Sopenharmony_ci return EntityId(); 731b1994897Sopenharmony_ci } 732b1994897Sopenharmony_ci 733b1994897Sopenharmony_ci if (utf::CompareMUtf8ToMUtf8(mutf8_name, *it) == 0) { 734b1994897Sopenharmony_ci return EntityId(it.GetId()); 735b1994897Sopenharmony_ci } 736b1994897Sopenharmony_ci 737b1994897Sopenharmony_ci return EntityId(); 738b1994897Sopenharmony_ci} 739b1994897Sopenharmony_ci 740b1994897Sopenharmony_ciuint32_t File::CalcFilenameHash(const std::string &filename) 741b1994897Sopenharmony_ci{ 742b1994897Sopenharmony_ci return GetHash32String(reinterpret_cast<const uint8_t *>(filename.c_str())); 743b1994897Sopenharmony_ci} 744b1994897Sopenharmony_ci 745b1994897Sopenharmony_ciFile::EntityId File::GetLiteralArraysId() const 746b1994897Sopenharmony_ci{ 747b1994897Sopenharmony_ci const Header *header = GetHeader(); 748b1994897Sopenharmony_ci return EntityId(header->literalarray_idx_off); 749b1994897Sopenharmony_ci} 750b1994897Sopenharmony_ci 751b1994897Sopenharmony_ciFile::EntityId File::GetClassIdFromClassHashTable(const uint8_t *mutf8_name) const 752b1994897Sopenharmony_ci{ 753b1994897Sopenharmony_ci auto class_hash_table = GetClassHashTable(); 754b1994897Sopenharmony_ci auto hash = GetHash32String(mutf8_name); 755b1994897Sopenharmony_ci auto pos = hash & (class_hash_table.size() - 1); 756b1994897Sopenharmony_ci auto entity_pair = &class_hash_table[pos]; 757b1994897Sopenharmony_ci 758b1994897Sopenharmony_ci if (entity_pair->descriptor_hash % class_hash_table.size() != pos) { 759b1994897Sopenharmony_ci return File::EntityId(); 760b1994897Sopenharmony_ci } 761b1994897Sopenharmony_ci 762b1994897Sopenharmony_ci while (true) { 763b1994897Sopenharmony_ci if (hash == entity_pair->descriptor_hash) { 764b1994897Sopenharmony_ci auto entity_id = File::EntityId(entity_pair->entity_id_offset); 765b1994897Sopenharmony_ci auto descriptor = GetStringData(entity_id).data; 766b1994897Sopenharmony_ci if (entity_id.IsValid() && utf::CompareMUtf8ToMUtf8(descriptor, mutf8_name) == 0) { 767b1994897Sopenharmony_ci return entity_id; 768b1994897Sopenharmony_ci } 769b1994897Sopenharmony_ci } 770b1994897Sopenharmony_ci if (entity_pair->next_pos == 0) { 771b1994897Sopenharmony_ci break; 772b1994897Sopenharmony_ci } 773b1994897Sopenharmony_ci entity_pair = &class_hash_table[entity_pair->next_pos - 1]; 774b1994897Sopenharmony_ci } 775b1994897Sopenharmony_ci 776b1994897Sopenharmony_ci return File::EntityId(); 777b1994897Sopenharmony_ci} 778b1994897Sopenharmony_ci 779b1994897Sopenharmony_ci 780b1994897Sopenharmony_cibool ContainsLiteralArrayInHeader(const std::array<uint8_t, File::VERSION_SIZE> &version) 781b1994897Sopenharmony_ci{ 782b1994897Sopenharmony_ci return panda::panda_file::IsVersionLessOrEqual(version, LAST_CONTAINS_LITERAL_IN_HEADER_VERSION); 783b1994897Sopenharmony_ci} 784b1994897Sopenharmony_ci 785b1994897Sopenharmony_cibool File::ValidateChecksum(uint32_t *cal_checksum_out) const 786b1994897Sopenharmony_ci{ 787b1994897Sopenharmony_ci constexpr uint32_t CHECKSUM_SIZE = 4U; 788b1994897Sopenharmony_ci // The checksum calculation does not include magic or checksum, so the offset needs to be added 789b1994897Sopenharmony_ci constexpr uint32_t FILE_CONTENT_OFFSET = File::MAGIC_SIZE + CHECKSUM_SIZE; 790b1994897Sopenharmony_ci uint32_t file_size = GetHeader()->file_size; 791b1994897Sopenharmony_ci uint32_t cal_checksum = adler32(1, GetBase() + FILE_CONTENT_OFFSET, file_size - FILE_CONTENT_OFFSET); 792b1994897Sopenharmony_ci 793b1994897Sopenharmony_ci if (cal_checksum_out != nullptr) { 794b1994897Sopenharmony_ci *cal_checksum_out = cal_checksum; 795b1994897Sopenharmony_ci } 796b1994897Sopenharmony_ci 797b1994897Sopenharmony_ci return GetHeader()->checksum == cal_checksum; 798b1994897Sopenharmony_ci} 799b1994897Sopenharmony_ci 800b1994897Sopenharmony_civoid File::ThrowIfWithCheck(bool cond, const std::string_view& msg, const std::string_view& tag) const 801b1994897Sopenharmony_ci{ 802b1994897Sopenharmony_ci if (UNLIKELY(cond)) { 803b1994897Sopenharmony_ci uint32_t cal_checksum = 0; 804b1994897Sopenharmony_ci bool is_checksum_match = ValidateChecksum(&cal_checksum); 805b1994897Sopenharmony_ci if (!is_checksum_match) { 806b1994897Sopenharmony_ci LOG(FATAL, PANDAFILE) << msg << ", checksum mismatch. The abc file has been corrupted. " 807b1994897Sopenharmony_ci << "Expected checksum: 0x" << std::hex << GetHeader()->checksum 808b1994897Sopenharmony_ci << ", Actual checksum: 0x" << std::hex << cal_checksum; 809b1994897Sopenharmony_ci } 810b1994897Sopenharmony_ci 811b1994897Sopenharmony_ci if (!tag.empty()) { 812b1994897Sopenharmony_ci LOG(FATAL, PANDAFILE) << msg << ", from method: " << tag; 813b1994897Sopenharmony_ci } else { 814b1994897Sopenharmony_ci LOG(FATAL, PANDAFILE) << msg; 815b1994897Sopenharmony_ci } 816b1994897Sopenharmony_ci } 817b1994897Sopenharmony_ci} 818b1994897Sopenharmony_ci 819b1994897Sopenharmony_ci} // namespace panda::panda_file 820