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