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#ifndef LIBPANDAFILE_FILE_H
17b1994897Sopenharmony_ci#define LIBPANDAFILE_FILE_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <array>
20b1994897Sopenharmony_ci#include <cstdint>
21b1994897Sopenharmony_ci#include <fcntl.h>
22b1994897Sopenharmony_ci#include <iostream>
23b1994897Sopenharmony_ci#include <memory>
24b1994897Sopenharmony_ci#include <string>
25b1994897Sopenharmony_ci#include <string_view>
26b1994897Sopenharmony_ci
27b1994897Sopenharmony_ci#include "helpers.h"
28b1994897Sopenharmony_ci#include "os/mem.h"
29b1994897Sopenharmony_ci#include "os/filesystem.h"
30b1994897Sopenharmony_ci#include "utils/span.h"
31b1994897Sopenharmony_ci#include "utils/utf.h"
32b1994897Sopenharmony_ci#include "utils/logger.h"
33b1994897Sopenharmony_ci
34b1994897Sopenharmony_cinamespace panda {
35b1994897Sopenharmony_cistruct EntryFileStat;
36b1994897Sopenharmony_ci}  // namespace panda
37b1994897Sopenharmony_ci
38b1994897Sopenharmony_cinamespace panda::panda_file {
39b1994897Sopenharmony_ci
40b1994897Sopenharmony_ciclass PandaCache;
41b1994897Sopenharmony_ci
42b1994897Sopenharmony_ci#define XPM_PROC_LENGTH 50
43b1994897Sopenharmony_ci#define PROC_SELF_XPM_REGION_PATH "/proc/self/xpm_region"
44b1994897Sopenharmony_ci/*
45b1994897Sopenharmony_ci * EntityPairHeader Describes pair for hash value of class's descriptor and its entity id offset,
46b1994897Sopenharmony_ci * used to quickly find class by its descriptor.
47b1994897Sopenharmony_ci */
48b1994897Sopenharmony_cistruct EntityPairHeader {
49b1994897Sopenharmony_ci    uint32_t descriptor_hash;
50b1994897Sopenharmony_ci    uint32_t entity_id_offset;
51b1994897Sopenharmony_ci    uint32_t next_pos;
52b1994897Sopenharmony_ci};
53b1994897Sopenharmony_ci
54b1994897Sopenharmony_ciclass File {
55b1994897Sopenharmony_cipublic:
56b1994897Sopenharmony_ci    using Index = uint16_t;
57b1994897Sopenharmony_ci    using Index32 = uint32_t;
58b1994897Sopenharmony_ci
59b1994897Sopenharmony_ci    static constexpr size_t MAGIC_SIZE = 8;
60b1994897Sopenharmony_ci    static constexpr size_t VERSION_SIZE = 4;
61b1994897Sopenharmony_ci    static const std::array<uint8_t, MAGIC_SIZE> MAGIC;
62b1994897Sopenharmony_ci
63b1994897Sopenharmony_ci    struct Header {
64b1994897Sopenharmony_ci        std::array<uint8_t, MAGIC_SIZE> magic;
65b1994897Sopenharmony_ci        uint32_t checksum;
66b1994897Sopenharmony_ci        std::array<uint8_t, VERSION_SIZE> version;
67b1994897Sopenharmony_ci        uint32_t file_size;
68b1994897Sopenharmony_ci        uint32_t foreign_off;
69b1994897Sopenharmony_ci        uint32_t foreign_size;
70b1994897Sopenharmony_ci        uint32_t num_classes;
71b1994897Sopenharmony_ci        uint32_t class_idx_off;
72b1994897Sopenharmony_ci        uint32_t num_lnps;
73b1994897Sopenharmony_ci        uint32_t lnp_idx_off;
74b1994897Sopenharmony_ci        uint32_t num_literalarrays;
75b1994897Sopenharmony_ci        uint32_t literalarray_idx_off;
76b1994897Sopenharmony_ci        uint32_t num_indexes;
77b1994897Sopenharmony_ci        uint32_t index_section_off;
78b1994897Sopenharmony_ci    };
79b1994897Sopenharmony_ci
80b1994897Sopenharmony_ci    struct IndexHeader {
81b1994897Sopenharmony_ci        uint32_t start;
82b1994897Sopenharmony_ci        uint32_t end;
83b1994897Sopenharmony_ci        uint32_t class_idx_size;
84b1994897Sopenharmony_ci        uint32_t class_idx_off;
85b1994897Sopenharmony_ci        uint32_t method_idx_size;
86b1994897Sopenharmony_ci        uint32_t method_idx_off;
87b1994897Sopenharmony_ci        uint32_t field_idx_size;
88b1994897Sopenharmony_ci        uint32_t field_idx_off;
89b1994897Sopenharmony_ci        uint32_t proto_idx_size;
90b1994897Sopenharmony_ci        uint32_t proto_idx_off;
91b1994897Sopenharmony_ci    };
92b1994897Sopenharmony_ci
93b1994897Sopenharmony_ci    struct StringData {
94b1994897Sopenharmony_ci        StringData(uint32_t len, const uint8_t *d) : utf16_length(len), is_ascii(false), data(d) {}
95b1994897Sopenharmony_ci        StringData() = default;
96b1994897Sopenharmony_ci        uint32_t utf16_length;  // NOLINT(misc-non-private-member-variables-in-classes)
97b1994897Sopenharmony_ci        bool is_ascii;          // NOLINT(misc-non-private-member-variables-in-classes)
98b1994897Sopenharmony_ci        const uint8_t *data;    // NOLINT(misc-non-private-member-variables-in-classes)
99b1994897Sopenharmony_ci    };
100b1994897Sopenharmony_ci
101b1994897Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
102b1994897Sopenharmony_ci    class EntityId {
103b1994897Sopenharmony_ci    public:
104b1994897Sopenharmony_ci        explicit constexpr EntityId(uint32_t offset) : offset_(offset) {}
105b1994897Sopenharmony_ci
106b1994897Sopenharmony_ci        EntityId() = default;
107b1994897Sopenharmony_ci
108b1994897Sopenharmony_ci        ~EntityId() = default;
109b1994897Sopenharmony_ci
110b1994897Sopenharmony_ci        bool IsValid() const
111b1994897Sopenharmony_ci        {
112b1994897Sopenharmony_ci            return offset_ > sizeof(Header);
113b1994897Sopenharmony_ci        }
114b1994897Sopenharmony_ci
115b1994897Sopenharmony_ci        uint32_t GetOffset() const
116b1994897Sopenharmony_ci        {
117b1994897Sopenharmony_ci            return offset_;
118b1994897Sopenharmony_ci        }
119b1994897Sopenharmony_ci
120b1994897Sopenharmony_ci        static constexpr size_t GetSize()
121b1994897Sopenharmony_ci        {
122b1994897Sopenharmony_ci            return sizeof(uint32_t);
123b1994897Sopenharmony_ci        }
124b1994897Sopenharmony_ci
125b1994897Sopenharmony_ci        friend bool operator<(const EntityId &l, const EntityId &r)
126b1994897Sopenharmony_ci        {
127b1994897Sopenharmony_ci            return l.offset_ < r.offset_;
128b1994897Sopenharmony_ci        }
129b1994897Sopenharmony_ci
130b1994897Sopenharmony_ci        friend bool operator==(const EntityId &l, const EntityId &r)
131b1994897Sopenharmony_ci        {
132b1994897Sopenharmony_ci            return l.offset_ == r.offset_;
133b1994897Sopenharmony_ci        }
134b1994897Sopenharmony_ci
135b1994897Sopenharmony_ci        friend std::ostream &operator<<(std::ostream &stream, const EntityId &id)
136b1994897Sopenharmony_ci        {
137b1994897Sopenharmony_ci            return stream << id.offset_;
138b1994897Sopenharmony_ci        }
139b1994897Sopenharmony_ci
140b1994897Sopenharmony_ci    private:
141b1994897Sopenharmony_ci        uint32_t offset_ {0};
142b1994897Sopenharmony_ci    };
143b1994897Sopenharmony_ci
144b1994897Sopenharmony_ci    enum OpenMode { READ_ONLY, READ_WRITE, WRITE_ONLY };
145b1994897Sopenharmony_ci
146b1994897Sopenharmony_ci    StringData GetStringData(EntityId id) const;
147b1994897Sopenharmony_ci    EntityId GetLiteralArraysId() const;
148b1994897Sopenharmony_ci
149b1994897Sopenharmony_ci    EntityId GetClassId(const uint8_t *mutf8_name) const;
150b1994897Sopenharmony_ci
151b1994897Sopenharmony_ci    EntityId GetClassIdFromClassHashTable(const uint8_t *mutf8_name) const;
152b1994897Sopenharmony_ci
153b1994897Sopenharmony_ci    const Header *GetHeader() const
154b1994897Sopenharmony_ci    {
155b1994897Sopenharmony_ci        return reinterpret_cast<const Header *>(GetBase());
156b1994897Sopenharmony_ci    }
157b1994897Sopenharmony_ci
158b1994897Sopenharmony_ci    const uint8_t *GetBase() const
159b1994897Sopenharmony_ci    {
160b1994897Sopenharmony_ci        return reinterpret_cast<const uint8_t *>(base_.Get());
161b1994897Sopenharmony_ci    }
162b1994897Sopenharmony_ci
163b1994897Sopenharmony_ci    const os::mem::ConstBytePtr &GetPtr() const
164b1994897Sopenharmony_ci    {
165b1994897Sopenharmony_ci        return base_;
166b1994897Sopenharmony_ci    }
167b1994897Sopenharmony_ci
168b1994897Sopenharmony_ci    bool IsExternal(EntityId id) const
169b1994897Sopenharmony_ci    {
170b1994897Sopenharmony_ci        const Header *header = GetHeader();
171b1994897Sopenharmony_ci        uint32_t foreign_begin = header->foreign_off;
172b1994897Sopenharmony_ci        uint32_t foreign_end = foreign_begin + header->foreign_size;
173b1994897Sopenharmony_ci        return id.GetOffset() >= foreign_begin && id.GetOffset() < foreign_end;
174b1994897Sopenharmony_ci    }
175b1994897Sopenharmony_ci
176b1994897Sopenharmony_ci    EntityId GetIdFromPointer(const uint8_t *ptr) const
177b1994897Sopenharmony_ci    {
178b1994897Sopenharmony_ci        return EntityId(ptr - GetBase());
179b1994897Sopenharmony_ci    }
180b1994897Sopenharmony_ci
181b1994897Sopenharmony_ci    Span<const uint8_t> GetSpanFromId(EntityId id) const
182b1994897Sopenharmony_ci    {
183b1994897Sopenharmony_ci        const Header *header = GetHeader();
184b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
185b1994897Sopenharmony_ci        ThrowIfWithCheck(!id.IsValid() || id.GetOffset() >= file.size(), File::INVALID_FILE_OFFSET,
186b1994897Sopenharmony_ci                         File::GET_SPAN_FROM_ID);
187b1994897Sopenharmony_ci        return file.Last(file.size() - id.GetOffset());
188b1994897Sopenharmony_ci    }
189b1994897Sopenharmony_ci
190b1994897Sopenharmony_ci    Span<const uint32_t> GetClasses() const
191b1994897Sopenharmony_ci    {
192b1994897Sopenharmony_ci        const Header *header = GetHeader();
193b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
194b1994897Sopenharmony_ci        Span class_idx_data = file.SubSpan(header->class_idx_off, header->num_classes * sizeof(uint32_t));
195b1994897Sopenharmony_ci        return Span(reinterpret_cast<const uint32_t *>(class_idx_data.data()), header->num_classes);
196b1994897Sopenharmony_ci    }
197b1994897Sopenharmony_ci
198b1994897Sopenharmony_ci    Span<const uint32_t> GetLiteralArrays() const
199b1994897Sopenharmony_ci    {
200b1994897Sopenharmony_ci        const Header *header = GetHeader();
201b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
202b1994897Sopenharmony_ci        Span litarr_idx_data = file.SubSpan(header->literalarray_idx_off, header->num_literalarrays * sizeof(uint32_t));
203b1994897Sopenharmony_ci        return Span(reinterpret_cast<const uint32_t *>(litarr_idx_data.data()), header->num_literalarrays);
204b1994897Sopenharmony_ci    }
205b1994897Sopenharmony_ci
206b1994897Sopenharmony_ci    Span<const IndexHeader> GetIndexHeaders() const
207b1994897Sopenharmony_ci    {
208b1994897Sopenharmony_ci        const Header *header = GetHeader();
209b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
210b1994897Sopenharmony_ci        auto sp = file.SubSpan(header->index_section_off, header->num_indexes * sizeof(IndexHeader));
211b1994897Sopenharmony_ci        return Span(reinterpret_cast<const IndexHeader *>(sp.data()), header->num_indexes);
212b1994897Sopenharmony_ci    }
213b1994897Sopenharmony_ci
214b1994897Sopenharmony_ci    const IndexHeader *GetIndexHeader(EntityId id) const
215b1994897Sopenharmony_ci    {
216b1994897Sopenharmony_ci        if (UNLIKELY(!id.IsValid() || id.GetOffset() >= GetHeader()->file_size)) {
217b1994897Sopenharmony_ci            return nullptr;
218b1994897Sopenharmony_ci        }
219b1994897Sopenharmony_ci        auto headers = GetIndexHeaders();
220b1994897Sopenharmony_ci        auto offset = id.GetOffset();
221b1994897Sopenharmony_ci        for (const auto &header : headers) {
222b1994897Sopenharmony_ci            if (header.start <= offset && offset < header.end) {
223b1994897Sopenharmony_ci                return &header;
224b1994897Sopenharmony_ci            }
225b1994897Sopenharmony_ci        }
226b1994897Sopenharmony_ci        return nullptr;
227b1994897Sopenharmony_ci    }
228b1994897Sopenharmony_ci
229b1994897Sopenharmony_ci    Span<const EntityId> GetClassIndex(const IndexHeader *index_header) const
230b1994897Sopenharmony_ci    {
231b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header == nullptr, File::NULL_INDEX_HEADER, File::GET_CLASS_INDEX);
232b1994897Sopenharmony_ci        auto *header = GetHeader();
233b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
234b1994897Sopenharmony_ci        ASSERT(index_header != nullptr);
235b1994897Sopenharmony_ci        auto class_idx_size = index_header->class_idx_size * EntityId::GetSize();
236b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header->class_idx_off > header->file_size || class_idx_size > header->file_size ||
237b1994897Sopenharmony_ci            index_header->class_idx_off > header->file_size - class_idx_size, File::INVALID_INDEX_HEADER,
238b1994897Sopenharmony_ci            File::GET_CLASS_INDEX);
239b1994897Sopenharmony_ci        auto sp = file.SubSpan(index_header->class_idx_off, index_header->class_idx_size * EntityId::GetSize());
240b1994897Sopenharmony_ci        return Span(reinterpret_cast<const EntityId *>(sp.data()), index_header->class_idx_size);
241b1994897Sopenharmony_ci    }
242b1994897Sopenharmony_ci
243b1994897Sopenharmony_ci    Span<const EntityId> GetClassIndex(EntityId id) const
244b1994897Sopenharmony_ci    {
245b1994897Sopenharmony_ci        auto *index_header = GetIndexHeader(id);
246b1994897Sopenharmony_ci        return GetClassIndex(index_header);
247b1994897Sopenharmony_ci    }
248b1994897Sopenharmony_ci
249b1994897Sopenharmony_ci    Span<const EntityId> GetMethodIndex(const IndexHeader *index_header) const
250b1994897Sopenharmony_ci    {
251b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header == nullptr, File::NULL_INDEX_HEADER, File::GET_METHOD_INDEX);
252b1994897Sopenharmony_ci        auto *header = GetHeader();
253b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
254b1994897Sopenharmony_ci        ASSERT(index_header != nullptr);
255b1994897Sopenharmony_ci        auto method_idx_size = index_header->method_idx_size * EntityId::GetSize();
256b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header->method_idx_off > header->file_size || method_idx_size > header->file_size ||
257b1994897Sopenharmony_ci            index_header->method_idx_off > header->file_size - method_idx_size, File::INVALID_INDEX_HEADER,
258b1994897Sopenharmony_ci            File::GET_METHOD_INDEX);
259b1994897Sopenharmony_ci        auto sp = file.SubSpan(index_header->method_idx_off, index_header->method_idx_size * EntityId::GetSize());
260b1994897Sopenharmony_ci        return Span(reinterpret_cast<const EntityId *>(sp.data()), index_header->method_idx_size);
261b1994897Sopenharmony_ci    }
262b1994897Sopenharmony_ci
263b1994897Sopenharmony_ci    Span<const EntityId> GetMethodIndex(EntityId id) const
264b1994897Sopenharmony_ci    {
265b1994897Sopenharmony_ci        auto *index_header = GetIndexHeader(id);
266b1994897Sopenharmony_ci        return GetMethodIndex(index_header);
267b1994897Sopenharmony_ci    }
268b1994897Sopenharmony_ci
269b1994897Sopenharmony_ci    Span<const EntityId> GetFieldIndex(const IndexHeader *index_header) const
270b1994897Sopenharmony_ci    {
271b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header == nullptr, File::NULL_INDEX_HEADER, File::GET_FIELD_INDEX);
272b1994897Sopenharmony_ci        auto *header = GetHeader();
273b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
274b1994897Sopenharmony_ci        ASSERT(index_header != nullptr);
275b1994897Sopenharmony_ci        auto field_idx_size = index_header->field_idx_size * EntityId::GetSize();
276b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header->field_idx_off > header->file_size || field_idx_size > header->file_size ||
277b1994897Sopenharmony_ci            index_header->field_idx_off > header->file_size - field_idx_size, File::INVALID_INDEX_HEADER,
278b1994897Sopenharmony_ci            File::GET_FIELD_INDEX);
279b1994897Sopenharmony_ci        auto sp = file.SubSpan(index_header->field_idx_off, index_header->field_idx_size * EntityId::GetSize());
280b1994897Sopenharmony_ci        return Span(reinterpret_cast<const EntityId *>(sp.data()), index_header->field_idx_size);
281b1994897Sopenharmony_ci    }
282b1994897Sopenharmony_ci
283b1994897Sopenharmony_ci    Span<const EntityId> GetFieldIndex(EntityId id) const
284b1994897Sopenharmony_ci    {
285b1994897Sopenharmony_ci        auto *index_header = GetIndexHeader(id);
286b1994897Sopenharmony_ci        return GetFieldIndex(index_header);
287b1994897Sopenharmony_ci    }
288b1994897Sopenharmony_ci
289b1994897Sopenharmony_ci    Span<const EntityId> GetProtoIndex(const IndexHeader *index_header) const
290b1994897Sopenharmony_ci    {
291b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header == nullptr, File::NULL_INDEX_HEADER, File::GET_PROTO_INDEX);
292b1994897Sopenharmony_ci        auto *header = GetHeader();
293b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
294b1994897Sopenharmony_ci        ASSERT(index_header != nullptr);
295b1994897Sopenharmony_ci        auto proto_idx_size = index_header->proto_idx_size * EntityId::GetSize();
296b1994897Sopenharmony_ci        ThrowIfWithCheck(index_header->proto_idx_off > header->file_size || proto_idx_size > header->file_size ||
297b1994897Sopenharmony_ci            index_header->proto_idx_off > header->file_size - proto_idx_size, File::INVALID_INDEX_HEADER,
298b1994897Sopenharmony_ci            File::GET_PROTO_INDEX);
299b1994897Sopenharmony_ci        auto sp = file.SubSpan(index_header->proto_idx_off, index_header->proto_idx_size * EntityId::GetSize());
300b1994897Sopenharmony_ci        return Span(reinterpret_cast<const EntityId *>(sp.data()), index_header->proto_idx_size);
301b1994897Sopenharmony_ci    }
302b1994897Sopenharmony_ci
303b1994897Sopenharmony_ci    Span<const EntityId> GetProtoIndex(EntityId id) const
304b1994897Sopenharmony_ci    {
305b1994897Sopenharmony_ci        auto *index_header = GetIndexHeader(id);
306b1994897Sopenharmony_ci        return GetProtoIndex(index_header);
307b1994897Sopenharmony_ci    }
308b1994897Sopenharmony_ci
309b1994897Sopenharmony_ci    Span<const EntityId> GetLineNumberProgramIndex() const
310b1994897Sopenharmony_ci    {
311b1994897Sopenharmony_ci        const Header *header = GetHeader();
312b1994897Sopenharmony_ci        Span file(GetBase(), header->file_size);
313b1994897Sopenharmony_ci        Span lnp_idx_data = file.SubSpan(header->lnp_idx_off, header->num_lnps * EntityId::GetSize());
314b1994897Sopenharmony_ci        return Span(reinterpret_cast<const EntityId *>(lnp_idx_data.data()), header->num_lnps);
315b1994897Sopenharmony_ci    }
316b1994897Sopenharmony_ci
317b1994897Sopenharmony_ci    EntityId ResolveClassIndex(EntityId id, Index idx) const
318b1994897Sopenharmony_ci    {
319b1994897Sopenharmony_ci        auto index = GetClassIndex(id);
320b1994897Sopenharmony_ci        if (UNLIKELY(idx >= index.Size())) {
321b1994897Sopenharmony_ci            return EntityId();
322b1994897Sopenharmony_ci        }
323b1994897Sopenharmony_ci        return index[idx];
324b1994897Sopenharmony_ci    }
325b1994897Sopenharmony_ci
326b1994897Sopenharmony_ci    EntityId ResolveMethodIndex(EntityId id, Index idx) const
327b1994897Sopenharmony_ci    {
328b1994897Sopenharmony_ci        auto index = GetMethodIndex(id);
329b1994897Sopenharmony_ci        if (UNLIKELY(idx >= index.Size())) {
330b1994897Sopenharmony_ci            return EntityId();
331b1994897Sopenharmony_ci        }
332b1994897Sopenharmony_ci        return index[idx];
333b1994897Sopenharmony_ci    }
334b1994897Sopenharmony_ci
335b1994897Sopenharmony_ci    EntityId ResolveOffsetByIndex(EntityId id, Index idx) const
336b1994897Sopenharmony_ci    {
337b1994897Sopenharmony_ci        auto index = GetMethodIndex(id);
338b1994897Sopenharmony_ci        if (UNLIKELY(idx >= index.Size())) {
339b1994897Sopenharmony_ci            return EntityId();
340b1994897Sopenharmony_ci        }
341b1994897Sopenharmony_ci        return index[idx];
342b1994897Sopenharmony_ci    }
343b1994897Sopenharmony_ci
344b1994897Sopenharmony_ci    EntityId ResolveFieldIndex(EntityId id, Index idx) const
345b1994897Sopenharmony_ci    {
346b1994897Sopenharmony_ci        auto index = GetFieldIndex(id);
347b1994897Sopenharmony_ci        if (UNLIKELY(idx >= index.Size())) {
348b1994897Sopenharmony_ci            return EntityId();
349b1994897Sopenharmony_ci        }
350b1994897Sopenharmony_ci        return index[idx];
351b1994897Sopenharmony_ci    }
352b1994897Sopenharmony_ci
353b1994897Sopenharmony_ci    EntityId ResolveProtoIndex(EntityId id, Index idx) const
354b1994897Sopenharmony_ci    {
355b1994897Sopenharmony_ci        auto index = GetProtoIndex(id);
356b1994897Sopenharmony_ci        if (UNLIKELY(idx >= index.Size())) {
357b1994897Sopenharmony_ci            return EntityId();
358b1994897Sopenharmony_ci        }
359b1994897Sopenharmony_ci        return index[idx];
360b1994897Sopenharmony_ci    }
361b1994897Sopenharmony_ci
362b1994897Sopenharmony_ci    EntityId ResolveLineNumberProgramIndex(Index32 idx) const
363b1994897Sopenharmony_ci    {
364b1994897Sopenharmony_ci        auto index = GetLineNumberProgramIndex();
365b1994897Sopenharmony_ci        if (UNLIKELY(idx >= index.Size())) {
366b1994897Sopenharmony_ci            return EntityId();
367b1994897Sopenharmony_ci        }
368b1994897Sopenharmony_ci        return index[idx];
369b1994897Sopenharmony_ci    }
370b1994897Sopenharmony_ci
371b1994897Sopenharmony_ci    const std::string &GetFilename() const
372b1994897Sopenharmony_ci    {
373b1994897Sopenharmony_ci        return FILENAME;
374b1994897Sopenharmony_ci    }
375b1994897Sopenharmony_ci
376b1994897Sopenharmony_ci    PandaCache *GetPandaCache() const
377b1994897Sopenharmony_ci    {
378b1994897Sopenharmony_ci#ifdef ENABLE_FULL_FILE_FIELDS
379b1994897Sopenharmony_ci        return panda_cache_.get();
380b1994897Sopenharmony_ci#else
381b1994897Sopenharmony_ci        LOG(WARNING, PANDAFILE) << "Not Support GetPandaCache from ohos side.";
382b1994897Sopenharmony_ci        return nullptr;
383b1994897Sopenharmony_ci#endif
384b1994897Sopenharmony_ci    }
385b1994897Sopenharmony_ci
386b1994897Sopenharmony_ci    uint32_t GetFilenameHash() const
387b1994897Sopenharmony_ci    {
388b1994897Sopenharmony_ci        return FILENAME_HASH;
389b1994897Sopenharmony_ci    }
390b1994897Sopenharmony_ci
391b1994897Sopenharmony_ci    // note: intentionally returns uint64_t instead of the field type due to usage
392b1994897Sopenharmony_ci    uint64_t GetUniqId() const
393b1994897Sopenharmony_ci    {
394b1994897Sopenharmony_ci        return UNIQ_ID;
395b1994897Sopenharmony_ci    }
396b1994897Sopenharmony_ci
397b1994897Sopenharmony_ci    const std::string &GetFullFileName() const
398b1994897Sopenharmony_ci    {
399b1994897Sopenharmony_ci#ifdef ENABLE_FULL_FILE_FIELDS
400b1994897Sopenharmony_ci        return FULL_FILENAME;
401b1994897Sopenharmony_ci#else
402b1994897Sopenharmony_ci        LOG(FATAL, PANDAFILE) << "Not Support GetFullFileName from ohos side.";
403b1994897Sopenharmony_ci        return FILENAME;
404b1994897Sopenharmony_ci#endif
405b1994897Sopenharmony_ci    }
406b1994897Sopenharmony_ci
407b1994897Sopenharmony_ci    static constexpr uint32_t GetFileBaseOffset()
408b1994897Sopenharmony_ci    {
409b1994897Sopenharmony_ci        return MEMBER_OFFSET(File, base_);
410b1994897Sopenharmony_ci    }
411b1994897Sopenharmony_ci
412b1994897Sopenharmony_ci    Span<const panda::panda_file::EntityPairHeader> GetClassHashTable() const
413b1994897Sopenharmony_ci    {
414b1994897Sopenharmony_ci        return class_hash_table_;
415b1994897Sopenharmony_ci    }
416b1994897Sopenharmony_ci
417b1994897Sopenharmony_ci    static uint32_t CalcFilenameHash(const std::string &filename);
418b1994897Sopenharmony_ci
419b1994897Sopenharmony_ci    static std::unique_ptr<const File> Open(std::string_view filename, OpenMode open_mode = READ_ONLY);
420b1994897Sopenharmony_ci
421b1994897Sopenharmony_ci    static std::unique_ptr<const File> OpenFromMemory(os::mem::ConstBytePtr &&ptr);
422b1994897Sopenharmony_ci
423b1994897Sopenharmony_ci    static std::unique_ptr<const File> OpenFromMemory(os::mem::ConstBytePtr &&ptr, std::string_view filename);
424b1994897Sopenharmony_ci
425b1994897Sopenharmony_ci    static std::unique_ptr<const File> OpenUncompressedArchive(int fd, const std::string_view &filename, size_t size,
426b1994897Sopenharmony_ci                                                               uint32_t offset, OpenMode open_mode = READ_ONLY);
427b1994897Sopenharmony_ci
428b1994897Sopenharmony_ci    void SetClassHashTable(panda::Span<const panda::panda_file::EntityPairHeader> class_hash_table) const
429b1994897Sopenharmony_ci    {
430b1994897Sopenharmony_ci        class_hash_table_ = class_hash_table;
431b1994897Sopenharmony_ci    }
432b1994897Sopenharmony_ci
433b1994897Sopenharmony_ci    bool ValidateChecksum(uint32_t *cal_checksum_out = nullptr) const;
434b1994897Sopenharmony_ci
435b1994897Sopenharmony_ci    void ThrowIfWithCheck(bool cond, const std::string_view& msg, const std::string_view& tag = "") const;
436b1994897Sopenharmony_ci
437b1994897Sopenharmony_ci    static constexpr const char *INVALID_FILE_OFFSET = "Invalid file offset";
438b1994897Sopenharmony_ci    static constexpr const char *NULL_INDEX_HEADER = "index_header is null";
439b1994897Sopenharmony_ci    static constexpr const char *INVALID_INDEX_HEADER = "index_header is invalid";
440b1994897Sopenharmony_ci
441b1994897Sopenharmony_ci    static constexpr const char *GET_CLASS_INDEX = "GetClassIndex";
442b1994897Sopenharmony_ci    static constexpr const char *GET_METHOD_INDEX = "GetMethodIndex";
443b1994897Sopenharmony_ci    static constexpr const char *GET_FIELD_INDEX = "GetFieldIndex";
444b1994897Sopenharmony_ci    static constexpr const char *GET_PROTO_INDEX = "GetProtoIndex";
445b1994897Sopenharmony_ci
446b1994897Sopenharmony_ci    static constexpr const char *ANNOTATION_DATA_ACCESSOR = "AnnotationDataAccessor";
447b1994897Sopenharmony_ci    static constexpr const char *CLASS_DATA_ACCESSOR = "ClassDataAccessor";
448b1994897Sopenharmony_ci    static constexpr const char *CODE_DATA_ACCESSOR = "CodeDataAccessor";
449b1994897Sopenharmony_ci    static constexpr const char *FIELD_DATA_ACCESSOR = "FieldDataAccessor";
450b1994897Sopenharmony_ci    static constexpr const char *GET_SPAN_FROM_ID = "GetSpanFromId";
451b1994897Sopenharmony_ci
452b1994897Sopenharmony_ci    ~File();
453b1994897Sopenharmony_ci
454b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(File);
455b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(File);
456b1994897Sopenharmony_ci
457b1994897Sopenharmony_ciprivate:
458b1994897Sopenharmony_ci    File(std::string filename, os::mem::ConstBytePtr &&base);
459b1994897Sopenharmony_ci
460b1994897Sopenharmony_ci    os::mem::ConstBytePtr base_;
461b1994897Sopenharmony_ci    const std::string FILENAME;
462b1994897Sopenharmony_ci    const uint32_t FILENAME_HASH;
463b1994897Sopenharmony_ci#ifdef ENABLE_FULL_FILE_FIELDS
464b1994897Sopenharmony_ci    const std::string FULL_FILENAME;
465b1994897Sopenharmony_ci    std::unique_ptr<PandaCache> panda_cache_;
466b1994897Sopenharmony_ci#endif
467b1994897Sopenharmony_ci    const uint32_t UNIQ_ID;
468b1994897Sopenharmony_ci    mutable panda::Span<const panda::panda_file::EntityPairHeader> class_hash_table_;
469b1994897Sopenharmony_ci};
470b1994897Sopenharmony_ci
471b1994897Sopenharmony_cistatic_assert(File::GetFileBaseOffset() == 0);
472b1994897Sopenharmony_ci
473b1994897Sopenharmony_ciinline bool operator==(const File::StringData &string_data1, const File::StringData &string_data2)
474b1994897Sopenharmony_ci{
475b1994897Sopenharmony_ci    if (string_data1.utf16_length != string_data2.utf16_length) {
476b1994897Sopenharmony_ci        return false;
477b1994897Sopenharmony_ci    }
478b1994897Sopenharmony_ci
479b1994897Sopenharmony_ci    return utf::IsEqual(string_data1.data, string_data2.data);
480b1994897Sopenharmony_ci}
481b1994897Sopenharmony_ci
482b1994897Sopenharmony_ciinline bool operator!=(const File::StringData &string_data1, const File::StringData &string_data2)
483b1994897Sopenharmony_ci{
484b1994897Sopenharmony_ci    return !(string_data1 == string_data2);
485b1994897Sopenharmony_ci}
486b1994897Sopenharmony_ci
487b1994897Sopenharmony_ciinline bool operator<(const File::StringData &string_data1, const File::StringData &string_data2)
488b1994897Sopenharmony_ci{
489b1994897Sopenharmony_ci    if (string_data1.utf16_length == string_data2.utf16_length) {
490b1994897Sopenharmony_ci        return utf::CompareMUtf8ToMUtf8(string_data1.data, string_data2.data) < 0;
491b1994897Sopenharmony_ci    }
492b1994897Sopenharmony_ci
493b1994897Sopenharmony_ci    return string_data1.utf16_length < string_data2.utf16_length;
494b1994897Sopenharmony_ci}
495b1994897Sopenharmony_ci
496b1994897Sopenharmony_cibool CheckSecureMem(uintptr_t mem, size_t size);
497b1994897Sopenharmony_ci
498b1994897Sopenharmony_ci/*
499b1994897Sopenharmony_ci * OpenPandaFileOrZip from location which specicify the name.
500b1994897Sopenharmony_ci */
501b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFileOrZip(std::string_view location,
502b1994897Sopenharmony_ci                                               panda_file::File::OpenMode open_mode = panda_file::File::READ_ONLY);
503b1994897Sopenharmony_ci
504b1994897Sopenharmony_ci/*
505b1994897Sopenharmony_ci * OpenPandaFileFromMemory from file buffer.
506b1994897Sopenharmony_ci */
507b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFileFromMemory(const void *buffer, size_t size, std::string tag = "");
508b1994897Sopenharmony_ci
509b1994897Sopenharmony_ci/*
510b1994897Sopenharmony_ci * OpenPandaFileFromMemory from secure buffer.
511b1994897Sopenharmony_ci */
512b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFileFromSecureMemory(uint8_t *buffer, size_t size);
513b1994897Sopenharmony_ci
514b1994897Sopenharmony_ci/*
515b1994897Sopenharmony_ci * OpenPandaFile from location which specicify the name.
516b1994897Sopenharmony_ci */
517b1994897Sopenharmony_cistd::unique_ptr<const File> OpenPandaFile(std::string_view location, std::string_view archive_filename = "",
518b1994897Sopenharmony_ci                                          panda_file::File::OpenMode open_mode = panda_file::File::READ_ONLY);
519b1994897Sopenharmony_ci
520b1994897Sopenharmony_ci/*
521b1994897Sopenharmony_ci * Check ptr point valid panda file: magic
522b1994897Sopenharmony_ci */
523b1994897Sopenharmony_cibool CheckHeader(const os::mem::ConstBytePtr &ptr, const std::string_view &filename = "");
524b1994897Sopenharmony_civoid CheckFileVersion(const std::array<uint8_t, File::VERSION_SIZE> &file_version, const std::string_view &filename);
525b1994897Sopenharmony_ci
526b1994897Sopenharmony_ci// Last version which contains redundance literal array in header
527b1994897Sopenharmony_ciconstexpr std::array<uint8_t, File::VERSION_SIZE> LAST_CONTAINS_LITERAL_IN_HEADER_VERSION {12, 0, 6, 0};
528b1994897Sopenharmony_cibool ContainsLiteralArrayInHeader(const std::array<uint8_t, File::VERSION_SIZE> &version);
529b1994897Sopenharmony_ci
530b1994897Sopenharmony_ci// NOLINTNEXTLINE(readability-identifier-naming)
531b1994897Sopenharmony_ciextern const char *ARCHIVE_FILENAME;
532b1994897Sopenharmony_ci}  // namespace panda::panda_file
533b1994897Sopenharmony_ci
534b1994897Sopenharmony_cinamespace std {
535b1994897Sopenharmony_citemplate <>
536b1994897Sopenharmony_cistruct hash<panda::panda_file::File::EntityId> {
537b1994897Sopenharmony_ci    std::size_t operator()(panda::panda_file::File::EntityId id) const
538b1994897Sopenharmony_ci    {
539b1994897Sopenharmony_ci        return std::hash<uint32_t> {}(id.GetOffset());
540b1994897Sopenharmony_ci    }
541b1994897Sopenharmony_ci};
542b1994897Sopenharmony_ci
543b1994897Sopenharmony_ci}  // namespace std
544b1994897Sopenharmony_ci
545b1994897Sopenharmony_ci#endif  // LIBPANDAFILE_FILE_H
546