1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef LIBPANDAFILE_FILE_ITEMS_H_
17 #define LIBPANDAFILE_FILE_ITEMS_H_
18 
19 #include "file.h"
20 #include "file_writer.h"
21 #include "macros.h"
22 #include "modifiers.h"
23 #include "type.h"
24 #include "file_format_version.h"
25 #include "source_lang_enum.h"
26 
27 #include <cstddef>
28 #include <cstdint>
29 
30 #include <algorithm>
31 #include <memory>
32 #include <string>
33 #include <type_traits>
34 #include <variant>
35 #include <vector>
36 #include <list>
37 #include <set>
38 
39 namespace ark::panda_file {
40 
41 enum class ClassTag : uint8_t {
42     NOTHING = 0x00,
43     INTERFACES = 0x01,
44     SOURCE_LANG = 0x02,
45     RUNTIME_ANNOTATION = 0x03,
46     ANNOTATION = 0x04,
47     RUNTIME_TYPE_ANNOTATION = 0x05,
48     TYPE_ANNOTATION = 0x06,
49     SOURCE_FILE = 0x07
50 };
51 
52 enum class MethodTag : uint8_t {
53     NOTHING = 0x00,
54     CODE = 0x01,
55     SOURCE_LANG = 0x02,
56     RUNTIME_ANNOTATION = 0x03,
57     RUNTIME_PARAM_ANNOTATION = 0x04,
58     DEBUG_INFO = 0x05,
59     ANNOTATION = 0x06,
60     PARAM_ANNOTATION = 0x07,
61     TYPE_ANNOTATION = 0x08,
62     RUNTIME_TYPE_ANNOTATION = 0x09,
63     PROFILE_INFO = 0x0a
64 };
65 
66 enum class FieldTag : uint8_t {
67     NOTHING = 0x00,
68     INT_VALUE = 0x01,
69     VALUE = 0x02,
70     RUNTIME_ANNOTATION = 0x03,
71     ANNOTATION = 0x04,
72     RUNTIME_TYPE_ANNOTATION = 0x05,
73     TYPE_ANNOTATION = 0x06
74 };
75 
76 bool IsDynamicLanguage(ark::panda_file::SourceLang lang);
77 std::optional<ark::panda_file::SourceLang> LanguageFromString(std::string_view lang);
78 const char *LanguageToString(ark::panda_file::SourceLang lang);
79 const char *GetCtorName(ark::panda_file::SourceLang lang);
80 const char *GetCctorName(ark::panda_file::SourceLang lang);
81 const char *GetStringClassDescriptor(ark::panda_file::SourceLang lang);
82 
83 constexpr size_t ID_SIZE = File::EntityId::GetSize();
84 constexpr size_t IDX_SIZE = sizeof(uint16_t);
85 constexpr size_t TAG_SIZE = 1;
86 constexpr uint32_t INVALID_OFFSET = std::numeric_limits<uint32_t>::max();
87 constexpr uint32_t INVALID_INDEX = std::numeric_limits<uint32_t>::max();
88 constexpr uint32_t MAX_INDEX_16 = std::numeric_limits<uint16_t>::max();
89 constexpr uint32_t MAX_INDEX_32 = std::numeric_limits<uint32_t>::max();
90 
91 constexpr uint32_t PGO_STRING_DEFAULT_COUNT = 5;
92 constexpr uint32_t PGO_CLASS_DEFAULT_COUNT = 3;
93 constexpr uint32_t PGO_CODE_DEFAULT_COUNT = 1;
94 
95 enum class ItemTypes {
96     ANNOTATION_ITEM,
97     CATCH_BLOCK_ITEM,
98     CLASS_INDEX_ITEM,
99     CLASS_ITEM,
100     CODE_ITEM,
101     DEBUG_INFO_ITEM,
102     END_ITEM,
103     FIELD_INDEX_ITEM,
104     FIELD_ITEM,
105     FOREIGN_CLASS_ITEM,
106     FOREIGN_FIELD_ITEM,
107     FOREIGN_METHOD_ITEM,
108     LINE_NUMBER_PROGRAM_INDEX_ITEM,
109     LINE_NUMBER_PROGRAM_ITEM,
110     LITERAL_ARRAY_ITEM,
111     LITERAL_ITEM,
112     METHOD_HANDLE_ITEM,
113     METHOD_INDEX_ITEM,
114     METHOD_ITEM,
115     PARAM_ANNOTATIONS_ITEM,
116     PRIMITIVE_TYPE_ITEM,
117     PROTO_INDEX_ITEM,
118     PROTO_ITEM,
119     REGION_HEADER,
120     REGION_SECTION,
121     STRING_ITEM,
122     TRY_BLOCK_ITEM,
123     VALUE_ITEM
124 };
125 
126 constexpr std::string_view STRING_ITEM = "string_item";
127 constexpr std::string_view CLASS_ITEM = "class_item";
128 constexpr std::string_view CODE_ITEM = "code_item";
129 
130 enum class IndexType {
131     // 16-bit indexes
132     CLASS = 0x0,
133     METHOD = 0x1,
134     FIELD = 0x2,
135     PROTO = 0x3,
136     LAST_16 = PROTO,
137 
138     // 32-bit indexes
139     LINE_NUMBER_PROG = 0x04,
140     LAST_32 = LINE_NUMBER_PROG,
141 
142     NONE
143 };
144 
145 constexpr size_t INDEX_COUNT_16 = static_cast<size_t>(IndexType::LAST_16) + 1;
146 
147 class IndexedItem;
148 
149 class BaseItem {
150 public:
151     using VisitorCallBack = std::function<bool(BaseItem *)>;
152 
153     BaseItem() = default;
154     virtual ~BaseItem() = default;
155 
156     DEFAULT_COPY_SEMANTIC(BaseItem);
157     DEFAULT_MOVE_SEMANTIC(BaseItem);
158 
GetSize() const159     size_t GetSize() const
160     {
161         return CalculateSize();
162     }
163 
164     virtual size_t CalculateSize() const = 0;
165 
ComputeLayout()166     virtual void ComputeLayout() {}
167 
Alignment()168     virtual size_t Alignment()
169     {
170         return 1;
171     }
172 
IsForeign() const173     virtual bool IsForeign() const
174     {
175         return false;
176     }
177 
GetOffset() const178     uint32_t GetOffset() const
179     {
180         return offset_;
181     }
182 
GetFileId() const183     panda_file::File::EntityId GetFileId() const
184     {
185         return panda_file::File::EntityId(offset_);
186     }
187 
SetOffset(uint32_t offset)188     void SetOffset(uint32_t offset)
189     {
190         offset_ = offset;
191     }
192 
NeedsEmit() const193     bool NeedsEmit() const
194     {
195         return needsEmit_;
196     }
197 
SetNeedsEmit(bool needsEmit)198     void SetNeedsEmit(bool needsEmit)
199     {
200         needsEmit_ = needsEmit;
201     }
202 
GetIndexDependencies() const203     const std::list<IndexedItem *> &GetIndexDependencies() const
204     {
205         return indexDeps_;
206     }
207 
AddIndexDependency(IndexedItem *item)208     void AddIndexDependency(IndexedItem *item)
209     {
210         ASSERT(item != nullptr);
211         indexDeps_.push_back(item);
212     }
213 
SetOrderIndex(uint32_t order)214     void SetOrderIndex(uint32_t order)
215     {
216         order_ = order;
217     }
218 
GetOrderIndex() const219     uint32_t GetOrderIndex() const
220     {
221         return order_;
222     }
223 
HasOrderIndex() const224     bool HasOrderIndex() const
225     {
226         return order_ != INVALID_INDEX;
227     }
228 
229     virtual bool Write(Writer *writer) = 0;
230 
231     std::string GetName() const;
232 
233     virtual ItemTypes GetItemType() const = 0;
234 
Dump([[maybe_unused]] std::ostream &os) const235     virtual void Dump([[maybe_unused]] std::ostream &os) const {}
236 
Visit([[maybe_unused]] const VisitorCallBack &cb)237     virtual void Visit([[maybe_unused]] const VisitorCallBack &cb) {}
238 
SetPGORank(uint32_t rank)239     void SetPGORank(uint32_t rank)
240     {
241         pgoRank_ = rank;
242     }
243 
GetPGORank() const244     uint32_t GetPGORank() const
245     {
246         return pgoRank_;
247     }
248 
SetOriginalRank(uint32_t rank)249     void SetOriginalRank(uint32_t rank)
250     {
251         originalRank_ = rank;
252     }
253 
GetOriginalRank() const254     uint32_t GetOriginalRank() const
255     {
256         return originalRank_;
257     }
258 
259 private:
260     bool needsEmit_ {true};
261     uint32_t offset_ {0};
262     uint32_t order_ {INVALID_INDEX};
263     std::list<IndexedItem *> indexDeps_;
264     uint32_t pgoRank_ {0};
265     uint32_t originalRank_ {0};
266 };
267 
268 class IndexedItem : public BaseItem {
269 public:
IndexedItem()270     IndexedItem()
271     {
272         itemAllocId_ = itemAllocIdNext_++;
273     }
274 
GetIndex(const BaseItem *item) const275     uint32_t GetIndex(const BaseItem *item) const
276     {
277         auto *idx = FindIndex(item);
278         ASSERT(idx != nullptr);
279         return idx->index;
280     }
281 
HasIndex(const BaseItem *item) const282     bool HasIndex(const BaseItem *item) const
283     {
284         return FindIndex(item) != nullptr;
285     }
286 
SetIndex(const BaseItem *start, const BaseItem *end, uint32_t index)287     void SetIndex(const BaseItem *start, const BaseItem *end, uint32_t index)
288     {
289         ASSERT(FindIndex(start, end) == nullptr);
290         indexes_.push_back({start, end, index});
291     }
292 
ClearIndexes()293     void ClearIndexes()
294     {
295         indexes_.clear();
296     }
297 
IncRefCount()298     void IncRefCount()
299     {
300         ++refCount_;
301     }
302 
DecRefCount()303     void DecRefCount()
304     {
305         ASSERT(refCount_ != 0);
306         --refCount_;
307     }
308 
GetRefCount() const309     size_t GetRefCount() const
310     {
311         return refCount_;
312     }
313 
GetIndexType() const314     virtual IndexType GetIndexType() const
315     {
316         return IndexType::NONE;
317     }
318 
GetItemAllocId() const319     size_t GetItemAllocId() const
320     {
321         return itemAllocId_;
322     }
323 
324 private:
325     struct Index {
326         const BaseItem *start;
327         const BaseItem *end;
328         uint32_t index;
329     };
330 
FindIndex(const BaseItem *start, const BaseItem *end) const331     const Index *FindIndex(const BaseItem *start, const BaseItem *end) const
332     {
333         auto it = std::find_if(indexes_.cbegin(), indexes_.cend(),
334                                [start, end](const Index &idx) { return idx.start == start && idx.end == end; });
335 
336         return it != indexes_.cend() ? &*it : nullptr;
337     }
338 
FindIndex(const BaseItem *item) const339     const Index *FindIndex(const BaseItem *item) const
340     {
341         ASSERT(item);
342         ASSERT(item->HasOrderIndex());
343         auto orderIdx = item->GetOrderIndex();
344 
345         auto it = std::find_if(indexes_.cbegin(), indexes_.cend(), [orderIdx](const Index &idx) {
346             if (idx.start == nullptr && idx.end == nullptr) {
347                 return true;
348             }
349 
350             if (idx.start == nullptr || idx.end == nullptr) {
351                 return false;
352             }
353 
354             ASSERT(idx.start->HasOrderIndex());
355             ASSERT(idx.end->HasOrderIndex());
356             return idx.start->GetOrderIndex() <= orderIdx && orderIdx < idx.end->GetOrderIndex();
357         });
358 
359         return it != indexes_.cend() ? &*it : nullptr;
360     }
361 
362     std::vector<Index> indexes_;
363     size_t refCount_ {1};
364     size_t itemAllocId_ {0};
365 
366     // needed for keeping same layout of panda file after rebuilding it,
367     // even if same `IndexedItem` was allocated at different addresses
368     static size_t itemAllocIdNext_;
369 };
370 
371 class TypeItem : public IndexedItem {
372 public:
TypeItem(Type type)373     explicit TypeItem(Type type) : type_(type) {}
374 
TypeItem(Type::TypeId typeId)375     explicit TypeItem(Type::TypeId typeId) : type_(typeId) {}
376 
377     ~TypeItem() override = default;
378 
GetType() const379     Type GetType() const
380     {
381         return type_;
382     }
383 
384     IndexType GetIndexType() const override
385     {
386         return IndexType::CLASS;
387     }
388 
389     DEFAULT_MOVE_SEMANTIC(TypeItem);
390     DEFAULT_COPY_SEMANTIC(TypeItem);
391 
392 private:
393     Type type_;
394 };
395 
396 class PrimitiveTypeItem : public TypeItem {
397 public:
PrimitiveTypeItem(Type type)398     explicit PrimitiveTypeItem(Type type) : PrimitiveTypeItem(type.GetId()) {}
399 
PrimitiveTypeItem(Type::TypeId typeId)400     explicit PrimitiveTypeItem(Type::TypeId typeId) : TypeItem(typeId)
401     {
402         ASSERT(GetType().IsPrimitive());
403         SetNeedsEmit(false);
404         SetOffset(GetType().GetFieldEncoding());
405     }
406 
407     ~PrimitiveTypeItem() override = default;
408 
409     size_t CalculateSize() const override
410     {
411         return 0;
412     }
413 
414     bool Write([[maybe_unused]] Writer *writer) override
415     {
416         return true;
417     }
418 
419     ItemTypes GetItemType() const override
420     {
421         return ItemTypes::PRIMITIVE_TYPE_ITEM;
422     }
423 
424     DEFAULT_MOVE_SEMANTIC(PrimitiveTypeItem);
425     DEFAULT_COPY_SEMANTIC(PrimitiveTypeItem);
426 };
427 
428 class StringItem : public BaseItem {
429 public:
430     explicit StringItem(std::string str);
431 
432     explicit StringItem(File::StringData data);
433 
434     ~StringItem() override = default;
435 
436     size_t CalculateSize() const override;
437 
438     bool Write(Writer *writer) override;
439 
440     ItemTypes GetItemType() const override
441     {
442         return ItemTypes::STRING_ITEM;
443     }
444 
GetData() const445     const std::string &GetData() const
446     {
447         return str_;
448     }
449 
GetUtf16Len() const450     size_t GetUtf16Len() const
451     {
452         return utf16Length_;
453     }
454 
455     DEFAULT_MOVE_SEMANTIC(StringItem);
456     DEFAULT_COPY_SEMANTIC(StringItem);
457 
458 private:
459     std::string str_;
460     size_t utf16Length_;
461     size_t isAscii_ = 0;
462 };
463 
464 class AnnotationItem;
465 class BaseClassItem;
466 class ClassItem;
467 class ForeignClassItem;
468 class ValueItem;
469 
470 class BaseFieldItem : public IndexedItem {
471 public:
472     IndexType GetIndexType() const override
473     {
474         return IndexType::FIELD;
475     }
476 
GetNameItem() const477     StringItem *GetNameItem() const
478     {
479         return name_;
480     }
481 
GetTypeItem() const482     TypeItem *GetTypeItem() const
483     {
484         return type_;
485     }
486 
GetClassItem() const487     BaseClassItem *GetClassItem() const
488     {
489         return class_;
490     }
491 
492     ~BaseFieldItem() override = default;
493 
494     DEFAULT_MOVE_SEMANTIC(BaseFieldItem);
495     DEFAULT_COPY_SEMANTIC(BaseFieldItem);
496 
497 protected:
498     BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type);
499 
500     size_t CalculateSize() const override;
501 
502     bool Write(Writer *writer) override;
503 
504 private:
505     BaseClassItem *class_;
506     StringItem *name_;
507     TypeItem *type_;
508 };
509 
510 class FieldItem : public BaseFieldItem {
511 public:
512     FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags);
513 
514     ~FieldItem() override = default;
515 
516     void SetValue(ValueItem *value);
517 
GetValue() const518     ValueItem *GetValue() const
519     {
520         return value_;
521     }
522 
AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)523     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
524     {
525         runtimeAnnotations_.push_back(runtimeAnnotation);
526     }
527 
AddAnnotation(AnnotationItem *annotation)528     void AddAnnotation(AnnotationItem *annotation)
529     {
530         annotations_.push_back(annotation);
531     }
532 
AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)533     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
534     {
535         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
536     }
537 
AddTypeAnnotation(AnnotationItem *typeAnnotation)538     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
539     {
540         typeAnnotations_.push_back(typeAnnotation);
541     }
542 
543     size_t CalculateSize() const override;
544 
545     bool Write(Writer *writer) override;
546 
547     ItemTypes GetItemType() const override
548     {
549         return ItemTypes::FIELD_ITEM;
550     }
551 
GetRuntimeAnnotations()552     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
553     {
554         return &runtimeAnnotations_;
555     }
556 
GetAnnotations()557     std::vector<AnnotationItem *> *GetAnnotations()
558     {
559         return &annotations_;
560     }
561 
GetTypeAnnotations()562     std::vector<AnnotationItem *> *GetTypeAnnotations()
563     {
564         return &typeAnnotations_;
565     }
566 
GetRuntimeTypeAnnotations()567     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
568     {
569         return &runtimeTypeAnnotations_;
570     }
571 
GetAccessFlags() const572     uint32_t GetAccessFlags() const
573     {
574         return accessFlags_;
575     }
576 
577     DEFAULT_MOVE_SEMANTIC(FieldItem);
578     DEFAULT_COPY_SEMANTIC(FieldItem);
579 
580 private:
581     bool WriteValue(Writer *writer);
582 
583     bool WriteAnnotations(Writer *writer);
584 
585     bool WriteTaggedData(Writer *writer);
586 
587     uint32_t accessFlags_;
588     ValueItem *value_ {nullptr};
589     std::vector<AnnotationItem *> runtimeAnnotations_;
590     std::vector<AnnotationItem *> annotations_;
591     std::vector<AnnotationItem *> typeAnnotations_;
592     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
593 };
594 
595 class ProtoItem;
596 class CodeItem;
597 
598 /**
599  * @brief Base class of `LineNumberProgramItem`.
600  *
601  * Instances of this class might be used in order to fill constant pool of a shared `LineNumberProgram`.
602  * Implementations must override `Empty`, `EmitOpcode` and `EmitRegister`, which are left no-op.
603  */
604 class LineNumberProgramItemBase {
605 public:
606     enum class Opcode : uint8_t {
607         END_SEQUENCE = 0x00,
608         ADVANCE_PC = 0x01,
609         ADVANCE_LINE = 0x02,
610         START_LOCAL = 0x03,
611         START_LOCAL_EXTENDED = 0x04,
612         END_LOCAL = 0x05,
613         RESTART_LOCAL = 0x06,
614         SET_PROLOGUE_END = 0x07,
615         SET_EPILOGUE_BEGIN = 0x08,
616         SET_FILE = 0x09,
617         SET_SOURCE_CODE = 0x0a,
618         SET_COLUMN = 0X0b,
619         LAST
620     };
621 
622     static constexpr uint8_t OPCODE_BASE = static_cast<uint8_t>(Opcode::LAST);
623     static constexpr int32_t LINE_RANGE = 15;
624     static constexpr int32_t LINE_BASE = -4;
625 
626     void EmitEnd();
627 
628     void EmitAdvancePc(std::vector<uint8_t> *constantPool, uint32_t value);
629 
630     void EmitAdvanceLine(std::vector<uint8_t> *constantPool, int32_t value);
631 
632     void EmitColumn(std::vector<uint8_t> *constantPool, uint32_t pcInc, uint32_t column);
633 
634     void EmitStartLocal(std::vector<uint8_t> *constantPool, int32_t registerNumber, StringItem *name, StringItem *type);
635 
636     void EmitStartLocalExtended(std::vector<uint8_t> *constantPool, int32_t registerNumber, StringItem *name,
637                                 StringItem *type, StringItem *typeSignature);
638 
639     void EmitEndLocal(int32_t registerNumber);
640 
641     void EmitRestartLocal(int32_t registerNumber);
642 
643     bool EmitSpecialOpcode(uint32_t pcInc, int32_t lineInc);
644 
645     void EmitPrologueEnd();
646 
647     void EmitEpilogueBegin();
648 
649     void EmitSetFile(std::vector<uint8_t> *constantPool, StringItem *sourceFile);
650 
651     void EmitSetSourceCode(std::vector<uint8_t> *constantPool, StringItem *sourceCode);
652 
653     void EmitOpcode(Opcode opcode);
654 
Empty() const655     virtual bool Empty() const
656     {
657         return true;
658     }
659 
660 protected:
EmitOpcode([[maybe_unused]] uint8_t opcode)661     virtual void EmitOpcode([[maybe_unused]] uint8_t opcode) {}
EmitRegister([[maybe_unused]] int32_t registerNumber)662     virtual void EmitRegister([[maybe_unused]] int32_t registerNumber) {}
663 
664     static void EmitUleb128(std::vector<uint8_t> *data, uint32_t value);
665 
666     static void EmitSleb128(std::vector<uint8_t> *data, int32_t value);
667 };
668 
669 // NOLINTNEXTLINE(fuchsia-multiple-inheritance)
670 class LineNumberProgramItem final : public IndexedItem, public LineNumberProgramItemBase {
671 public:
672     bool Write(Writer *writer) override;
673 
674     size_t CalculateSize() const override;
675 
676     ItemTypes GetItemType() const override
677     {
678         return ItemTypes::LINE_NUMBER_PROGRAM_ITEM;
679     }
680 
681     bool Empty() const override
682     {
683         return GetData().empty();
684     }
685 
GetData() const686     const std::vector<uint8_t> &GetData() const
687     {
688         return data_;
689     }
690 
691     IndexType GetIndexType() const override
692     {
693         return IndexType::LINE_NUMBER_PROG;
694     }
695 
696     void SetData(std::vector<uint8_t> &&data);
697 
698 private:
699     void EmitOpcode(uint8_t opcode) override;
700     void EmitRegister(int32_t registerNumber) override;
701 
702     std::vector<uint8_t> data_;
703 };
704 
705 class DebugInfoItem : public BaseItem {
706 public:
DebugInfoItem(LineNumberProgramItem *item)707     explicit DebugInfoItem(LineNumberProgramItem *item) : program_(item) {}
708 
709     ~DebugInfoItem() override = default;
710 
711     DEFAULT_MOVE_SEMANTIC(DebugInfoItem);
712     DEFAULT_COPY_SEMANTIC(DebugInfoItem);
713 
GetLineNumber() const714     size_t GetLineNumber() const
715     {
716         return lineNum_;
717     }
718 
SetLineNumber(size_t lineNum)719     void SetLineNumber(size_t lineNum)
720     {
721         lineNum_ = lineNum;
722     }
723 
GetLineNumberProgram() const724     LineNumberProgramItem *GetLineNumberProgram() const
725     {
726         return program_;
727     }
728 
SetLineNumberProgram(LineNumberProgramItem *program)729     void SetLineNumberProgram(LineNumberProgramItem *program)
730     {
731         ASSERT(program->GetOffset() != 0);
732         program_ = program;
733     }
734 
AddParameter(StringItem *name)735     void AddParameter(StringItem *name)
736     {
737         parameters_.push_back(name);
738     }
739 
GetParameters() const740     const std::vector<StringItem *> *GetParameters() const
741     {
742         return &parameters_;
743     }
744 
GetConstantPool()745     std::vector<uint8_t> *GetConstantPool()
746     {
747         return &constantPool_;
748     }
749 
750     size_t CalculateSize() const override;
751 
752     bool Write(Writer *writer) override;
753 
754     ItemTypes GetItemType() const override
755     {
756         return ItemTypes::DEBUG_INFO_ITEM;
757     }
758 
759     void Dump(std::ostream &os) const override;
760 
761 private:
762     size_t lineNum_ {0};
763     LineNumberProgramItem *program_;
764     std::vector<uint8_t> constantPool_;
765     std::vector<StringItem *> parameters_;
766 };
767 
768 class BaseMethodItem : public IndexedItem {
769 public:
GetProto() const770     ProtoItem *GetProto() const
771     {
772         return proto_;
773     }
774 
IsStatic() const775     bool IsStatic() const
776     {
777         return (accessFlags_ & ACC_STATIC) != 0;
778     }
779 
780     IndexType GetIndexType() const override
781     {
782         return IndexType::METHOD;
783     }
784 
GetNameItem() const785     StringItem *GetNameItem() const
786     {
787         return name_;
788     }
789 
GetClassItem() const790     BaseClassItem *GetClassItem() const
791     {
792         return class_;
793     }
794 
GetAccessFlags() const795     uint32_t GetAccessFlags() const
796     {
797         return accessFlags_;
798     }
799 
800     ~BaseMethodItem() override = default;
801 
802     DEFAULT_MOVE_SEMANTIC(BaseMethodItem);
803     DEFAULT_COPY_SEMANTIC(BaseMethodItem);
804 
805 protected:
806     BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags);
807 
808     size_t CalculateSize() const override;
809 
810     bool Write(Writer *writer) override;
811 
812 private:
813     BaseClassItem *class_;
814     StringItem *name_;
815     ProtoItem *proto_;
816     uint32_t accessFlags_;
817 };
818 
819 class MethodParamItem {
820 public:
MethodParamItem(TypeItem *type)821     explicit MethodParamItem(TypeItem *type) : type_(type) {}
822 
823     ~MethodParamItem() = default;
824 
825     DEFAULT_MOVE_SEMANTIC(MethodParamItem);
826     DEFAULT_COPY_SEMANTIC(MethodParamItem);
827 
AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)828     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
829     {
830         runtimeAnnotations_.push_back(runtimeAnnotation);
831     }
832 
AddAnnotation(AnnotationItem *annotation)833     void AddAnnotation(AnnotationItem *annotation)
834     {
835         annotations_.push_back(annotation);
836     }
837 
AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)838     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
839     {
840         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
841     }
842 
AddTypeAnnotation(AnnotationItem *typeAnnotation)843     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
844     {
845         typeAnnotations_.push_back(typeAnnotation);
846     }
847 
GetType() const848     TypeItem *GetType() const
849     {
850         return type_;
851     }
852 
GetRuntimeAnnotations() const853     const std::vector<AnnotationItem *> &GetRuntimeAnnotations() const
854     {
855         return runtimeAnnotations_;
856     }
857 
GetAnnotations() const858     const std::vector<AnnotationItem *> &GetAnnotations() const
859     {
860         return annotations_;
861     }
862 
GetRuntimeTypeAnnotations() const863     const std::vector<AnnotationItem *> &GetRuntimeTypeAnnotations() const
864     {
865         return runtimeTypeAnnotations_;
866     }
867 
GetTypeAnnotations() const868     const std::vector<AnnotationItem *> &GetTypeAnnotations() const
869     {
870         return typeAnnotations_;
871     }
872 
HasAnnotations() const873     bool HasAnnotations() const
874     {
875         return !annotations_.empty();
876     }
877 
HasRuntimeAnnotations() const878     bool HasRuntimeAnnotations() const
879     {
880         return !runtimeAnnotations_.empty();
881     }
882 
883 private:
884     TypeItem *type_;
885     std::vector<AnnotationItem *> runtimeAnnotations_;
886     std::vector<AnnotationItem *> annotations_;
887     std::vector<AnnotationItem *> typeAnnotations_;
888     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
889 };
890 
891 class ParamAnnotationsItem;
892 class BaseClassItem;
893 
894 class MethodItem : public BaseMethodItem {
895 public:
896     MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags,
897                std::vector<MethodParamItem> params);
898 
899     ~MethodItem() override = default;
900 
901     DEFAULT_MOVE_SEMANTIC(MethodItem);
902     DEFAULT_COPY_SEMANTIC(MethodItem);
903 
SetSourceLang(SourceLang lang)904     void SetSourceLang(SourceLang lang)
905     {
906         sourceLang_ = lang;
907     }
908 
SetCode(CodeItem *code)909     void SetCode(CodeItem *code)
910     {
911         code_ = code;
912     }
913 
SetDebugInfo(DebugInfoItem *debugInfo)914     void SetDebugInfo(DebugInfoItem *debugInfo)
915     {
916         debugInfo_ = debugInfo;
917     }
918 
GetDebugInfo()919     DebugInfoItem *GetDebugInfo()
920     {
921         return debugInfo_;
922     }
923 
AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)924     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
925     {
926         runtimeAnnotations_.push_back(runtimeAnnotation);
927     }
928 
AddAnnotation(AnnotationItem *annotation)929     void AddAnnotation(AnnotationItem *annotation)
930     {
931         annotations_.push_back(annotation);
932     }
933 
AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)934     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
935     {
936         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
937     }
938 
AddTypeAnnotation(AnnotationItem *typeAnnotation)939     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
940     {
941         typeAnnotations_.push_back(typeAnnotation);
942     }
943 
SetRuntimeParamAnnotationItem(ParamAnnotationsItem *annotations)944     void SetRuntimeParamAnnotationItem(ParamAnnotationsItem *annotations)
945     {
946         runtimeParamAnnotations_ = annotations;
947     }
948 
SetParamAnnotationItem(ParamAnnotationsItem *annotations)949     void SetParamAnnotationItem(ParamAnnotationsItem *annotations)
950     {
951         paramAnnotations_ = annotations;
952     }
953 
HasRuntimeParamAnnotations() const954     bool HasRuntimeParamAnnotations() const
955     {
956         return std::any_of(params_.cbegin(), params_.cend(),
957                            [](const MethodParamItem &item) { return item.HasRuntimeAnnotations(); });
958     }
959 
HasParamAnnotations() const960     bool HasParamAnnotations() const
961     {
962         return std::any_of(params_.cbegin(), params_.cend(),
963                            [](const MethodParamItem &item) { return item.HasAnnotations(); });
964     }
965 
GetCode() const966     CodeItem *GetCode() const
967     {
968         return code_;
969     }
970 
GetDebugInfo() const971     DebugInfoItem *GetDebugInfo() const
972     {
973         return debugInfo_;
974     }
975 
976     size_t CalculateSize() const override;
977 
978     bool Write(Writer *writer) override;
979 
980     ItemTypes GetItemType() const override
981     {
982         return ItemTypes::METHOD_ITEM;
983     }
984 
GetParams()985     std::vector<MethodParamItem> &GetParams()
986     {
987         return params_;
988     }
989 
GetRuntimeAnnotations()990     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
991     {
992         return &runtimeAnnotations_;
993     }
994 
GetAnnotations()995     std::vector<AnnotationItem *> *GetAnnotations()
996     {
997         return &annotations_;
998     }
999 
GetTypeAnnotations()1000     std::vector<AnnotationItem *> *GetTypeAnnotations()
1001     {
1002         return &typeAnnotations_;
1003     }
1004 
GetRuntimeTypeAnnotations()1005     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
1006     {
1007         return &runtimeTypeAnnotations_;
1008     }
1009 
SetProfileSize(size_t size)1010     void SetProfileSize(size_t size)
1011     {
1012         ASSERT(size <= MAX_PROFILE_SIZE);
1013         profileSize_ = size;
1014     }
1015 
GetProfileSize() const1016     size_t GetProfileSize() const
1017     {
1018         return profileSize_;
1019     }
1020 
1021 private:
1022     bool WriteRuntimeAnnotations(Writer *writer);
1023 
1024     bool WriteTypeAnnotations(Writer *writer);
1025 
1026     bool WriteTaggedData(Writer *writer);
1027 
1028     std::vector<MethodParamItem> params_;
1029 
1030     SourceLang sourceLang_ {SourceLang::PANDA_ASSEMBLY};
1031     CodeItem *code_ {nullptr};
1032     DebugInfoItem *debugInfo_ {nullptr};
1033     std::vector<AnnotationItem *> runtimeAnnotations_;
1034     std::vector<AnnotationItem *> annotations_;
1035     std::vector<AnnotationItem *> typeAnnotations_;
1036     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
1037     ParamAnnotationsItem *runtimeParamAnnotations_ {nullptr};
1038     ParamAnnotationsItem *paramAnnotations_ {nullptr};
1039     uint16_t profileSize_ {0};
1040 
1041 public:
1042     constexpr static auto MAX_PROFILE_SIZE = std::numeric_limits<decltype(profileSize_)>::max();
1043 };
1044 
1045 class BaseClassItem : public TypeItem {
1046 public:
GetNameItem()1047     StringItem *GetNameItem()
1048     {
1049         return &name_;
1050     }
1051 
GetNameItemData() const1052     const std::string &GetNameItemData() const
1053     {
1054         return name_.GetData();
1055     }
1056 
1057 protected:
BaseClassItem(const std::string &name)1058     explicit BaseClassItem(const std::string &name) : TypeItem(Type::TypeId::REFERENCE), name_(name) {}
1059 
1060     ~BaseClassItem() override = default;
1061 
1062     size_t CalculateSize() const override;
1063 
1064     void ComputeLayout() override;
1065 
1066     bool Write(Writer *writer) override;
1067 
1068     DEFAULT_MOVE_SEMANTIC(BaseClassItem);
1069     DEFAULT_COPY_SEMANTIC(BaseClassItem);
1070 
1071 private:
1072     StringItem name_;
1073 };
1074 
1075 class ClassItem : public BaseClassItem {
1076 public:
ClassItem(const std::string &name)1077     explicit ClassItem(const std::string &name) : BaseClassItem(name) {}
1078 
1079     ~ClassItem() override = default;
1080 
SetAccessFlags(uint32_t accessFlags)1081     void SetAccessFlags(uint32_t accessFlags)
1082     {
1083         accessFlags_ = accessFlags;
1084     }
1085 
SetSourceLang(SourceLang lang)1086     void SetSourceLang(SourceLang lang)
1087     {
1088         sourceLang_ = lang;
1089     }
1090 
SetSuperClass(BaseClassItem *superClass)1091     void SetSuperClass(BaseClassItem *superClass)
1092     {
1093         superClass_ = superClass;
1094     }
1095 
AddInterface(BaseClassItem *iface)1096     void AddInterface(BaseClassItem *iface)
1097     {
1098         AddIndexDependency(iface);
1099         ifaces_.push_back(iface);
1100     }
1101 
AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)1102     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
1103     {
1104         runtimeAnnotations_.push_back(runtimeAnnotation);
1105     }
1106 
AddAnnotation(AnnotationItem *annotation)1107     void AddAnnotation(AnnotationItem *annotation)
1108     {
1109         annotations_.push_back(annotation);
1110     }
1111 
AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)1112     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
1113     {
1114         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
1115     }
1116 
AddTypeAnnotation(AnnotationItem *typeAnnotation)1117     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
1118     {
1119         typeAnnotations_.push_back(typeAnnotation);
1120     }
1121 
1122     template <class... Args>
AddField(Args.... args)1123     FieldItem *AddField(Args... args)
1124     {
1125         fields_.emplace_back(std::make_unique<FieldItem>(this, std::forward<Args>(args)...));
1126         return fields_.back().get();
1127     }
1128 
1129     template <class... Args>
AddMethod(Args.... args)1130     MethodItem *AddMethod(Args... args)
1131     {
1132         // insert new method to set ordered by method name
1133         return methods_.insert(std::make_unique<MethodItem>(this, std::forward<Args>(args)...))->get();
1134     }
1135 
GetSourceFile() const1136     StringItem *GetSourceFile() const
1137     {
1138         return sourceFile_;
1139     }
1140 
SetSourceFile(StringItem *item)1141     void SetSourceFile(StringItem *item)
1142     {
1143         sourceFile_ = item;
1144     }
1145 
1146     size_t CalculateSizeWithoutFieldsAndMethods() const;
1147 
1148     size_t CalculateSize() const override;
1149 
1150     void ComputeLayout() override;
1151 
1152     bool Write(Writer *writer) override;
1153 
1154     ItemTypes GetItemType() const override
1155     {
1156         return ItemTypes::CLASS_ITEM;
1157     }
1158 
VisitFields(const VisitorCallBack &cb)1159     void VisitFields(const VisitorCallBack &cb)
1160     {
1161         for (auto &field : fields_) {
1162             if (!cb(field.get())) {
1163                 break;
1164             }
1165         }
1166     }
1167 
VisitMethods(const VisitorCallBack &cb)1168     void VisitMethods(const VisitorCallBack &cb)
1169     {
1170         for (auto &method : methods_) {
1171             if (!cb(method.get())) {
1172                 break;
1173             }
1174         }
1175     }
1176 
1177     void Visit(const VisitorCallBack &cb) override
1178     {
1179         VisitFields(cb);
1180         VisitMethods(cb);
1181     }
1182 
GetRuntimeAnnotations()1183     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
1184     {
1185         return &runtimeAnnotations_;
1186     }
1187 
GetAnnotations()1188     std::vector<AnnotationItem *> *GetAnnotations()
1189     {
1190         return &annotations_;
1191     }
1192 
GetTypeAnnotations()1193     std::vector<AnnotationItem *> *GetTypeAnnotations()
1194     {
1195         return &typeAnnotations_;
1196     }
1197 
GetRuntimeTypeAnnotations()1198     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
1199     {
1200         return &runtimeTypeAnnotations_;
1201     }
1202 
GetSourceLang() const1203     SourceLang GetSourceLang() const
1204     {
1205         return sourceLang_;
1206     }
1207 
GetAccessFlags() const1208     uint32_t GetAccessFlags() const
1209     {
1210         return accessFlags_;
1211     }
1212 
GetSuperClass() const1213     BaseClassItem *GetSuperClass() const
1214     {
1215         return superClass_;
1216     }
1217 
GetInterfaces() const1218     const std::vector<BaseClassItem *> &GetInterfaces() const
1219     {
1220         return ifaces_;
1221     }
1222 
1223     DEFAULT_MOVE_SEMANTIC(ClassItem);
1224     DEFAULT_COPY_SEMANTIC(ClassItem);
1225 
1226 private:
1227     struct MethodCompByName {
1228         using is_transparent = std::true_type;  // NOLINT(readability-identifier-naming)
1229 
operator ()ark::panda_file::ClassTag::ClassItem::MethodCompByName1230         bool operator()(const StringItem *str1, const StringItem *str2) const
1231         {
1232             if (str1->GetUtf16Len() == str2->GetUtf16Len()) {
1233                 return str1->GetData() < str2->GetData();
1234             }
1235             return str1->GetUtf16Len() < str2->GetUtf16Len();
1236         }
1237 
operator ()ark::panda_file::ClassTag::ClassItem::MethodCompByName1238         bool operator()(const StringItem *m1, const std::unique_ptr<MethodItem> &m2) const
1239         {
1240             return (*this)(m1, m2->GetNameItem());
1241         }
1242 
operator ()ark::panda_file::ClassTag::ClassItem::MethodCompByName1243         bool operator()(const std::unique_ptr<MethodItem> &m1, const StringItem *str2) const
1244         {
1245             return (*this)(m1->GetNameItem(), str2);
1246         }
1247 
operator ()ark::panda_file::ClassTag::ClassItem::MethodCompByName1248         bool operator()(const std::unique_ptr<MethodItem> &m1, const std::unique_ptr<MethodItem> &m2) const
1249         {
1250             return (*this)(m1->GetNameItem(), m2->GetNameItem());
1251         }
1252     };
1253 
1254     bool WriteIfaces(Writer *writer);
1255 
1256     bool WriteAnnotations(Writer *writer);
1257 
1258     bool WriteTaggedData(Writer *writer);
1259 
1260     BaseClassItem *superClass_ {nullptr};
1261     uint32_t accessFlags_ {0};
1262     SourceLang sourceLang_ {SourceLang::PANDA_ASSEMBLY};
1263     std::vector<BaseClassItem *> ifaces_;
1264     std::vector<AnnotationItem *> runtimeAnnotations_;
1265     std::vector<AnnotationItem *> annotations_;
1266     std::vector<AnnotationItem *> typeAnnotations_;
1267     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
1268     StringItem *sourceFile_ {nullptr};
1269     std::vector<std::unique_ptr<FieldItem>> fields_;
1270     std::multiset<std::unique_ptr<MethodItem>, MethodCompByName> methods_;
1271 
1272 public:
1273     using FindMethodIterator = typename std::multiset<std::unique_ptr<MethodItem>, MethodCompByName>::const_iterator;
1274 
FindMethod(StringItem *name) const1275     std::pair<FindMethodIterator, FindMethodIterator> FindMethod(StringItem *name) const
1276     {
1277         return methods_.equal_range(name);
1278     }
1279 };
1280 
1281 class ForeignClassItem : public BaseClassItem {
1282 public:
ForeignClassItem(const std::string &name)1283     explicit ForeignClassItem(const std::string &name) : BaseClassItem(name) {}
1284 
1285     ~ForeignClassItem() override = default;
1286 
1287     bool IsForeign() const override
1288     {
1289         return true;
1290     }
1291 
1292     ItemTypes GetItemType() const override
1293     {
1294         return ItemTypes::FOREIGN_CLASS_ITEM;
1295     }
1296 
1297     DEFAULT_MOVE_SEMANTIC(ForeignClassItem);
1298     DEFAULT_COPY_SEMANTIC(ForeignClassItem);
1299 };
1300 
1301 class ForeignFieldItem : public BaseFieldItem {
1302 public:
ForeignFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type)1303     ForeignFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type) : BaseFieldItem(cls, name, type) {}
1304 
1305     ~ForeignFieldItem() override = default;
1306 
1307     bool IsForeign() const override
1308     {
1309         return true;
1310     }
1311 
1312     ItemTypes GetItemType() const override
1313     {
1314         return ItemTypes::FOREIGN_FIELD_ITEM;
1315     }
1316 
1317     DEFAULT_MOVE_SEMANTIC(ForeignFieldItem);
1318     DEFAULT_COPY_SEMANTIC(ForeignFieldItem);
1319 };
1320 
1321 class ForeignMethodItem : public BaseMethodItem {
1322 public:
ForeignMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags)1323     ForeignMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags)
1324         : BaseMethodItem(cls, name, proto, accessFlags)
1325     {
1326     }
1327 
1328     ~ForeignMethodItem() override = default;
1329 
1330     bool IsForeign() const override
1331     {
1332         return true;
1333     }
1334 
1335     ItemTypes GetItemType() const override
1336     {
1337         return ItemTypes::FOREIGN_METHOD_ITEM;
1338     }
1339 
1340     DEFAULT_MOVE_SEMANTIC(ForeignMethodItem);
1341     DEFAULT_COPY_SEMANTIC(ForeignMethodItem);
1342 };
1343 
1344 class ProtoItem;
1345 
1346 class ParamAnnotationsItem : public BaseItem {
1347 public:
1348     ParamAnnotationsItem(MethodItem *method, bool isRuntimeAnnotations);
1349 
1350     ~ParamAnnotationsItem() override = default;
1351 
1352     ItemTypes GetItemType() const override
1353     {
1354         return ItemTypes::PARAM_ANNOTATIONS_ITEM;
1355     }
1356 
1357     size_t CalculateSize() const override;
1358 
1359     bool Write(Writer *writer) override;
1360 
1361     DEFAULT_MOVE_SEMANTIC(ParamAnnotationsItem);
1362     DEFAULT_COPY_SEMANTIC(ParamAnnotationsItem);
1363 
1364 private:
1365     std::vector<std::vector<AnnotationItem *>> annotations_;
1366 };
1367 
1368 class ProtoItem : public IndexedItem {
1369 public:
1370     ProtoItem(TypeItem *retType, const std::vector<MethodParamItem> &params);
1371 
1372     ~ProtoItem() override = default;
1373 
1374     DEFAULT_MOVE_SEMANTIC(ProtoItem);
1375     DEFAULT_COPY_SEMANTIC(ProtoItem);
1376 
1377     size_t CalculateSize() const override
1378     {
1379         size_t size = shorty_.size() * sizeof(uint16_t);
1380         size += referenceTypes_.size() * IDX_SIZE;
1381         return size;
1382     }
1383 
1384     bool Write(Writer *writer) override;
1385 
1386     ItemTypes GetItemType() const override
1387     {
1388         return ItemTypes::PROTO_ITEM;
1389     }
1390 
1391     IndexType GetIndexType() const override
1392     {
1393         return IndexType::PROTO;
1394     }
1395 
1396     size_t Alignment() override
1397     {
1398         return sizeof(uint16_t);
1399     }
1400 
GetShorty() const1401     const std::vector<uint16_t> &GetShorty() const
1402     {
1403         return shorty_;
1404     }
1405 
GetRefTypes() const1406     const std::vector<TypeItem *> &GetRefTypes() const
1407     {
1408         return referenceTypes_;
1409     }
1410 
1411 private:
1412     static constexpr size_t SHORTY_ELEM_SIZE = 4;
1413 
1414     void AddType(TypeItem *type, size_t *n);
1415 
1416     std::vector<uint16_t> shorty_;
1417     std::vector<TypeItem *> referenceTypes_;
1418 };
1419 
1420 class CodeItem : public BaseItem {
1421 public:
1422     class CatchBlock : public BaseItem {
1423     public:
CatchBlock(MethodItem *method, BaseClassItem *type, size_t handlerPc, size_t codeSize = 0)1424         CatchBlock(MethodItem *method, BaseClassItem *type, size_t handlerPc, size_t codeSize = 0)
1425             : method_(method), type_(type), handlerPc_(handlerPc), codeSize_(codeSize)
1426         {
1427         }
1428 
1429         ~CatchBlock() override = default;
1430 
1431         DEFAULT_MOVE_SEMANTIC(CatchBlock);
1432         DEFAULT_COPY_SEMANTIC(CatchBlock);
1433 
GetMethod() const1434         MethodItem *GetMethod() const
1435         {
1436             return method_;
1437         }
1438 
GetType() const1439         BaseClassItem *GetType() const
1440         {
1441             return type_;
1442         }
1443 
GetHandlerPc() const1444         size_t GetHandlerPc() const
1445         {
1446             return handlerPc_;
1447         }
1448 
GetCodeSize() const1449         size_t GetCodeSize() const
1450         {
1451             return codeSize_;
1452         }
1453 
1454         size_t CalculateSize() const override;
1455 
1456         bool Write(Writer *writer) override;
1457 
1458         ItemTypes GetItemType() const override
1459         {
1460             return ItemTypes::CATCH_BLOCK_ITEM;
1461         }
1462 
1463     private:
1464         MethodItem *method_;
1465         BaseClassItem *type_;
1466         size_t handlerPc_;
1467         size_t codeSize_;
1468     };
1469 
1470     class TryBlock : public BaseItem {
1471     public:
TryBlock(size_t startPc, size_t length, std::vector<CatchBlock> catchBlocks)1472         TryBlock(size_t startPc, size_t length, std::vector<CatchBlock> catchBlocks)
1473             : startPc_(startPc), length_(length), catchBlocks_(std::move(catchBlocks))
1474         {
1475         }
1476 
1477         ~TryBlock() override = default;
1478 
1479         DEFAULT_MOVE_SEMANTIC(TryBlock);
1480         DEFAULT_COPY_SEMANTIC(TryBlock);
1481 
GetStartPc() const1482         size_t GetStartPc() const
1483         {
1484             return startPc_;
1485         }
1486 
GetLength() const1487         size_t GetLength() const
1488         {
1489             return length_;
1490         }
1491 
GetCatchBlocks() const1492         std::vector<CatchBlock> GetCatchBlocks() const
1493         {
1494             return catchBlocks_;
1495         }
1496 
1497         size_t CalculateSizeWithoutCatchBlocks() const;
1498 
1499         void ComputeLayout() override;
1500 
1501         size_t CalculateSize() const override;
1502 
1503         bool Write(Writer *writer) override;
1504 
1505         ItemTypes GetItemType() const override
1506         {
1507             return ItemTypes::TRY_BLOCK_ITEM;
1508         }
1509 
1510     private:
1511         size_t startPc_;
1512         size_t length_;
1513         std::vector<CatchBlock> catchBlocks_;
1514     };
1515 
CodeItem(size_t numVregs, size_t numArgs, std::vector<uint8_t> instructions)1516     CodeItem(size_t numVregs, size_t numArgs, std::vector<uint8_t> instructions)
1517         : numVregs_(numVregs), numArgs_(numArgs), instructions_(std::move(instructions))
1518     {
1519     }
1520 
1521     CodeItem() = default;
1522 
1523     ~CodeItem() override = default;
1524 
SetNumVregs(size_t numVregs)1525     void SetNumVregs(size_t numVregs)
1526     {
1527         numVregs_ = numVregs;
1528     }
1529 
SetNumArgs(size_t numArgs)1530     void SetNumArgs(size_t numArgs)
1531     {
1532         numArgs_ = numArgs;
1533     }
1534 
GetInstructions()1535     std::vector<uint8_t> *GetInstructions()
1536     {
1537         return &instructions_;
1538     }
1539 
SetNumInstructions(size_t numIns)1540     void SetNumInstructions(size_t numIns)
1541     {
1542         numIns_ = numIns;
1543     }
1544 
GetNumInstructions() const1545     size_t GetNumInstructions() const
1546     {
1547         return numIns_;
1548     }
1549 
GetTryBlocks()1550     std::vector<TryBlock> GetTryBlocks()
1551     {
1552         return tryBlocks_;
1553     }
1554 
AddTryBlock(const TryBlock &tryBlock)1555     void AddTryBlock(const TryBlock &tryBlock)
1556     {
1557         tryBlocks_.push_back(tryBlock);
1558     }
1559 
1560     size_t CalculateSizeWithoutTryBlocks() const;
1561 
1562     void ComputeLayout() override;
1563 
1564     size_t CalculateSize() const override;
1565 
1566     size_t GetCodeSize() const;
1567 
1568     bool Write(Writer *writer) override;
1569 
1570     ItemTypes GetItemType() const override
1571     {
1572         return ItemTypes::CODE_ITEM;
1573     }
1574 
AddMethod(BaseMethodItem *method)1575     void AddMethod(BaseMethodItem *method)
1576     {
1577         methods_.emplace_back(method);
1578     }
1579 
GetMethodNames() const1580     std::vector<std::string> GetMethodNames() const
1581     {
1582         std::vector<std::string> names;
1583         for (const auto *method : methods_) {
1584             if (method == nullptr) {
1585                 continue;
1586             }
1587             std::string className;
1588             if (method->GetClassItem() != nullptr) {
1589                 className = method->GetClassItem()->GetNameItem()->GetData();
1590                 className.pop_back();          // remove '\0'
1591                 ASSERT(className.size() > 2);  // 2 - L and ;
1592                 className.erase(0, 1);
1593                 className.pop_back();
1594                 className.append("::");
1595             }
1596             className.append(method->GetNameItem()->GetData());
1597             className.pop_back();  // remove '\0'
1598             names.emplace_back(className);
1599         }
1600         return names;
1601     }
1602 
GetNumVregs()1603     size_t GetNumVregs()
1604     {
1605         return numVregs_;
1606     }
1607 
GetNumArgs()1608     size_t GetNumArgs()
1609     {
1610         return numArgs_;
1611     }
1612 
1613     DEFAULT_MOVE_SEMANTIC(CodeItem);
1614     DEFAULT_COPY_SEMANTIC(CodeItem);
1615 
1616 private:
1617     size_t numVregs_ {0};
1618     size_t numArgs_ {0};
1619     size_t numIns_ {0};
1620     std::vector<uint8_t> instructions_;
1621     std::vector<TryBlock> tryBlocks_;
1622     std::vector<BaseMethodItem *> methods_;
1623 };
1624 
1625 class ScalarValueItem;
1626 class ArrayValueItem;
1627 
1628 class ValueItem : public BaseItem {
1629 public:
1630     enum class Type { INTEGER, LONG, FLOAT, DOUBLE, ID, ARRAY };
1631 
ValueItem(Type type)1632     explicit ValueItem(Type type) : type_(type) {}
1633 
1634     ~ValueItem() override = default;
1635 
1636     DEFAULT_MOVE_SEMANTIC(ValueItem);
1637     DEFAULT_COPY_SEMANTIC(ValueItem);
1638 
GetType() const1639     Type GetType() const
1640     {
1641         return type_;
1642     }
1643 
IsArray() const1644     bool IsArray() const
1645     {
1646         return type_ == Type::ARRAY;
1647     }
1648 
Is32bit() const1649     bool Is32bit() const
1650     {
1651         return type_ == Type::INTEGER || type_ == Type::FLOAT || type_ == Type::ID;
1652     }
1653 
1654     ItemTypes GetItemType() const override
1655     {
1656         return ItemTypes::VALUE_ITEM;
1657     }
1658 
1659     ScalarValueItem *GetAsScalar();
1660 
1661     ArrayValueItem *GetAsArray();
1662 
1663 private:
1664     Type type_;
1665 };
1666 
1667 class ScalarValueItem : public ValueItem {
1668 public:
ScalarValueItem(uint32_t v)1669     explicit ScalarValueItem(uint32_t v) : ValueItem(Type::INTEGER), value_(v) {}
1670 
ScalarValueItem(uint64_t v)1671     explicit ScalarValueItem(uint64_t v) : ValueItem(Type::LONG), value_(v) {}
1672 
ScalarValueItem(float v)1673     explicit ScalarValueItem(float v) : ValueItem(Type::FLOAT), value_(v) {}
1674 
ScalarValueItem(double v)1675     explicit ScalarValueItem(double v) : ValueItem(Type::DOUBLE), value_(v) {}
1676 
ScalarValueItem(BaseItem *v)1677     explicit ScalarValueItem(BaseItem *v) : ValueItem(Type::ID), value_(v) {}
1678 
1679     ~ScalarValueItem() override = default;
1680 
1681     DEFAULT_MOVE_SEMANTIC(ScalarValueItem);
1682     DEFAULT_COPY_SEMANTIC(ScalarValueItem);
1683 
1684     template <class T>
GetValue() const1685     T GetValue() const
1686     {
1687         return std::get<T>(value_);
1688     }
1689 
1690     template <class T>
HasValue() const1691     bool HasValue() const
1692     {
1693         return std::holds_alternative<T>(value_);
1694     }
1695 
GetId() const1696     File::EntityId GetId() const
1697     {
1698         return File::EntityId(GetValue<BaseItem *>()->GetOffset());
1699     }
1700 
GetIdItem() const1701     BaseItem *GetIdItem() const
1702     {
1703         return GetValue<BaseItem *>();
1704     }
1705 
1706     size_t GetULeb128EncodedSize();
1707 
1708     size_t GetSLeb128EncodedSize();
1709 
1710     size_t CalculateSize() const override;
1711 
1712     size_t Alignment() override;
1713 
1714     bool Write(Writer *writer) override;
1715 
1716     bool WriteAsUleb128(Writer *writer);
1717 
1718 private:
1719     std::variant<uint32_t, uint64_t, float, double, BaseItem *> value_;
1720 };
1721 
1722 class ArrayValueItem : public ValueItem {
1723 public:
ArrayValueItem(panda_file::Type componentType, std::vector<ScalarValueItem> items)1724     ArrayValueItem(panda_file::Type componentType, std::vector<ScalarValueItem> items)
1725         : ValueItem(Type::ARRAY), componentType_(componentType), items_(std::move(items))
1726     {
1727     }
1728 
1729     ~ArrayValueItem() override = default;
1730 
1731     DEFAULT_MOVE_SEMANTIC(ArrayValueItem);
1732     DEFAULT_COPY_SEMANTIC(ArrayValueItem);
1733 
1734     size_t CalculateSize() const override;
1735 
1736     void ComputeLayout() override;
1737 
1738     bool Write(Writer *writer) override;
1739 
GetComponentType() const1740     panda_file::Type GetComponentType() const
1741     {
1742         return componentType_;
1743     }
1744 
GetItems() const1745     const std::vector<ScalarValueItem> &GetItems() const
1746     {
1747         return items_;
1748     }
1749 
1750 private:
1751     size_t GetComponentSize() const;
1752 
1753     panda_file::Type componentType_;
1754     std::vector<ScalarValueItem> items_;
1755 };
1756 
1757 class LiteralItem;
1758 class LiteralArrayItem;
1759 
1760 class LiteralItem : public BaseItem {
1761 public:
1762     enum class Type { B1, B2, B4, B8, STRING, METHOD };
1763 
LiteralItem(uint8_t v)1764     explicit LiteralItem(uint8_t v) : type_(Type::B1), value_(v) {}
1765 
LiteralItem(uint16_t v)1766     explicit LiteralItem(uint16_t v) : type_(Type::B2), value_(v) {}
1767 
LiteralItem(uint32_t v)1768     explicit LiteralItem(uint32_t v) : type_(Type::B4), value_(v) {}
1769 
LiteralItem(uint64_t v)1770     explicit LiteralItem(uint64_t v) : type_(Type::B8), value_(v) {}
1771 
LiteralItem(StringItem *v)1772     explicit LiteralItem(StringItem *v) : type_(Type::STRING), value_(v) {}
1773 
LiteralItem(MethodItem *v)1774     explicit LiteralItem(MethodItem *v) : type_(Type::METHOD), value_(v) {}
1775 
1776     ~LiteralItem() override = default;
1777 
1778     DEFAULT_MOVE_SEMANTIC(LiteralItem);
1779     DEFAULT_COPY_SEMANTIC(LiteralItem);
1780 
GetType() const1781     Type GetType() const
1782     {
1783         return type_;
1784     }
1785 
1786     ItemTypes GetItemType() const override
1787     {
1788         return ItemTypes::LITERAL_ITEM;
1789     }
1790 
1791     template <class T>
GetValue() const1792     T GetValue() const
1793     {
1794         return std::get<T>(value_);
1795     }
1796 
1797     size_t CalculateSize() const override;
1798 
1799     size_t Alignment() override;
1800 
GetId() const1801     File::EntityId GetId() const
1802     {
1803         return File::EntityId(GetValue<StringItem *>()->GetOffset());
1804     }
1805 
GetMethodId() const1806     File::EntityId GetMethodId() const
1807     {
1808         return File::EntityId(GetValue<MethodItem *>()->GetFileId());
1809     }
1810 
1811     bool Write(Writer *writer) override;
1812 
1813 private:
1814     Type type_;
1815     std::variant<uint8_t, uint16_t, uint32_t, uint64_t, StringItem *, MethodItem *> value_;
1816 };
1817 
1818 class LiteralArrayItem : public ValueItem {
1819 public:
LiteralArrayItem()1820     explicit LiteralArrayItem() : ValueItem(Type::ARRAY) {}
1821 
1822     ~LiteralArrayItem() override = default;
1823 
1824     DEFAULT_MOVE_SEMANTIC(LiteralArrayItem);
1825     DEFAULT_COPY_SEMANTIC(LiteralArrayItem);
1826 
1827     void AddItems(const std::vector<LiteralItem> &item);
1828 
GetItems() const1829     const std::vector<LiteralItem> &GetItems() const
1830     {
1831         return items_;
1832     }
1833 
1834     size_t CalculateSize() const override;
1835 
1836     void ComputeLayout() override;
1837 
1838     bool Write(Writer *writer) override;
1839 
1840     ItemTypes GetItemType() const override
1841     {
1842         return ItemTypes::LITERAL_ARRAY_ITEM;
1843     }
1844 
SetIndex(uint32_t index)1845     void SetIndex(uint32_t index)
1846     {
1847         index_ = index;
1848     }
1849 
GetIndex() const1850     uint32_t GetIndex() const
1851     {
1852         return index_;
1853     }
1854 
1855 private:
1856     std::vector<LiteralItem> items_;
1857     uint32_t index_ {0};
1858 };
1859 
1860 class AnnotationItem : public BaseItem {
1861 public:
1862     class Elem {
1863     public:
Elem(StringItem *name, ValueItem *value)1864         Elem(StringItem *name, ValueItem *value) : name_(name), value_(value)
1865         {
1866             value_->SetNeedsEmit(!value_->Is32bit());
1867         }
1868 
1869         ~Elem() = default;
1870 
1871         DEFAULT_MOVE_SEMANTIC(Elem);
1872         DEFAULT_COPY_SEMANTIC(Elem);
1873 
GetName() const1874         const StringItem *GetName() const
1875         {
1876             return name_;
1877         }
1878 
GetValue() const1879         ValueItem *GetValue() const
1880         {
1881             return value_;
1882         }
1883 
SetValue(ValueItem *item)1884         void SetValue(ValueItem *item)
1885         {
1886             value_ = item;
1887         }
1888 
1889     private:
1890         StringItem *name_;
1891         ValueItem *value_;
1892     };
1893 
1894     class Tag {
1895     public:
Tag(char item)1896         explicit Tag(char item) : item_(item) {}
1897 
1898         ~Tag() = default;
1899 
1900         DEFAULT_MOVE_SEMANTIC(Tag);
1901         DEFAULT_COPY_SEMANTIC(Tag);
1902 
GetItem() const1903         uint8_t GetItem() const
1904         {
1905             return item_;
1906         }
1907 
1908     private:
1909         uint8_t item_;
1910     };
1911 
AnnotationItem(BaseClassItem *cls, std::vector<Elem> elements, std::vector<Tag> tags)1912     AnnotationItem(BaseClassItem *cls, std::vector<Elem> elements, std::vector<Tag> tags)
1913         : class_(cls), elements_(std::move(elements)), tags_(std::move(tags))
1914     {
1915         AddIndexDependency(cls);
1916     }
1917 
1918     ~AnnotationItem() override = default;
1919 
1920     DEFAULT_MOVE_SEMANTIC(AnnotationItem);
1921     DEFAULT_COPY_SEMANTIC(AnnotationItem);
1922 
1923     size_t CalculateSize() const override;
1924 
1925     bool Write(Writer *writer) override;
1926 
1927     ItemTypes GetItemType() const override
1928     {
1929         return ItemTypes::ANNOTATION_ITEM;
1930     }
1931 
GetClassItem() const1932     BaseClassItem *GetClassItem() const
1933     {
1934         return class_;
1935     }
1936 
GetElements()1937     std::vector<Elem> *GetElements()
1938     {
1939         return &elements_;
1940     }
1941 
GetElements() const1942     const std::vector<Elem> *GetElements() const
1943     {
1944         return &elements_;
1945     }
1946 
SetElements(std::vector<Elem> &&elements)1947     void SetElements(std::vector<Elem> &&elements)
1948     {
1949         elements_ = std::move(elements);
1950     }
1951 
GetTags() const1952     const std::vector<Tag> &GetTags() const
1953     {
1954         return tags_;
1955     }
1956 
SetTags(std::vector<Tag> &&tags)1957     void SetTags(std::vector<Tag> &&tags)
1958     {
1959         tags_ = std::move(tags);
1960     }
1961 
1962 private:
1963     BaseClassItem *class_;
1964     std::vector<Elem> elements_;
1965     std::vector<Tag> tags_;
1966 };
1967 
1968 enum class MethodHandleType : uint8_t {
1969     PUT_STATIC = 0x00,
1970     GET_STATIC = 0x01,
1971     PUT_INSTANCE = 0x02,
1972     GET_INSTANCE = 0x03,
1973     INVOKE_STATIC = 0x04,
1974     INVOKE_INSTANCE = 0x05,
1975     INVOKE_CONSTRUCTOR = 0x06,
1976     INVOKE_DIRECT = 0x07,
1977     INVOKE_INTERFACE = 0x08
1978 };
1979 
1980 class MethodHandleItem : public BaseItem {
1981 public:
MethodHandleItem(MethodHandleType type, BaseItem *entity)1982     MethodHandleItem(MethodHandleType type, BaseItem *entity) : type_(type), entity_(entity) {}
1983 
1984     ~MethodHandleItem() override = default;
1985 
1986     DEFAULT_MOVE_SEMANTIC(MethodHandleItem);
1987     DEFAULT_COPY_SEMANTIC(MethodHandleItem);
1988 
1989     size_t CalculateSize() const override
1990     {
1991         return sizeof(uint8_t) + leb128::UnsignedEncodingSize(entity_->GetOffset());
1992     }
1993 
1994     bool Write(Writer *writer) override;
1995 
1996     ItemTypes GetItemType() const override
1997     {
1998         return ItemTypes::METHOD_HANDLE_ITEM;
1999     }
2000 
GetType() const2001     MethodHandleType GetType() const
2002     {
2003         return type_;
2004     }
2005 
2006 private:
2007     MethodHandleType type_;
2008     BaseItem *entity_;
2009 };
2010 
2011 enum class ArgumentType : uint8_t {
2012     INTEGER = 0x00,
2013     LONG = 0x01,
2014     FLOAT = 0x02,
2015     DOUBLE = 0x03,
2016     STRING = 0x04,
2017     CLASS = 0x05,
2018     METHOD_HANDLE = 0x06,
2019     METHOD_TYPE = 0x07
2020 };
2021 
2022 }  // namespace ark::panda_file
2023 
2024 #endif  // LIBPANDAFILE_FILE_ITEMS_H_
2025