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