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 ¶meters_; 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> ¶ms); 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