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 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 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()159 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()173 virtual bool IsForeign() const 174 { 175 return false; 176 } 177 GetOffset()178 uint32_t GetOffset() const 179 { 180 return offset_; 181 } 182 GetFileId()183 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()193 bool NeedsEmit() const 194 { 195 return needsEmit_; 196 } 197 SetNeedsEmit(bool needsEmit)198 void SetNeedsEmit(bool needsEmit) 199 { 200 needsEmit_ = needsEmit; 201 } 202 GetIndexDependencies()203 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()219 uint32_t GetOrderIndex() const 220 { 221 return order_; 222 } 223 HasOrderIndex()224 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(std::ostream & os)235 virtual void Dump([[maybe_unused]] std::ostream &os) const {} 236 Visit(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()244 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()254 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)275 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)282 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()309 size_t GetRefCount() const 310 { 311 return refCount_; 312 } 313 GetIndexType()314 virtual IndexType GetIndexType() const 315 { 316 return IndexType::NONE; 317 } 318 GetItemAllocId()319 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)331 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)339 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()379 Type GetType() const 380 { 381 return type_; 382 } 383 GetIndexType()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 CalculateSize()409 size_t CalculateSize() const override 410 { 411 return 0; 412 } 413 Write(Writer * writer)414 bool Write([[maybe_unused]] Writer *writer) override 415 { 416 return true; 417 } 418 GetItemType()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 GetItemType()440 ItemTypes GetItemType() const override 441 { 442 return ItemTypes::STRING_ITEM; 443 } 444 GetData()445 const std::string &GetData() const 446 { 447 return str_; 448 } 449 GetUtf16Len()450 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: GetIndexType()472 IndexType GetIndexType() const override 473 { 474 return IndexType::FIELD; 475 } 476 GetNameItem()477 StringItem *GetNameItem() const 478 { 479 return name_; 480 } 481 GetTypeItem()482 TypeItem *GetTypeItem() const 483 { 484 return type_; 485 } 486 GetClassItem()487 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 PANDA_PUBLIC_API BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type); 499 500 PANDA_PUBLIC_API size_t CalculateSize() const override; 501 502 PANDA_PUBLIC_API 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 PANDA_PUBLIC_API FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags); 513 514 ~FieldItem() override = default; 515 516 PANDA_PUBLIC_API void SetValue(ValueItem *value); 517 GetValue()518 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 GetItemType()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()572 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 PANDA_PUBLIC_API void EmitEnd(); 627 628 PANDA_PUBLIC_API void EmitAdvancePc(std::vector<uint8_t> *constantPool, uint32_t value); 629 630 PANDA_PUBLIC_API void EmitAdvanceLine(std::vector<uint8_t> *constantPool, int32_t value); 631 632 PANDA_PUBLIC_API void EmitColumn(std::vector<uint8_t> *constantPool, uint32_t pcInc, uint32_t column); 633 634 PANDA_PUBLIC_API void EmitStartLocal(std::vector<uint8_t> *constantPool, int32_t registerNumber, StringItem *name, 635 StringItem *type); 636 637 PANDA_PUBLIC_API void EmitStartLocalExtended(std::vector<uint8_t> *constantPool, int32_t registerNumber, 638 StringItem *name, StringItem *type, StringItem *typeSignature); 639 640 PANDA_PUBLIC_API void EmitEndLocal(int32_t registerNumber); 641 642 void EmitRestartLocal(int32_t registerNumber); 643 644 PANDA_PUBLIC_API bool EmitSpecialOpcode(uint32_t pcInc, int32_t lineInc); 645 646 void EmitPrologueEnd(); 647 648 void EmitEpilogueBegin(); 649 650 PANDA_PUBLIC_API void EmitSetFile(std::vector<uint8_t> *constantPool, StringItem *sourceFile); 651 652 PANDA_PUBLIC_API void EmitSetSourceCode(std::vector<uint8_t> *constantPool, StringItem *sourceCode); 653 654 void EmitOpcode(Opcode opcode); 655 Empty()656 virtual bool Empty() const 657 { 658 return true; 659 } 660 661 protected: EmitOpcode(uint8_t opcode)662 virtual void EmitOpcode([[maybe_unused]] uint8_t opcode) {} EmitRegister(int32_t registerNumber)663 virtual void EmitRegister([[maybe_unused]] int32_t registerNumber) {} 664 665 static void EmitUleb128(std::vector<uint8_t> *data, uint32_t value); 666 667 static void EmitSleb128(std::vector<uint8_t> *data, int32_t value); 668 }; 669 670 // NOLINTNEXTLINE(fuchsia-multiple-inheritance) 671 class LineNumberProgramItem final : public IndexedItem, public LineNumberProgramItemBase { 672 public: 673 bool Write(Writer *writer) override; 674 675 size_t CalculateSize() const override; 676 GetItemType()677 ItemTypes GetItemType() const override 678 { 679 return ItemTypes::LINE_NUMBER_PROGRAM_ITEM; 680 } 681 Empty()682 bool Empty() const override 683 { 684 return GetData().empty(); 685 } 686 GetData()687 const std::vector<uint8_t> &GetData() const 688 { 689 return data_; 690 } 691 GetIndexType()692 IndexType GetIndexType() const override 693 { 694 return IndexType::LINE_NUMBER_PROG; 695 } 696 697 void SetData(std::vector<uint8_t> &&data); 698 699 private: 700 void EmitOpcode(uint8_t opcode) override; 701 void EmitRegister(int32_t registerNumber) override; 702 703 std::vector<uint8_t> data_; 704 }; 705 706 class PANDA_PUBLIC_API DebugInfoItem : public BaseItem { 707 public: DebugInfoItem(LineNumberProgramItem * item)708 explicit DebugInfoItem(LineNumberProgramItem *item) : program_(item) {} 709 710 ~DebugInfoItem() override = default; 711 712 DEFAULT_MOVE_SEMANTIC(DebugInfoItem); 713 DEFAULT_COPY_SEMANTIC(DebugInfoItem); 714 GetLineNumber()715 size_t GetLineNumber() const 716 { 717 return lineNum_; 718 } 719 SetLineNumber(size_t lineNum)720 void SetLineNumber(size_t lineNum) 721 { 722 lineNum_ = lineNum; 723 } 724 GetLineNumberProgram()725 LineNumberProgramItem *GetLineNumberProgram() const 726 { 727 return program_; 728 } 729 SetLineNumberProgram(LineNumberProgramItem * program)730 void SetLineNumberProgram(LineNumberProgramItem *program) 731 { 732 ASSERT(program->GetOffset() != 0); 733 program_ = program; 734 } 735 AddParameter(StringItem * name)736 void AddParameter(StringItem *name) 737 { 738 parameters_.push_back(name); 739 } 740 GetParameters()741 const std::vector<StringItem *> *GetParameters() const 742 { 743 return ¶meters_; 744 } 745 GetConstantPool()746 std::vector<uint8_t> *GetConstantPool() 747 { 748 return &constantPool_; 749 } 750 751 size_t CalculateSize() const override; 752 753 bool Write(Writer *writer) override; 754 GetItemType()755 ItemTypes GetItemType() const override 756 { 757 return ItemTypes::DEBUG_INFO_ITEM; 758 } 759 760 void Dump(std::ostream &os) const override; 761 762 private: 763 size_t lineNum_ {0}; 764 LineNumberProgramItem *program_; 765 std::vector<uint8_t> constantPool_; 766 std::vector<StringItem *> parameters_; 767 }; 768 769 class BaseMethodItem : public IndexedItem { 770 public: GetProto()771 ProtoItem *GetProto() const 772 { 773 return proto_; 774 } 775 IsStatic()776 bool IsStatic() const 777 { 778 return (accessFlags_ & ACC_STATIC) != 0; 779 } 780 GetIndexType()781 IndexType GetIndexType() const override 782 { 783 return IndexType::METHOD; 784 } 785 GetNameItem()786 StringItem *GetNameItem() const 787 { 788 return name_; 789 } 790 GetClassItem()791 BaseClassItem *GetClassItem() const 792 { 793 return class_; 794 } 795 GetAccessFlags()796 uint32_t GetAccessFlags() const 797 { 798 return accessFlags_; 799 } 800 801 ~BaseMethodItem() override = default; 802 803 DEFAULT_MOVE_SEMANTIC(BaseMethodItem); 804 DEFAULT_COPY_SEMANTIC(BaseMethodItem); 805 806 protected: 807 PANDA_PUBLIC_API BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags); 808 809 PANDA_PUBLIC_API size_t CalculateSize() const override; 810 811 PANDA_PUBLIC_API bool Write(Writer *writer) override; 812 813 private: 814 BaseClassItem *class_; 815 StringItem *name_; 816 ProtoItem *proto_; 817 uint32_t accessFlags_; 818 }; 819 820 class MethodParamItem { 821 public: MethodParamItem(TypeItem * type)822 explicit MethodParamItem(TypeItem *type) : type_(type) {} 823 824 ~MethodParamItem() = default; 825 826 DEFAULT_MOVE_SEMANTIC(MethodParamItem); 827 DEFAULT_COPY_SEMANTIC(MethodParamItem); 828 AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)829 void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation) 830 { 831 runtimeAnnotations_.push_back(runtimeAnnotation); 832 } 833 AddAnnotation(AnnotationItem * annotation)834 void AddAnnotation(AnnotationItem *annotation) 835 { 836 annotations_.push_back(annotation); 837 } 838 AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)839 void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation) 840 { 841 runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation); 842 } 843 AddTypeAnnotation(AnnotationItem * typeAnnotation)844 void AddTypeAnnotation(AnnotationItem *typeAnnotation) 845 { 846 typeAnnotations_.push_back(typeAnnotation); 847 } 848 GetType()849 TypeItem *GetType() const 850 { 851 return type_; 852 } 853 GetRuntimeAnnotations()854 const std::vector<AnnotationItem *> &GetRuntimeAnnotations() const 855 { 856 return runtimeAnnotations_; 857 } 858 GetAnnotations()859 const std::vector<AnnotationItem *> &GetAnnotations() const 860 { 861 return annotations_; 862 } 863 GetRuntimeTypeAnnotations()864 const std::vector<AnnotationItem *> &GetRuntimeTypeAnnotations() const 865 { 866 return runtimeTypeAnnotations_; 867 } 868 GetTypeAnnotations()869 const std::vector<AnnotationItem *> &GetTypeAnnotations() const 870 { 871 return typeAnnotations_; 872 } 873 HasAnnotations()874 bool HasAnnotations() const 875 { 876 return !annotations_.empty(); 877 } 878 HasRuntimeAnnotations()879 bool HasRuntimeAnnotations() const 880 { 881 return !runtimeAnnotations_.empty(); 882 } 883 884 private: 885 TypeItem *type_; 886 std::vector<AnnotationItem *> runtimeAnnotations_; 887 std::vector<AnnotationItem *> annotations_; 888 std::vector<AnnotationItem *> typeAnnotations_; 889 std::vector<AnnotationItem *> runtimeTypeAnnotations_; 890 }; 891 892 class ParamAnnotationsItem; 893 class BaseClassItem; 894 895 class MethodItem : public BaseMethodItem { 896 public: 897 PANDA_PUBLIC_API MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags, 898 std::vector<MethodParamItem> params); 899 900 ~MethodItem() override = default; 901 902 DEFAULT_MOVE_SEMANTIC(MethodItem); 903 DEFAULT_COPY_SEMANTIC(MethodItem); 904 SetSourceLang(SourceLang lang)905 void SetSourceLang(SourceLang lang) 906 { 907 sourceLang_ = lang; 908 } 909 SetCode(CodeItem * code)910 void SetCode(CodeItem *code) 911 { 912 code_ = code; 913 } 914 SetDebugInfo(DebugInfoItem * debugInfo)915 void SetDebugInfo(DebugInfoItem *debugInfo) 916 { 917 debugInfo_ = debugInfo; 918 } 919 GetDebugInfo()920 DebugInfoItem *GetDebugInfo() 921 { 922 return debugInfo_; 923 } 924 AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)925 void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation) 926 { 927 runtimeAnnotations_.push_back(runtimeAnnotation); 928 } 929 AddAnnotation(AnnotationItem * annotation)930 void AddAnnotation(AnnotationItem *annotation) 931 { 932 annotations_.push_back(annotation); 933 } 934 AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)935 void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation) 936 { 937 runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation); 938 } 939 AddTypeAnnotation(AnnotationItem * typeAnnotation)940 void AddTypeAnnotation(AnnotationItem *typeAnnotation) 941 { 942 typeAnnotations_.push_back(typeAnnotation); 943 } 944 SetRuntimeParamAnnotationItem(ParamAnnotationsItem * annotations)945 void SetRuntimeParamAnnotationItem(ParamAnnotationsItem *annotations) 946 { 947 runtimeParamAnnotations_ = annotations; 948 } 949 SetParamAnnotationItem(ParamAnnotationsItem * annotations)950 void SetParamAnnotationItem(ParamAnnotationsItem *annotations) 951 { 952 paramAnnotations_ = annotations; 953 } 954 HasRuntimeParamAnnotations()955 bool HasRuntimeParamAnnotations() const 956 { 957 return std::any_of(params_.cbegin(), params_.cend(), 958 [](const MethodParamItem &item) { return item.HasRuntimeAnnotations(); }); 959 } 960 HasParamAnnotations()961 bool HasParamAnnotations() const 962 { 963 return std::any_of(params_.cbegin(), params_.cend(), 964 [](const MethodParamItem &item) { return item.HasAnnotations(); }); 965 } 966 GetCode()967 CodeItem *GetCode() const 968 { 969 return code_; 970 } 971 GetDebugInfo()972 DebugInfoItem *GetDebugInfo() const 973 { 974 return debugInfo_; 975 } 976 977 size_t CalculateSize() const override; 978 979 bool Write(Writer *writer) override; 980 GetItemType()981 ItemTypes GetItemType() const override 982 { 983 return ItemTypes::METHOD_ITEM; 984 } 985 GetParams()986 std::vector<MethodParamItem> &GetParams() 987 { 988 return params_; 989 } 990 GetRuntimeAnnotations()991 std::vector<AnnotationItem *> *GetRuntimeAnnotations() 992 { 993 return &runtimeAnnotations_; 994 } 995 GetAnnotations()996 std::vector<AnnotationItem *> *GetAnnotations() 997 { 998 return &annotations_; 999 } 1000 GetTypeAnnotations()1001 std::vector<AnnotationItem *> *GetTypeAnnotations() 1002 { 1003 return &typeAnnotations_; 1004 } 1005 GetRuntimeTypeAnnotations()1006 std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations() 1007 { 1008 return &runtimeTypeAnnotations_; 1009 } 1010 SetProfileSize(size_t size)1011 void SetProfileSize(size_t size) 1012 { 1013 ASSERT(size <= MAX_PROFILE_SIZE); 1014 profileSize_ = size; 1015 } 1016 GetProfileSize()1017 size_t GetProfileSize() const 1018 { 1019 return profileSize_; 1020 } 1021 1022 private: 1023 bool WriteRuntimeAnnotations(Writer *writer); 1024 1025 bool WriteTypeAnnotations(Writer *writer); 1026 1027 bool WriteTaggedData(Writer *writer); 1028 1029 std::vector<MethodParamItem> params_; 1030 1031 SourceLang sourceLang_ {SourceLang::PANDA_ASSEMBLY}; 1032 CodeItem *code_ {nullptr}; 1033 DebugInfoItem *debugInfo_ {nullptr}; 1034 std::vector<AnnotationItem *> runtimeAnnotations_; 1035 std::vector<AnnotationItem *> annotations_; 1036 std::vector<AnnotationItem *> typeAnnotations_; 1037 std::vector<AnnotationItem *> runtimeTypeAnnotations_; 1038 ParamAnnotationsItem *runtimeParamAnnotations_ {nullptr}; 1039 ParamAnnotationsItem *paramAnnotations_ {nullptr}; 1040 uint16_t profileSize_ {0}; 1041 1042 public: 1043 constexpr static auto MAX_PROFILE_SIZE = std::numeric_limits<decltype(profileSize_)>::max(); 1044 }; 1045 1046 class BaseClassItem : public TypeItem { 1047 public: GetNameItem()1048 StringItem *GetNameItem() 1049 { 1050 return &name_; 1051 } 1052 GetNameItemData()1053 const std::string &GetNameItemData() const 1054 { 1055 return name_.GetData(); 1056 } 1057 1058 protected: BaseClassItem(const std::string & name)1059 explicit BaseClassItem(const std::string &name) : TypeItem(Type::TypeId::REFERENCE), name_(name) {} 1060 1061 ~BaseClassItem() override = default; 1062 1063 size_t CalculateSize() const override; 1064 1065 void ComputeLayout() override; 1066 1067 bool Write(Writer *writer) override; 1068 1069 DEFAULT_MOVE_SEMANTIC(BaseClassItem); 1070 DEFAULT_COPY_SEMANTIC(BaseClassItem); 1071 1072 private: 1073 StringItem name_; 1074 }; 1075 1076 class ClassItem : public BaseClassItem { 1077 public: ClassItem(const std::string & name)1078 explicit ClassItem(const std::string &name) : BaseClassItem(name) {} 1079 1080 ~ClassItem() override = default; 1081 SetAccessFlags(uint32_t accessFlags)1082 void SetAccessFlags(uint32_t accessFlags) 1083 { 1084 accessFlags_ = accessFlags; 1085 } 1086 SetSourceLang(SourceLang lang)1087 void SetSourceLang(SourceLang lang) 1088 { 1089 sourceLang_ = lang; 1090 } 1091 SetSuperClass(BaseClassItem * superClass)1092 void SetSuperClass(BaseClassItem *superClass) 1093 { 1094 superClass_ = superClass; 1095 } 1096 AddInterface(BaseClassItem * iface)1097 void AddInterface(BaseClassItem *iface) 1098 { 1099 AddIndexDependency(iface); 1100 ifaces_.push_back(iface); 1101 } 1102 AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)1103 void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation) 1104 { 1105 runtimeAnnotations_.push_back(runtimeAnnotation); 1106 } 1107 AddAnnotation(AnnotationItem * annotation)1108 void AddAnnotation(AnnotationItem *annotation) 1109 { 1110 annotations_.push_back(annotation); 1111 } 1112 AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)1113 void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation) 1114 { 1115 runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation); 1116 } 1117 AddTypeAnnotation(AnnotationItem * typeAnnotation)1118 void AddTypeAnnotation(AnnotationItem *typeAnnotation) 1119 { 1120 typeAnnotations_.push_back(typeAnnotation); 1121 } 1122 1123 template <class... Args> AddField(Args...args)1124 FieldItem *AddField(Args... args) 1125 { 1126 fields_.emplace_back(std::make_unique<FieldItem>(this, std::forward<Args>(args)...)); 1127 return fields_.back().get(); 1128 } 1129 1130 template <class... Args> AddMethod(Args...args)1131 MethodItem *AddMethod(Args... args) 1132 { 1133 // insert new method to set ordered by method name 1134 return methods_.insert(std::make_unique<MethodItem>(this, std::forward<Args>(args)...))->get(); 1135 } 1136 GetSourceFile()1137 StringItem *GetSourceFile() const 1138 { 1139 return sourceFile_; 1140 } 1141 SetSourceFile(StringItem * item)1142 void SetSourceFile(StringItem *item) 1143 { 1144 sourceFile_ = item; 1145 } 1146 1147 size_t CalculateSizeWithoutFieldsAndMethods() const; 1148 1149 size_t CalculateSize() const override; 1150 1151 void ComputeLayout() override; 1152 1153 bool Write(Writer *writer) override; 1154 GetItemType()1155 ItemTypes GetItemType() const override 1156 { 1157 return ItemTypes::CLASS_ITEM; 1158 } 1159 VisitFields(const VisitorCallBack & cb)1160 void VisitFields(const VisitorCallBack &cb) 1161 { 1162 for (auto &field : fields_) { 1163 if (!cb(field.get())) { 1164 break; 1165 } 1166 } 1167 } 1168 VisitMethods(const VisitorCallBack & cb)1169 void VisitMethods(const VisitorCallBack &cb) 1170 { 1171 for (auto &method : methods_) { 1172 if (!cb(method.get())) { 1173 break; 1174 } 1175 } 1176 } 1177 Visit(const VisitorCallBack & cb)1178 void Visit(const VisitorCallBack &cb) override 1179 { 1180 VisitFields(cb); 1181 VisitMethods(cb); 1182 } 1183 GetRuntimeAnnotations()1184 std::vector<AnnotationItem *> *GetRuntimeAnnotations() 1185 { 1186 return &runtimeAnnotations_; 1187 } 1188 GetAnnotations()1189 std::vector<AnnotationItem *> *GetAnnotations() 1190 { 1191 return &annotations_; 1192 } 1193 GetTypeAnnotations()1194 std::vector<AnnotationItem *> *GetTypeAnnotations() 1195 { 1196 return &typeAnnotations_; 1197 } 1198 GetRuntimeTypeAnnotations()1199 std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations() 1200 { 1201 return &runtimeTypeAnnotations_; 1202 } 1203 GetSourceLang()1204 SourceLang GetSourceLang() const 1205 { 1206 return sourceLang_; 1207 } 1208 GetAccessFlags()1209 uint32_t GetAccessFlags() const 1210 { 1211 return accessFlags_; 1212 } 1213 GetSuperClass()1214 BaseClassItem *GetSuperClass() const 1215 { 1216 return superClass_; 1217 } 1218 GetInterfaces()1219 const std::vector<BaseClassItem *> &GetInterfaces() const 1220 { 1221 return ifaces_; 1222 } 1223 1224 DEFAULT_MOVE_SEMANTIC(ClassItem); 1225 DEFAULT_COPY_SEMANTIC(ClassItem); 1226 1227 private: 1228 struct MethodCompByName { 1229 using is_transparent = std::true_type; // NOLINT(readability-identifier-naming) 1230 operatorMethodCompByName1231 bool operator()(const StringItem *str1, const StringItem *str2) const 1232 { 1233 if (str1->GetUtf16Len() == str2->GetUtf16Len()) { 1234 return str1->GetData() < str2->GetData(); 1235 } 1236 return str1->GetUtf16Len() < str2->GetUtf16Len(); 1237 } 1238 operatorMethodCompByName1239 bool operator()(const StringItem *m1, const std::unique_ptr<MethodItem> &m2) const 1240 { 1241 return (*this)(m1, m2->GetNameItem()); 1242 } 1243 operatorMethodCompByName1244 bool operator()(const std::unique_ptr<MethodItem> &m1, const StringItem *str2) const 1245 { 1246 return (*this)(m1->GetNameItem(), str2); 1247 } 1248 operatorMethodCompByName1249 bool operator()(const std::unique_ptr<MethodItem> &m1, const std::unique_ptr<MethodItem> &m2) const 1250 { 1251 return (*this)(m1->GetNameItem(), m2->GetNameItem()); 1252 } 1253 }; 1254 1255 bool WriteIfaces(Writer *writer); 1256 1257 bool WriteAnnotations(Writer *writer); 1258 1259 bool WriteTaggedData(Writer *writer); 1260 1261 BaseClassItem *superClass_ {nullptr}; 1262 uint32_t accessFlags_ {0}; 1263 SourceLang sourceLang_ {SourceLang::PANDA_ASSEMBLY}; 1264 std::vector<BaseClassItem *> ifaces_; 1265 std::vector<AnnotationItem *> runtimeAnnotations_; 1266 std::vector<AnnotationItem *> annotations_; 1267 std::vector<AnnotationItem *> typeAnnotations_; 1268 std::vector<AnnotationItem *> runtimeTypeAnnotations_; 1269 StringItem *sourceFile_ {nullptr}; 1270 std::vector<std::unique_ptr<FieldItem>> fields_; 1271 std::multiset<std::unique_ptr<MethodItem>, MethodCompByName> methods_; 1272 1273 public: 1274 using FindMethodIterator = typename std::multiset<std::unique_ptr<MethodItem>, MethodCompByName>::const_iterator; 1275 FindMethod(StringItem * name)1276 std::pair<FindMethodIterator, FindMethodIterator> FindMethod(StringItem *name) const 1277 { 1278 return methods_.equal_range(name); 1279 } 1280 }; 1281 1282 class ForeignClassItem : public BaseClassItem { 1283 public: ForeignClassItem(const std::string & name)1284 explicit ForeignClassItem(const std::string &name) : BaseClassItem(name) {} 1285 1286 ~ForeignClassItem() override = default; 1287 IsForeign()1288 bool IsForeign() const override 1289 { 1290 return true; 1291 } 1292 GetItemType()1293 ItemTypes GetItemType() const override 1294 { 1295 return ItemTypes::FOREIGN_CLASS_ITEM; 1296 } 1297 1298 DEFAULT_MOVE_SEMANTIC(ForeignClassItem); 1299 DEFAULT_COPY_SEMANTIC(ForeignClassItem); 1300 }; 1301 1302 class ForeignFieldItem : public BaseFieldItem { 1303 public: ForeignFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type)1304 ForeignFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type) : BaseFieldItem(cls, name, type) {} 1305 1306 ~ForeignFieldItem() override = default; 1307 IsForeign()1308 bool IsForeign() const override 1309 { 1310 return true; 1311 } 1312 GetItemType()1313 ItemTypes GetItemType() const override 1314 { 1315 return ItemTypes::FOREIGN_FIELD_ITEM; 1316 } 1317 1318 DEFAULT_MOVE_SEMANTIC(ForeignFieldItem); 1319 DEFAULT_COPY_SEMANTIC(ForeignFieldItem); 1320 }; 1321 1322 class ForeignMethodItem : public BaseMethodItem { 1323 public: ForeignMethodItem(BaseClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t accessFlags)1324 ForeignMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags) 1325 : BaseMethodItem(cls, name, proto, accessFlags) 1326 { 1327 } 1328 1329 ~ForeignMethodItem() override = default; 1330 IsForeign()1331 bool IsForeign() const override 1332 { 1333 return true; 1334 } 1335 GetItemType()1336 ItemTypes GetItemType() const override 1337 { 1338 return ItemTypes::FOREIGN_METHOD_ITEM; 1339 } 1340 1341 DEFAULT_MOVE_SEMANTIC(ForeignMethodItem); 1342 DEFAULT_COPY_SEMANTIC(ForeignMethodItem); 1343 }; 1344 1345 class ProtoItem; 1346 1347 class ParamAnnotationsItem : public BaseItem { 1348 public: 1349 PANDA_PUBLIC_API ParamAnnotationsItem(MethodItem *method, bool isRuntimeAnnotations); 1350 1351 ~ParamAnnotationsItem() override = default; 1352 GetItemType()1353 ItemTypes GetItemType() const override 1354 { 1355 return ItemTypes::PARAM_ANNOTATIONS_ITEM; 1356 } 1357 1358 size_t CalculateSize() const override; 1359 1360 bool Write(Writer *writer) override; 1361 1362 DEFAULT_MOVE_SEMANTIC(ParamAnnotationsItem); 1363 DEFAULT_COPY_SEMANTIC(ParamAnnotationsItem); 1364 1365 private: 1366 std::vector<std::vector<AnnotationItem *>> annotations_; 1367 }; 1368 1369 class ProtoItem : public IndexedItem { 1370 public: 1371 ProtoItem(TypeItem *retType, const std::vector<MethodParamItem> ¶ms); 1372 1373 ~ProtoItem() override = default; 1374 1375 DEFAULT_MOVE_SEMANTIC(ProtoItem); 1376 DEFAULT_COPY_SEMANTIC(ProtoItem); 1377 CalculateSize()1378 size_t CalculateSize() const override 1379 { 1380 size_t size = shorty_.size() * sizeof(uint16_t); 1381 size += referenceTypes_.size() * IDX_SIZE; 1382 return size; 1383 } 1384 1385 bool Write(Writer *writer) override; 1386 GetItemType()1387 ItemTypes GetItemType() const override 1388 { 1389 return ItemTypes::PROTO_ITEM; 1390 } 1391 GetIndexType()1392 IndexType GetIndexType() const override 1393 { 1394 return IndexType::PROTO; 1395 } 1396 Alignment()1397 size_t Alignment() override 1398 { 1399 return sizeof(uint16_t); 1400 } 1401 GetShorty()1402 const std::vector<uint16_t> &GetShorty() const 1403 { 1404 return shorty_; 1405 } 1406 GetRefTypes()1407 const std::vector<TypeItem *> &GetRefTypes() const 1408 { 1409 return referenceTypes_; 1410 } 1411 1412 private: 1413 static constexpr size_t SHORTY_ELEM_SIZE = 4; 1414 1415 void AddType(TypeItem *type, size_t *n); 1416 1417 std::vector<uint16_t> shorty_; 1418 std::vector<TypeItem *> referenceTypes_; 1419 }; 1420 1421 class PANDA_PUBLIC_API CodeItem : public BaseItem { 1422 public: 1423 class PANDA_PUBLIC_API CatchBlock : public BaseItem { 1424 public: 1425 CatchBlock(MethodItem *method, BaseClassItem *type, size_t handlerPc, size_t codeSize = 0) method_(method)1426 : method_(method), type_(type), handlerPc_(handlerPc), codeSize_(codeSize) 1427 { 1428 } 1429 1430 ~CatchBlock() override = default; 1431 1432 DEFAULT_MOVE_SEMANTIC(CatchBlock); 1433 DEFAULT_COPY_SEMANTIC(CatchBlock); 1434 GetMethod()1435 MethodItem *GetMethod() const 1436 { 1437 return method_; 1438 } 1439 GetType()1440 BaseClassItem *GetType() const 1441 { 1442 return type_; 1443 } 1444 GetHandlerPc()1445 size_t GetHandlerPc() const 1446 { 1447 return handlerPc_; 1448 } 1449 GetCodeSize()1450 size_t GetCodeSize() const 1451 { 1452 return codeSize_; 1453 } 1454 1455 size_t CalculateSize() const override; 1456 1457 bool Write(Writer *writer) override; 1458 GetItemType()1459 ItemTypes GetItemType() const override 1460 { 1461 return ItemTypes::CATCH_BLOCK_ITEM; 1462 } 1463 1464 private: 1465 MethodItem *method_; 1466 BaseClassItem *type_; 1467 size_t handlerPc_; 1468 size_t codeSize_; 1469 }; 1470 1471 class PANDA_PUBLIC_API TryBlock : public BaseItem { 1472 public: TryBlock(size_t startPc,size_t length,std::vector<CatchBlock> catchBlocks)1473 TryBlock(size_t startPc, size_t length, std::vector<CatchBlock> catchBlocks) 1474 : startPc_(startPc), length_(length), catchBlocks_(std::move(catchBlocks)) 1475 { 1476 } 1477 1478 ~TryBlock() override = default; 1479 1480 DEFAULT_MOVE_SEMANTIC(TryBlock); 1481 DEFAULT_COPY_SEMANTIC(TryBlock); 1482 GetStartPc()1483 size_t GetStartPc() const 1484 { 1485 return startPc_; 1486 } 1487 GetLength()1488 size_t GetLength() const 1489 { 1490 return length_; 1491 } 1492 GetCatchBlocks()1493 std::vector<CatchBlock> GetCatchBlocks() const 1494 { 1495 return catchBlocks_; 1496 } 1497 1498 size_t CalculateSizeWithoutCatchBlocks() const; 1499 1500 void ComputeLayout() override; 1501 1502 size_t CalculateSize() const override; 1503 1504 bool Write(Writer *writer) override; 1505 GetItemType()1506 ItemTypes GetItemType() const override 1507 { 1508 return ItemTypes::TRY_BLOCK_ITEM; 1509 } 1510 1511 private: 1512 size_t startPc_; 1513 size_t length_; 1514 std::vector<CatchBlock> catchBlocks_; 1515 }; 1516 CodeItem(size_t numVregs,size_t numArgs,std::vector<uint8_t> instructions)1517 CodeItem(size_t numVregs, size_t numArgs, std::vector<uint8_t> instructions) 1518 : numVregs_(numVregs), numArgs_(numArgs), instructions_(std::move(instructions)) 1519 { 1520 } 1521 1522 CodeItem() = default; 1523 1524 ~CodeItem() override = default; 1525 SetNumVregs(size_t numVregs)1526 void SetNumVregs(size_t numVregs) 1527 { 1528 numVregs_ = numVregs; 1529 } 1530 SetNumArgs(size_t numArgs)1531 void SetNumArgs(size_t numArgs) 1532 { 1533 numArgs_ = numArgs; 1534 } 1535 GetInstructions()1536 std::vector<uint8_t> *GetInstructions() 1537 { 1538 return &instructions_; 1539 } 1540 SetNumInstructions(size_t numIns)1541 void SetNumInstructions(size_t numIns) 1542 { 1543 numIns_ = numIns; 1544 } 1545 GetNumInstructions()1546 size_t GetNumInstructions() const 1547 { 1548 return numIns_; 1549 } 1550 GetTryBlocks()1551 std::vector<TryBlock> GetTryBlocks() 1552 { 1553 return tryBlocks_; 1554 } 1555 AddTryBlock(const TryBlock & tryBlock)1556 void AddTryBlock(const TryBlock &tryBlock) 1557 { 1558 tryBlocks_.push_back(tryBlock); 1559 } 1560 1561 size_t CalculateSizeWithoutTryBlocks() const; 1562 1563 void ComputeLayout() override; 1564 1565 size_t CalculateSize() const override; 1566 1567 size_t GetCodeSize() const; 1568 1569 bool Write(Writer *writer) override; 1570 GetItemType()1571 ItemTypes GetItemType() const override 1572 { 1573 return ItemTypes::CODE_ITEM; 1574 } 1575 AddMethod(BaseMethodItem * method)1576 void AddMethod(BaseMethodItem *method) 1577 { 1578 methods_.emplace_back(method); 1579 } 1580 GetMethodNames()1581 std::vector<std::string> GetMethodNames() const 1582 { 1583 std::vector<std::string> names; 1584 for (const auto *method : methods_) { 1585 if (method == nullptr) { 1586 continue; 1587 } 1588 std::string className; 1589 if (method->GetClassItem() != nullptr) { 1590 className = method->GetClassItem()->GetNameItem()->GetData(); 1591 className.pop_back(); // remove '\0' 1592 ASSERT(className.size() > 2); // 2 - L and ; 1593 className.erase(0, 1); 1594 className.pop_back(); 1595 className.append("::"); 1596 } 1597 className.append(method->GetNameItem()->GetData()); 1598 className.pop_back(); // remove '\0' 1599 names.emplace_back(className); 1600 } 1601 return names; 1602 } 1603 GetNumVregs()1604 size_t GetNumVregs() 1605 { 1606 return numVregs_; 1607 } 1608 GetNumArgs()1609 size_t GetNumArgs() 1610 { 1611 return numArgs_; 1612 } 1613 1614 DEFAULT_MOVE_SEMANTIC(CodeItem); 1615 DEFAULT_COPY_SEMANTIC(CodeItem); 1616 1617 private: 1618 size_t numVregs_ {0}; 1619 size_t numArgs_ {0}; 1620 size_t numIns_ {0}; 1621 std::vector<uint8_t> instructions_; 1622 std::vector<TryBlock> tryBlocks_; 1623 std::vector<BaseMethodItem *> methods_; 1624 }; 1625 1626 class ScalarValueItem; 1627 class ArrayValueItem; 1628 1629 class ValueItem : public BaseItem { 1630 public: 1631 enum class Type { INTEGER, LONG, FLOAT, DOUBLE, ID, ARRAY }; 1632 ValueItem(Type type)1633 explicit ValueItem(Type type) : type_(type) {} 1634 1635 ~ValueItem() override = default; 1636 1637 DEFAULT_MOVE_SEMANTIC(ValueItem); 1638 DEFAULT_COPY_SEMANTIC(ValueItem); 1639 GetType()1640 Type GetType() const 1641 { 1642 return type_; 1643 } 1644 IsArray()1645 bool IsArray() const 1646 { 1647 return type_ == Type::ARRAY; 1648 } 1649 Is32bit()1650 bool Is32bit() const 1651 { 1652 return type_ == Type::INTEGER || type_ == Type::FLOAT || type_ == Type::ID; 1653 } 1654 GetItemType()1655 ItemTypes GetItemType() const override 1656 { 1657 return ItemTypes::VALUE_ITEM; 1658 } 1659 1660 ScalarValueItem *GetAsScalar(); 1661 1662 ArrayValueItem *GetAsArray(); 1663 1664 private: 1665 Type type_; 1666 }; 1667 1668 class PANDA_PUBLIC_API ScalarValueItem : public ValueItem { 1669 public: ScalarValueItem(uint32_t v)1670 explicit ScalarValueItem(uint32_t v) : ValueItem(Type::INTEGER), value_(v) {} 1671 ScalarValueItem(uint64_t v)1672 explicit ScalarValueItem(uint64_t v) : ValueItem(Type::LONG), value_(v) {} 1673 ScalarValueItem(float v)1674 explicit ScalarValueItem(float v) : ValueItem(Type::FLOAT), value_(v) {} 1675 ScalarValueItem(double v)1676 explicit ScalarValueItem(double v) : ValueItem(Type::DOUBLE), value_(v) {} 1677 ScalarValueItem(BaseItem * v)1678 explicit ScalarValueItem(BaseItem *v) : ValueItem(Type::ID), value_(v) {} 1679 1680 ~ScalarValueItem() override = default; 1681 1682 DEFAULT_MOVE_SEMANTIC(ScalarValueItem); 1683 DEFAULT_COPY_SEMANTIC(ScalarValueItem); 1684 1685 template <class T> GetValue()1686 T GetValue() const 1687 { 1688 return std::get<T>(value_); 1689 } 1690 1691 template <class T> HasValue()1692 bool HasValue() const 1693 { 1694 return std::holds_alternative<T>(value_); 1695 } 1696 GetId()1697 File::EntityId GetId() const 1698 { 1699 return File::EntityId(GetValue<BaseItem *>()->GetOffset()); 1700 } 1701 GetIdItem()1702 BaseItem *GetIdItem() const 1703 { 1704 return GetValue<BaseItem *>(); 1705 } 1706 1707 size_t GetULeb128EncodedSize(); 1708 1709 size_t GetSLeb128EncodedSize(); 1710 1711 size_t CalculateSize() const override; 1712 1713 size_t Alignment() override; 1714 1715 bool Write(Writer *writer) override; 1716 1717 bool WriteAsUleb128(Writer *writer); 1718 1719 private: 1720 std::variant<uint32_t, uint64_t, float, double, BaseItem *> value_; 1721 }; 1722 1723 class PANDA_PUBLIC_API ArrayValueItem : public ValueItem { 1724 public: ArrayValueItem(panda_file::Type componentType,std::vector<ScalarValueItem> items)1725 ArrayValueItem(panda_file::Type componentType, std::vector<ScalarValueItem> items) 1726 : ValueItem(Type::ARRAY), componentType_(componentType), items_(std::move(items)) 1727 { 1728 } 1729 1730 ~ArrayValueItem() override = default; 1731 1732 DEFAULT_MOVE_SEMANTIC(ArrayValueItem); 1733 DEFAULT_COPY_SEMANTIC(ArrayValueItem); 1734 1735 size_t CalculateSize() const override; 1736 1737 void ComputeLayout() override; 1738 1739 bool Write(Writer *writer) override; 1740 GetComponentType()1741 panda_file::Type GetComponentType() const 1742 { 1743 return componentType_; 1744 } 1745 GetItems()1746 const std::vector<ScalarValueItem> &GetItems() const 1747 { 1748 return items_; 1749 } 1750 1751 private: 1752 size_t GetComponentSize() const; 1753 1754 panda_file::Type componentType_; 1755 std::vector<ScalarValueItem> items_; 1756 }; 1757 1758 class LiteralItem; 1759 class LiteralArrayItem; 1760 1761 class PANDA_PUBLIC_API LiteralItem : public BaseItem { 1762 public: 1763 enum class Type { B1, B2, B4, B8, STRING, METHOD, LITERALARRAY }; 1764 LiteralItem(uint8_t v)1765 explicit LiteralItem(uint8_t v) : type_(Type::B1), value_(v) {} 1766 LiteralItem(uint16_t v)1767 explicit LiteralItem(uint16_t v) : type_(Type::B2), value_(v) {} 1768 LiteralItem(uint32_t v)1769 explicit LiteralItem(uint32_t v) : type_(Type::B4), value_(v) {} 1770 LiteralItem(uint64_t v)1771 explicit LiteralItem(uint64_t v) : type_(Type::B8), value_(v) {} 1772 LiteralItem(StringItem * v)1773 explicit LiteralItem(StringItem *v) : type_(Type::STRING), value_(v) {} 1774 LiteralItem(MethodItem * v)1775 explicit LiteralItem(MethodItem *v) : type_(Type::METHOD), value_(v) {} 1776 LiteralItem(LiteralArrayItem * v)1777 explicit LiteralItem(LiteralArrayItem *v) : type_(Type::LITERALARRAY), value_(v) {} 1778 1779 ~LiteralItem() override = default; 1780 1781 DEFAULT_MOVE_SEMANTIC(LiteralItem); 1782 DEFAULT_COPY_SEMANTIC(LiteralItem); 1783 GetType()1784 Type GetType() const 1785 { 1786 return type_; 1787 } 1788 GetItemType()1789 ItemTypes GetItemType() const override 1790 { 1791 return ItemTypes::LITERAL_ITEM; 1792 } 1793 1794 template <class T> GetValue()1795 T GetValue() const 1796 { 1797 return std::get<T>(value_); 1798 } 1799 1800 size_t CalculateSize() const override; 1801 1802 size_t Alignment() override; 1803 GetId()1804 File::EntityId GetId() const 1805 { 1806 return File::EntityId(GetValue<StringItem *>()->GetOffset()); 1807 } 1808 1809 File::EntityId GetLiteralArrayFileId() const; 1810 GetMethodId()1811 File::EntityId GetMethodId() const 1812 { 1813 return File::EntityId(GetValue<MethodItem *>()->GetFileId()); 1814 } 1815 1816 bool Write(Writer *writer) override; 1817 1818 private: 1819 Type type_; 1820 std::variant<uint8_t, uint16_t, uint32_t, uint64_t, StringItem *, MethodItem *, LiteralArrayItem *> value_; 1821 }; 1822 1823 class LiteralArrayItem : public ValueItem { 1824 public: LiteralArrayItem()1825 explicit LiteralArrayItem() : ValueItem(Type::ARRAY) {} 1826 1827 ~LiteralArrayItem() override = default; 1828 1829 DEFAULT_MOVE_SEMANTIC(LiteralArrayItem); 1830 DEFAULT_COPY_SEMANTIC(LiteralArrayItem); 1831 1832 PANDA_PUBLIC_API void AddItems(const std::vector<LiteralItem> &item); 1833 GetItems()1834 const std::vector<LiteralItem> &GetItems() const 1835 { 1836 return items_; 1837 } 1838 1839 size_t CalculateSize() const override; 1840 1841 void ComputeLayout() override; 1842 1843 bool Write(Writer *writer) override; 1844 GetItemType()1845 ItemTypes GetItemType() const override 1846 { 1847 return ItemTypes::LITERAL_ARRAY_ITEM; 1848 } 1849 SetIndex(uint32_t index)1850 void SetIndex(uint32_t index) 1851 { 1852 index_ = index; 1853 } 1854 GetIndex()1855 uint32_t GetIndex() const 1856 { 1857 return index_; 1858 } 1859 1860 private: 1861 std::vector<LiteralItem> items_; 1862 uint32_t index_ {0}; 1863 }; 1864 1865 class PANDA_PUBLIC_API AnnotationItem : public BaseItem { 1866 public: 1867 class Elem { 1868 public: Elem(StringItem * name,ValueItem * value)1869 Elem(StringItem *name, ValueItem *value) : name_(name), value_(value) 1870 { 1871 value_->SetNeedsEmit(!value_->Is32bit()); 1872 } 1873 1874 ~Elem() = default; 1875 1876 DEFAULT_MOVE_SEMANTIC(Elem); 1877 DEFAULT_COPY_SEMANTIC(Elem); 1878 GetName()1879 const StringItem *GetName() const 1880 { 1881 return name_; 1882 } 1883 GetValue()1884 ValueItem *GetValue() const 1885 { 1886 return value_; 1887 } 1888 SetValue(ValueItem * item)1889 void SetValue(ValueItem *item) 1890 { 1891 value_ = item; 1892 } 1893 1894 private: 1895 StringItem *name_; 1896 ValueItem *value_; 1897 }; 1898 1899 class Tag { 1900 public: Tag(char item)1901 explicit Tag(char item) : item_(item) {} 1902 1903 ~Tag() = default; 1904 1905 DEFAULT_MOVE_SEMANTIC(Tag); 1906 DEFAULT_COPY_SEMANTIC(Tag); 1907 GetItem()1908 uint8_t GetItem() const 1909 { 1910 return item_; 1911 } 1912 1913 private: 1914 uint8_t item_; 1915 }; 1916 AnnotationItem(BaseClassItem * cls,std::vector<Elem> elements,std::vector<Tag> tags)1917 AnnotationItem(BaseClassItem *cls, std::vector<Elem> elements, std::vector<Tag> tags) 1918 : class_(cls), elements_(std::move(elements)), tags_(std::move(tags)) 1919 { 1920 AddIndexDependency(cls); 1921 } 1922 1923 ~AnnotationItem() override = default; 1924 1925 DEFAULT_MOVE_SEMANTIC(AnnotationItem); 1926 DEFAULT_COPY_SEMANTIC(AnnotationItem); 1927 1928 size_t CalculateSize() const override; 1929 1930 bool Write(Writer *writer) override; 1931 GetItemType()1932 ItemTypes GetItemType() const override 1933 { 1934 return ItemTypes::ANNOTATION_ITEM; 1935 } 1936 GetClassItem()1937 BaseClassItem *GetClassItem() const 1938 { 1939 return class_; 1940 } 1941 GetElements()1942 std::vector<Elem> *GetElements() 1943 { 1944 return &elements_; 1945 } 1946 GetElements()1947 const std::vector<Elem> *GetElements() const 1948 { 1949 return &elements_; 1950 } 1951 SetElements(std::vector<Elem> && elements)1952 void SetElements(std::vector<Elem> &&elements) 1953 { 1954 elements_ = std::move(elements); 1955 } 1956 GetTags()1957 const std::vector<Tag> &GetTags() const 1958 { 1959 return tags_; 1960 } 1961 SetTags(std::vector<Tag> && tags)1962 void SetTags(std::vector<Tag> &&tags) 1963 { 1964 tags_ = std::move(tags); 1965 } 1966 1967 private: 1968 BaseClassItem *class_; 1969 std::vector<Elem> elements_; 1970 std::vector<Tag> tags_; 1971 }; 1972 1973 enum class MethodHandleType : uint8_t { 1974 PUT_STATIC = 0x00, 1975 GET_STATIC = 0x01, 1976 PUT_INSTANCE = 0x02, 1977 GET_INSTANCE = 0x03, 1978 INVOKE_STATIC = 0x04, 1979 INVOKE_INSTANCE = 0x05, 1980 INVOKE_CONSTRUCTOR = 0x06, 1981 INVOKE_DIRECT = 0x07, 1982 INVOKE_INTERFACE = 0x08 1983 }; 1984 1985 class PANDA_PUBLIC_API MethodHandleItem : public BaseItem { 1986 public: MethodHandleItem(MethodHandleType type,BaseItem * entity)1987 MethodHandleItem(MethodHandleType type, BaseItem *entity) : type_(type), entity_(entity) {} 1988 1989 ~MethodHandleItem() override = default; 1990 1991 DEFAULT_MOVE_SEMANTIC(MethodHandleItem); 1992 DEFAULT_COPY_SEMANTIC(MethodHandleItem); 1993 CalculateSize()1994 size_t CalculateSize() const override 1995 { 1996 return sizeof(uint8_t) + leb128::UnsignedEncodingSize(entity_->GetOffset()); 1997 } 1998 1999 bool Write(Writer *writer) override; 2000 GetItemType()2001 ItemTypes GetItemType() const override 2002 { 2003 return ItemTypes::METHOD_HANDLE_ITEM; 2004 } 2005 GetType()2006 MethodHandleType GetType() const 2007 { 2008 return type_; 2009 } 2010 2011 private: 2012 MethodHandleType type_; 2013 BaseItem *entity_; 2014 }; 2015 2016 enum class ArgumentType : uint8_t { 2017 INTEGER = 0x00, 2018 LONG = 0x01, 2019 FLOAT = 0x02, 2020 DOUBLE = 0x03, 2021 STRING = 0x04, 2022 CLASS = 0x05, 2023 METHOD_HANDLE = 0x06, 2024 METHOD_TYPE = 0x07 2025 }; 2026 2027 } // namespace ark::panda_file 2028 2029 #endif // LIBPANDAFILE_FILE_ITEMS_H_ 2030