• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "file_items.h"
17 #include "macros.h"
18 #include "utils/bit_utils.h"
19 #include "utils/leb128.h"
20 #include "utils/utf.h"
21 
22 #include <iomanip>
23 
24 namespace ark::panda_file {
25 
26 #include "file_items_gen.inc"
27 
28 size_t IndexedItem::itemAllocIdNext_ = 0;
29 
30 template <class Tag, class Val>
WriteUlebTaggedValue(Writer * writer,Tag tag,Val v)31 static bool WriteUlebTaggedValue(Writer *writer, Tag tag, Val v)
32 {
33     if (!writer->WriteByte(static_cast<uint8_t>(tag))) {
34         return false;
35     }
36 
37     if (!writer->WriteUleb128(v)) {
38         return false;
39     }
40 
41     return true;
42 }
43 
44 template <class Tag, class Val>
WriteSlebTaggedValue(Writer * writer,Tag tag,Val v)45 static bool WriteSlebTaggedValue(Writer *writer, Tag tag, Val v)
46 {
47     if (!writer->WriteByte(static_cast<uint8_t>(tag))) {
48         return false;
49     }
50 
51     if (!writer->WriteSleb128(v)) {
52         return false;
53     }
54 
55     return true;
56 }
57 
58 template <class Tag, class Val>
WriteTaggedValue(Writer * writer,Tag tag,Val v)59 static bool WriteTaggedValue(Writer *writer, Tag tag, Val v)
60 {
61     if (!writer->WriteByte(static_cast<uint8_t>(tag))) {
62         return false;
63     }
64 
65     if (!writer->Write(v)) {
66         return false;
67     }
68 
69     return true;
70 }
71 
72 template <class Tag>
WriteIdTaggedValue(Writer * writer,Tag tag,BaseItem * item)73 static bool WriteIdTaggedValue(Writer *writer, Tag tag, BaseItem *item)
74 {
75     ASSERT(item->GetOffset() != 0);
76     return WriteTaggedValue(writer, tag, item->GetOffset());
77 }
78 
79 // CC-OFFNXT(G.FUN.01-CPP, huge_cyclomatic_complexity[C++], huge_method[C++]) big switch case
ItemTypeToString(ItemTypes type)80 std::string ItemTypeToString(ItemTypes type)
81 {
82     switch (type) {
83         case ItemTypes::ANNOTATION_ITEM:
84             return "annotation_item";
85         case ItemTypes::CATCH_BLOCK_ITEM:
86             return "catch_block_item";
87         case ItemTypes::CLASS_INDEX_ITEM:
88             return "class_index_item";
89         case ItemTypes::CLASS_ITEM:
90             return "class_item";
91         case ItemTypes::CODE_ITEM:
92             return "code_item";
93         case ItemTypes::DEBUG_INFO_ITEM:
94             return "debug_info_item";
95         case ItemTypes::END_ITEM:
96             return "end_item";
97         case ItemTypes::FIELD_INDEX_ITEM:
98             return "field_index_item";
99         case ItemTypes::FIELD_ITEM:
100             return "field_item";
101         case ItemTypes::FOREIGN_CLASS_ITEM:
102             return "foreign_class_item";
103         case ItemTypes::FOREIGN_FIELD_ITEM:
104             return "foreign_field_item";
105         case ItemTypes::FOREIGN_METHOD_ITEM:
106             return "foreign_method_item";
107         case ItemTypes::LINE_NUMBER_PROGRAM_INDEX_ITEM:
108             return "line_number_program_index_item";
109         case ItemTypes::LINE_NUMBER_PROGRAM_ITEM:
110             return "line_number_program_item";
111         case ItemTypes::LITERAL_ARRAY_ITEM:
112             return "literal_array_item";
113         case ItemTypes::LITERAL_ITEM:
114             return "literal_item";
115         case ItemTypes::METHOD_HANDLE_ITEM:
116             return "method_handle_item";
117         case ItemTypes::METHOD_INDEX_ITEM:
118             return "method_index_item";
119         case ItemTypes::METHOD_ITEM:
120             return "method_item";
121         case ItemTypes::PARAM_ANNOTATIONS_ITEM:
122             return "param_annotations_item";
123         case ItemTypes::PRIMITIVE_TYPE_ITEM:
124             return "primitive_type_item";
125         case ItemTypes::PROTO_INDEX_ITEM:
126             return "proto_index_item";
127         case ItemTypes::PROTO_ITEM:
128             return "proto_item";
129         case ItemTypes::REGION_HEADER:
130             return "region_header";
131         case ItemTypes::REGION_SECTION:
132             return "region_section";
133         case ItemTypes::STRING_ITEM:
134             return "string_item";
135         case ItemTypes::TRY_BLOCK_ITEM:
136             return "try_block_item";
137         case ItemTypes::VALUE_ITEM:
138             return "value_item";
139         default:
140             return "";
141     }
142 }
143 
GetName() const144 std::string BaseItem::GetName() const
145 {
146     return ItemTypeToString(GetItemType());
147 }
148 
StringItem(std::string str)149 StringItem::StringItem(std::string str) : str_(std::move(str))
150 {
151     str_.push_back(0);
152     utf16Length_ = utf::MUtf8ToUtf16Size(utf::CStringAsMutf8(str_.data()));
153     isAscii_ = 1;
154 
155     for (auto c : str_) {
156         if (static_cast<uint8_t>(c) > utf::UTF8_1B_MAX) {
157             isAscii_ = 0;
158             break;
159         }
160     }
161 }
162 
StringItem(File::StringData data)163 StringItem::StringItem(File::StringData data)
164     : str_(reinterpret_cast<const char *>(data.data)), utf16Length_(data.utf16Length)
165 {
166 }
167 
CalculateSize() const168 size_t StringItem::CalculateSize() const
169 {
170     size_t n = str_.size();
171     return leb128::UnsignedEncodingSize((utf16Length_ << 1U) | isAscii_) + n;
172 }
173 
Write(Writer * writer)174 bool StringItem::Write(Writer *writer)
175 {
176     ASSERT(GetOffset() == writer->GetOffset());
177     constexpr size_t MAX_LENGTH = 0x7fffffffU;
178     if (utf16Length_ > MAX_LENGTH) {
179         LOG(ERROR, PANDAFILE) << "Writing StringItem with size greater than 0x7fffffffU is not supported!";
180         return false;
181     }
182 
183     if (!writer->WriteUleb128((utf16Length_ << 1U) | isAscii_)) {
184         return false;
185     }
186 
187     for (auto c : str_) {
188         if (!writer->WriteByte(static_cast<uint8_t>(c))) {
189             return false;
190         }
191     }
192     return true;
193 }
194 
CalculateSize() const195 size_t BaseClassItem::CalculateSize() const
196 {
197     return name_.GetSize();
198 }
199 
ComputeLayout()200 void BaseClassItem::ComputeLayout()
201 {
202     uint32_t offset = GetOffset();
203 
204     ASSERT(offset != 0);
205 
206     name_.SetOffset(offset);
207 }
208 
Write(Writer * writer)209 bool BaseClassItem::Write(Writer *writer)
210 {
211     ASSERT(GetOffset() == writer->GetOffset());
212     return name_.Write(writer);
213 }
214 
CalculateSizeWithoutFieldsAndMethods() const215 size_t ClassItem::CalculateSizeWithoutFieldsAndMethods() const
216 {
217     size_t size = BaseClassItem::CalculateSize() + ID_SIZE + leb128::UnsignedEncodingSize(accessFlags_);
218 
219     size += leb128::UnsignedEncodingSize(fields_.size());
220     size += leb128::UnsignedEncodingSize(methods_.size());
221 
222     if (!ifaces_.empty()) {
223         size += TAG_SIZE + leb128::UnsignedEncodingSize(ifaces_.size()) + IDX_SIZE * ifaces_.size();
224     }
225 
226     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
227         size += TAG_SIZE + sizeof(SourceLang);
228     }
229 
230     size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
231     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
232     size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
233     size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
234 
235     if (sourceFile_ != nullptr) {
236         size += TAG_SIZE + ID_SIZE;
237     }
238 
239     size += TAG_SIZE;  // null tag
240 
241     return size;
242 }
243 
CalculateSize() const244 size_t ClassItem::CalculateSize() const
245 {
246     size_t size = CalculateSizeWithoutFieldsAndMethods();
247 
248     for (auto &field : fields_) {
249         size += field->GetSize();
250     }
251 
252     for (auto &method : methods_) {
253         size += method->GetSize();
254     }
255 
256     return size;
257 }
258 
ComputeLayout()259 void ClassItem::ComputeLayout()
260 {
261     BaseClassItem::ComputeLayout();
262 
263     uint32_t offset = GetOffset();
264 
265     offset += CalculateSizeWithoutFieldsAndMethods();
266 
267     for (auto &field : fields_) {
268         field->SetOffset(offset);
269         field->ComputeLayout();
270         offset += field->GetSize();
271     }
272 
273     for (auto &method : methods_) {
274         method->SetOffset(offset);
275         method->ComputeLayout();
276         offset += method->GetSize();
277     }
278 }
279 
WriteIfaces(Writer * writer)280 bool ClassItem::WriteIfaces(Writer *writer)
281 {
282     if (!ifaces_.empty()) {
283         if (!writer->WriteByte(static_cast<uint8_t>(ClassTag::INTERFACES))) {
284             return false;
285         }
286 
287         if (!writer->WriteUleb128(ifaces_.size())) {
288             return false;
289         }
290 
291         for (auto iface : ifaces_) {
292             ASSERT(iface->HasIndex(this));
293             if (!writer->Write<uint16_t>(iface->GetIndex(this))) {
294                 return false;
295             }
296         }
297     }
298 
299     return true;
300 }
301 
WriteAnnotations(Writer * writer)302 bool ClassItem::WriteAnnotations(Writer *writer)
303 {
304     for (auto runtimeAnnotation : runtimeAnnotations_) {
305         if (!WriteIdTaggedValue(writer, ClassTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
306             return false;
307         }
308     }
309 
310     for (auto annotation : annotations_) {
311         if (!WriteIdTaggedValue(writer, ClassTag::ANNOTATION, annotation)) {
312             return false;
313         }
314     }
315 
316     for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
317         if (!WriteIdTaggedValue(writer, ClassTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
318             return false;
319         }
320     }
321 
322     for (auto typeAnnotation : typeAnnotations_) {
323         if (!WriteIdTaggedValue(writer, ClassTag::TYPE_ANNOTATION, typeAnnotation)) {
324             return false;
325         }
326     }
327 
328     return true;
329 }
330 
WriteTaggedData(Writer * writer)331 bool ClassItem::WriteTaggedData(Writer *writer)
332 {
333     if (!WriteIfaces(writer)) {
334         return false;
335     }
336 
337     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
338         if (!WriteTaggedValue(writer, ClassTag::SOURCE_LANG, static_cast<uint8_t>(sourceLang_))) {
339             return false;
340         }
341     }
342 
343     if (!WriteAnnotations(writer)) {
344         return false;
345     }
346 
347     if (sourceFile_ != nullptr) {
348         if (!WriteIdTaggedValue(writer, ClassTag::SOURCE_FILE, sourceFile_)) {
349             return false;
350         }
351     }
352 
353     return writer->WriteByte(static_cast<uint8_t>(ClassTag::NOTHING));
354 }
355 
Write(Writer * writer)356 bool ClassItem::Write(Writer *writer)
357 {
358     if (!BaseClassItem::Write(writer)) {
359         return false;
360     }
361 
362     uint32_t offset = superClass_ != nullptr ? superClass_->GetOffset() : 0;
363     if (!writer->Write(offset)) {
364         return false;
365     }
366 
367     if (!writer->WriteUleb128(accessFlags_)) {
368         return false;
369     }
370 
371     if (!writer->WriteUleb128(fields_.size())) {
372         return false;
373     }
374 
375     if (!writer->WriteUleb128(methods_.size())) {
376         return false;
377     }
378 
379     if (!WriteTaggedData(writer)) {
380         return false;
381     }
382 
383     for (auto &field : fields_) {
384         if (!field->Write(writer)) {
385             return false;
386         }
387     }
388 
389     for (auto &method : methods_) {
390         if (!method->Write(writer)) {
391             return false;
392         }
393     }
394 
395     return true;
396 }
397 
SetDependencyMark()398 void ClassItem::SetDependencyMark()
399 {
400     BaseItem::SetDependencyMark();
401     for (auto &iface : ifaces_) {
402         iface->SetDependencyMark();
403     }
404     if (superClass_ != nullptr) {
405         superClass_->SetDependencyMark();
406     }
407     if (sourceFile_ != nullptr) {
408         sourceFile_->SetDependencyMark();
409     }
410     for (auto &item : annotations_) {
411         item->SetDependencyMark();
412     }
413     for (auto &item : runtimeAnnotations_) {
414         item->SetDependencyMark();
415     }
416     for (auto &item : typeAnnotations_) {
417         item->SetDependencyMark();
418     }
419     for (auto &item : runtimeTypeAnnotations_) {
420         item->SetDependencyMark();
421     }
422     for (auto &field : fields_) {
423         if (!field->GetDependencyMark()) {
424             field->SetDependencyMark();
425         }
426     }
427     for (auto &method : methods_) {
428         if (!method->GetDependencyMark()) {
429             method->SetDependencyMark();
430         }
431     }
432 }
433 
ParamAnnotationsItem(MethodItem * method,bool isRuntimeAnnotations)434 ParamAnnotationsItem::ParamAnnotationsItem(MethodItem *method, bool isRuntimeAnnotations)
435 {
436     for (const auto &param : method->GetParams()) {
437         if (isRuntimeAnnotations) {
438             annotations_.push_back(param.GetRuntimeAnnotations());
439         } else {
440             annotations_.push_back(param.GetAnnotations());
441         }
442     }
443 
444     if (isRuntimeAnnotations) {
445         method->SetRuntimeParamAnnotationItem(this);
446     } else {
447         method->SetParamAnnotationItem(this);
448     }
449 }
450 
CalculateSize() const451 size_t ParamAnnotationsItem::CalculateSize() const
452 {
453     size_t size = sizeof(uint32_t);  // size
454 
455     for (const auto &paramAnnotations : annotations_) {
456         size += sizeof(uint32_t);  // count
457         size += paramAnnotations.size() * ID_SIZE;
458     }
459 
460     return size;
461 }
462 
Write(Writer * writer)463 bool ParamAnnotationsItem::Write(Writer *writer)
464 {
465     ASSERT(GetOffset() == writer->GetOffset());
466 
467     if (!writer->Write(static_cast<uint32_t>(annotations_.size()))) {
468         return false;
469     }
470 
471     for (const auto &paramAnnotations : annotations_) {
472         if (!writer->Write(static_cast<uint32_t>(paramAnnotations.size()))) {
473             return false;
474         }
475 
476         for (auto *item : paramAnnotations) {
477             ASSERT(item->GetOffset() != 0);
478 
479             if (!writer->Write(item->GetOffset())) {
480                 return false;
481             }
482         }
483     }
484 
485     return true;
486 }
487 
ProtoItem(TypeItem * retType,const std::vector<MethodParamItem> & params)488 ProtoItem::ProtoItem(TypeItem *retType, const std::vector<MethodParamItem> &params)
489 {
490     size_t n = 0;
491     shorty_.push_back(0);
492     AddType(retType, &n);
493     for (auto &p : params) {
494         AddType(p.GetType(), &n);
495     }
496 }
497 
AddType(TypeItem * type,size_t * n)498 void ProtoItem::AddType(TypeItem *type, size_t *n)
499 {
500     constexpr size_t SHORTY_ELEMS_COUNT = std::numeric_limits<uint16_t>::digits / SHORTY_ELEM_SIZE;
501 
502     uint16_t v = shorty_.back();
503 
504     size_t shift = (*n % SHORTY_ELEMS_COUNT) * SHORTY_ELEM_SIZE;
505 
506     v |= static_cast<uint16_t>(static_cast<uint16_t>(type->GetType().GetEncoding()) << shift);
507     shorty_.back() = v;
508 
509     if (!type->GetType().IsPrimitive()) {
510         referenceTypes_.push_back(type);
511         AddIndexDependency(type);
512     }
513 
514     *n += 1;
515 
516     if (*n % SHORTY_ELEMS_COUNT == 0) {
517         shorty_.push_back(0);
518     }
519 }
520 
Write(Writer * writer)521 bool ProtoItem::Write(Writer *writer)
522 {
523     ASSERT(GetOffset() == writer->GetOffset());
524     for (auto s : shorty_) {
525         if (!writer->Write(s)) {
526             return false;
527         }
528     }
529 
530     for (auto r : referenceTypes_) {
531         ASSERT(r->HasIndex(this));
532         if (!writer->Write<uint16_t>(r->GetIndex(this))) {
533             return false;
534         }
535     }
536 
537     return true;
538 }
539 
SetDependencyMark()540 void ProtoItem::SetDependencyMark()
541 {
542     BaseItem::SetDependencyMark();
543     for (auto item : referenceTypes_) {
544         item->SetDependencyMark();
545     }
546 }
547 
BaseMethodItem(BaseClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t accessFlags)548 BaseMethodItem::BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags)
549     : class_(cls), name_(name), proto_(proto), accessFlags_(accessFlags)
550 {
551     AddIndexDependency(cls);
552     AddIndexDependency(proto);
553 }
554 
CalculateSize() const555 size_t BaseMethodItem::CalculateSize() const
556 {
557     // class id + proto id + name id + access flags
558     return IDX_SIZE + IDX_SIZE + ID_SIZE + leb128::UnsignedEncodingSize(accessFlags_);
559 }
560 
Write(Writer * writer)561 bool BaseMethodItem::Write(Writer *writer)
562 {
563     ASSERT(GetOffset() == writer->GetOffset());
564     ASSERT(class_ != nullptr);
565     ASSERT(class_->HasIndex(this));
566 
567     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
568         return false;
569     }
570 
571     ASSERT(proto_->HasIndex(this));
572 
573     if (!writer->Write<uint16_t>(proto_->GetIndex(this))) {
574         return false;
575     }
576 
577     ASSERT(name_->GetOffset() != 0);
578 
579     if (!writer->Write(name_->GetOffset())) {
580         return false;
581     }
582 
583     return writer->WriteUleb128(accessFlags_);
584 }
585 
SetDependencyMark()586 void BaseMethodItem::SetDependencyMark()
587 {
588     BaseItem::SetDependencyMark();
589     if (class_ != nullptr) {
590         if (!class_->GetDependencyMark()) {
591             class_->SetDependencyMark();
592         }
593     }
594     if (name_ != nullptr) {
595         name_->SetDependencyMark();
596     }
597     if (proto_ != nullptr) {
598         proto_->SetDependencyMark();
599     }
600     auto deps = GetIndexDependencies();
601     for (auto dep : deps) {
602         dep->SetDependencyMark();
603     }
604 }
605 
MethodItem(ClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t accessFlags,std::vector<MethodParamItem> params)606 MethodItem::MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags,
607                        std::vector<MethodParamItem> params)
608     : BaseMethodItem(cls, name, proto, accessFlags), params_(std::move(params))
609 {
610 }
611 
CalculateSize() const612 size_t MethodItem::CalculateSize() const
613 {
614     size_t size = BaseMethodItem::CalculateSize();
615 
616     if (code_ != nullptr) {
617         size += TAG_SIZE + ID_SIZE;
618     }
619 
620     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
621         size += TAG_SIZE + sizeof(SourceLang);
622     }
623 
624     size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
625 
626     if (runtimeParamAnnotations_ != nullptr) {
627         size += TAG_SIZE + ID_SIZE;
628     }
629 
630     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
631 
632     if (paramAnnotations_ != nullptr) {
633         size += TAG_SIZE + ID_SIZE;
634     }
635 
636     size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
637     size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
638 
639     if (debugInfo_ != nullptr) {
640         size += TAG_SIZE + ID_SIZE;
641     }
642 
643     if (profileSize_ != 0) {
644         size += TAG_SIZE + sizeof(profileSize_);
645     }
646 
647     size += TAG_SIZE;  // null tag
648 
649     return size;
650 }
651 
WriteRuntimeAnnotations(Writer * writer)652 bool MethodItem::WriteRuntimeAnnotations(Writer *writer)
653 {
654     for (auto runtimeAnnotation : runtimeAnnotations_) {
655         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
656             return false;
657         }
658     }
659 
660     if (runtimeParamAnnotations_ != nullptr) {
661         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_PARAM_ANNOTATION, runtimeParamAnnotations_)) {
662             return false;
663         }
664     }
665 
666     return true;
667 }
668 
WriteTypeAnnotations(Writer * writer)669 bool MethodItem::WriteTypeAnnotations(Writer *writer)
670 {
671     for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
672         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
673             return false;
674         }
675     }
676 
677     for (auto typeAnnotation : typeAnnotations_) {
678         if (!WriteIdTaggedValue(writer, MethodTag::TYPE_ANNOTATION, typeAnnotation)) {
679             return false;
680         }
681     }
682 
683     return true;
684 }
685 
WriteTaggedData(Writer * writer)686 bool MethodItem::WriteTaggedData(Writer *writer)
687 {
688     if (code_ != nullptr) {
689         if (!WriteIdTaggedValue(writer, MethodTag::CODE, code_)) {
690             return false;
691         }
692     }
693 
694     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
695         if (!WriteTaggedValue(writer, MethodTag::SOURCE_LANG, static_cast<uint8_t>(sourceLang_))) {
696             return false;
697         }
698     }
699 
700     if (!WriteRuntimeAnnotations(writer)) {
701         return false;
702     }
703 
704     if (debugInfo_ != nullptr) {
705         if (!WriteIdTaggedValue(writer, MethodTag::DEBUG_INFO, debugInfo_)) {
706             return false;
707         }
708     }
709 
710     for (auto annotation : annotations_) {
711         if (!WriteIdTaggedValue(writer, MethodTag::ANNOTATION, annotation)) {
712             return false;
713         }
714     }
715 
716     if (!WriteTypeAnnotations(writer)) {
717         return false;
718     }
719 
720     if (paramAnnotations_ != nullptr) {
721         if (!WriteIdTaggedValue(writer, MethodTag::PARAM_ANNOTATION, paramAnnotations_)) {
722             return false;
723         }
724     }
725 
726     if (profileSize_ != 0) {
727         if (!WriteTaggedValue(writer, MethodTag::PROFILE_INFO, static_cast<uint16_t>(profileSize_))) {
728             return false;
729         }
730     }
731 
732     return writer->WriteByte(static_cast<uint8_t>(MethodTag::NOTHING));
733 }
734 
Write(Writer * writer)735 bool MethodItem::Write(Writer *writer)
736 {
737     if (!BaseMethodItem::Write(writer)) {
738         return false;
739     }
740 
741     return WriteTaggedData(writer);
742 }
743 
SetDependencyMark()744 void MethodItem::SetDependencyMark()
745 {
746     BaseMethodItem::SetDependencyMark();
747     if (code_ != nullptr) {
748         code_->SetDependencyMark();
749     }
750     if (debugInfo_ != nullptr) {
751         debugInfo_->SetDependencyMark();
752     }
753     for (auto &item : annotations_) {
754         item->SetDependencyMark();
755     }
756     for (auto &item : runtimeAnnotations_) {
757         item->SetDependencyMark();
758     }
759     for (auto &item : typeAnnotations_) {
760         item->SetDependencyMark();
761     }
762     for (auto &item : runtimeTypeAnnotations_) {
763         item->SetDependencyMark();
764     }
765 }
766 
CalculateSize() const767 size_t CodeItem::CatchBlock::CalculateSize() const
768 {
769     ASSERT(type_ == nullptr || type_->HasIndex(method_));
770     uint32_t typeOff = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
771     return leb128::UnsignedEncodingSize(typeOff) + leb128::UnsignedEncodingSize(handlerPc_) +
772            leb128::UnsignedEncodingSize(codeSize_);
773 }
774 
Write(Writer * writer)775 bool CodeItem::CatchBlock::Write(Writer *writer)
776 {
777     ASSERT(GetOffset() == writer->GetOffset());
778     ASSERT(type_ == nullptr || type_->HasIndex(method_));
779 
780     uint32_t typeOff = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
781     if (!writer->WriteUleb128(typeOff)) {
782         return false;
783     }
784 
785     if (!writer->WriteUleb128(handlerPc_)) {
786         return false;
787     }
788 
789     if (!writer->WriteUleb128(codeSize_)) {
790         return false;
791     }
792 
793     return true;
794 }
795 
ComputeLayout()796 void CodeItem::TryBlock::ComputeLayout()
797 {
798     size_t offset = GetOffset();
799     offset += CalculateSizeWithoutCatchBlocks();
800 
801     for (auto &catchBlock : catchBlocks_) {
802         catchBlock.SetOffset(offset);
803         catchBlock.ComputeLayout();
804         offset += catchBlock.GetSize();
805     }
806 }
807 
CalculateSizeWithoutCatchBlocks() const808 size_t CodeItem::TryBlock::CalculateSizeWithoutCatchBlocks() const
809 {
810     return leb128::UnsignedEncodingSize(startPc_) + leb128::UnsignedEncodingSize(length_) +
811            leb128::UnsignedEncodingSize(catchBlocks_.size());
812 }
813 
CalculateSize() const814 size_t CodeItem::TryBlock::CalculateSize() const
815 {
816     size_t size = CalculateSizeWithoutCatchBlocks();
817 
818     for (auto &catchBlock : catchBlocks_) {
819         size += catchBlock.GetSize();
820     }
821 
822     return size;
823 }
824 
Write(Writer * writer)825 bool CodeItem::TryBlock::Write(Writer *writer)
826 {
827     ASSERT(GetOffset() == writer->GetOffset());
828 
829     if (!writer->WriteUleb128(startPc_)) {
830         return false;
831     }
832 
833     if (!writer->WriteUleb128(length_)) {
834         return false;
835     }
836 
837     if (!writer->WriteUleb128(catchBlocks_.size())) {
838         return false;
839     }
840 
841     for (auto &catchBlock : catchBlocks_) {
842         if (!catchBlock.Write(writer)) {
843             return false;
844         }
845     }
846 
847     return true;
848 }
849 
ComputeLayout()850 void CodeItem::ComputeLayout()
851 {
852     uint32_t offset = GetOffset();
853 
854     offset += CalculateSizeWithoutTryBlocks();
855 
856     for (auto &tryBlock : tryBlocks_) {
857         tryBlock.SetOffset(offset);
858         tryBlock.ComputeLayout();
859         offset += tryBlock.GetSize();
860     }
861 }
862 
CalculateSizeWithoutTryBlocks() const863 size_t CodeItem::CalculateSizeWithoutTryBlocks() const
864 {
865     size_t size = leb128::UnsignedEncodingSize(numVregs_) + leb128::UnsignedEncodingSize(numArgs_) +
866                   leb128::UnsignedEncodingSize(instructions_.size()) + leb128::UnsignedEncodingSize(tryBlocks_.size());
867 
868     size += instructions_.size();
869 
870     return size;
871 }
872 
GetCodeSize() const873 size_t CodeItem::GetCodeSize() const
874 {
875     return instructions_.size();
876 }
877 
CalculateSize() const878 size_t CodeItem::CalculateSize() const
879 {
880     size_t size = CalculateSizeWithoutTryBlocks();
881 
882     for (auto &tryBlock : tryBlocks_) {
883         size += tryBlock.GetSize();
884     }
885 
886     return size;
887 }
888 
Write(Writer * writer)889 bool CodeItem::Write(Writer *writer)
890 {
891     ASSERT(GetOffset() == writer->GetOffset());
892 
893     if (!writer->WriteUleb128(numVregs_)) {
894         return false;
895     }
896 
897     if (!writer->WriteUleb128(numArgs_)) {
898         return false;
899     }
900 
901     if (!writer->WriteUleb128(instructions_.size())) {
902         return false;
903     }
904 
905     if (!writer->WriteUleb128(tryBlocks_.size())) {
906         return false;
907     }
908 
909     if (!writer->WriteBytes(instructions_)) {
910         return false;
911     }
912 
913     for (auto &tryBlock : tryBlocks_) {
914         if (!tryBlock.Write(writer)) {
915             return false;
916         }
917     }
918 
919     return true;
920 }
921 
GetAsScalar()922 ScalarValueItem *ValueItem::GetAsScalar()
923 {
924     ASSERT(!IsArray());
925     return static_cast<ScalarValueItem *>(this);
926 }
927 
GetAsArray()928 ArrayValueItem *ValueItem::GetAsArray()
929 {
930     ASSERT(IsArray());
931     return static_cast<ArrayValueItem *>(this);
932 }
933 
GetULeb128EncodedSize()934 size_t ScalarValueItem::GetULeb128EncodedSize()
935 {
936     switch (GetType()) {
937         case Type::INTEGER:
938             return leb128::UnsignedEncodingSize(GetValue<uint32_t>());
939 
940         case Type::LONG:
941             return leb128::UnsignedEncodingSize(GetValue<uint64_t>());
942 
943         case Type::ID:
944             return leb128::UnsignedEncodingSize(GetId().GetOffset());
945 
946         default:
947             return 0;
948     }
949 }
950 
GetSLeb128EncodedSize()951 size_t ScalarValueItem::GetSLeb128EncodedSize()
952 {
953     switch (GetType()) {
954         case Type::INTEGER:
955             return leb128::SignedEncodingSize(static_cast<int32_t>(GetValue<uint32_t>()));
956 
957         case Type::LONG:
958             return leb128::SignedEncodingSize(static_cast<int64_t>(GetValue<uint64_t>()));
959 
960         default:
961             return 0;
962     }
963 }
964 
CalculateSize() const965 size_t ScalarValueItem::CalculateSize() const
966 {
967     size_t size = 0;
968     switch (GetType()) {
969         case Type::INTEGER: {
970             size = sizeof(uint32_t);
971             break;
972         }
973 
974         case Type::LONG: {
975             size = sizeof(uint64_t);
976             break;
977         }
978 
979         case Type::FLOAT: {
980             size = sizeof(float);
981             break;
982         }
983 
984         case Type::DOUBLE: {
985             size = sizeof(double);
986             break;
987         }
988 
989         case Type::ID: {
990             size = ID_SIZE;
991             break;
992         }
993         default: {
994             UNREACHABLE();
995             break;
996         }
997     }
998 
999     return size;
1000 }
1001 
Alignment()1002 size_t ScalarValueItem::Alignment()
1003 {
1004     return GetSize();
1005 }
1006 
Write(Writer * writer)1007 bool ScalarValueItem::Write(Writer *writer)
1008 {
1009     ASSERT(GetOffset() == writer->GetOffset());
1010 
1011     switch (GetType()) {
1012         case Type::INTEGER:
1013             return writer->Write(GetValue<uint32_t>());
1014 
1015         case Type::LONG:
1016             return writer->Write(GetValue<uint64_t>());
1017 
1018         case Type::FLOAT:
1019             return writer->Write(bit_cast<uint32_t>(GetValue<float>()));
1020 
1021         case Type::DOUBLE:
1022             return writer->Write(bit_cast<uint64_t>(GetValue<double>()));
1023 
1024         case Type::ID: {
1025             ASSERT(GetId().IsValid());
1026             return writer->Write(GetId().GetOffset());
1027         }
1028         default: {
1029             UNREACHABLE();
1030             break;
1031         }
1032     }
1033 
1034     return true;
1035 }
1036 
WriteAsUleb128(Writer * writer)1037 bool ScalarValueItem::WriteAsUleb128(Writer *writer)
1038 {
1039     ASSERT(GetOffset() == writer->GetOffset());
1040 
1041     switch (GetType()) {
1042         case Type::INTEGER:
1043             return writer->WriteUleb128(GetValue<uint32_t>());
1044 
1045         case Type::LONG:
1046             return writer->WriteUleb128(GetValue<uint64_t>());
1047 
1048         case Type::ID: {
1049             ASSERT(GetId().IsValid());
1050             return writer->WriteUleb128(GetId().GetOffset());
1051         }
1052         default:
1053             return false;
1054     }
1055 }
1056 
CalculateSize() const1057 size_t ArrayValueItem::CalculateSize() const
1058 {
1059     size_t size = leb128::UnsignedEncodingSize(items_.size()) + items_.size() * GetComponentSize();
1060     return size;
1061 }
1062 
ComputeLayout()1063 void ArrayValueItem::ComputeLayout()
1064 {
1065     uint32_t offset = GetOffset();
1066 
1067     ASSERT(offset != 0);
1068 
1069     offset += leb128::UnsignedEncodingSize(items_.size());
1070 
1071     for (auto &item : items_) {
1072         item.SetOffset(offset);
1073         offset += GetComponentSize();
1074     }
1075 }
1076 
Write(Writer * writer)1077 bool ArrayValueItem::Write(Writer *writer)
1078 {
1079     ASSERT(GetOffset() == writer->GetOffset());
1080 
1081     if (!writer->WriteUleb128(items_.size())) {
1082         return false;
1083     }
1084 
1085     switch (componentType_.GetId()) {
1086         case panda_file::Type::TypeId::U1:
1087         case panda_file::Type::TypeId::I8:
1088         case panda_file::Type::TypeId::U8: {
1089             for (auto &item : items_) {
1090                 auto value = static_cast<uint8_t>(item.GetValue<uint32_t>());
1091                 if (!writer->Write(value)) {
1092                     return false;
1093                 }
1094             }
1095             break;
1096         }
1097         case panda_file::Type::TypeId::I16:
1098         case panda_file::Type::TypeId::U16: {
1099             for (auto &item : items_) {
1100                 auto value = static_cast<uint16_t>(item.GetValue<uint32_t>());
1101                 if (!writer->Write(value)) {
1102                     return false;
1103                 }
1104             }
1105             break;
1106         }
1107         default: {
1108             for (auto &item : items_) {
1109                 if (!item.Write(writer)) {
1110                     return false;
1111                 }
1112             }
1113             break;
1114         }
1115     }
1116 
1117     return true;
1118 }
1119 
GetComponentSize() const1120 size_t ArrayValueItem::GetComponentSize() const
1121 {
1122     switch (componentType_.GetId()) {
1123         case panda_file::Type::TypeId::U1:
1124         case panda_file::Type::TypeId::I8:
1125         case panda_file::Type::TypeId::U8:
1126             return sizeof(uint8_t);
1127         case panda_file::Type::TypeId::I16:
1128         case panda_file::Type::TypeId::U16:
1129             return sizeof(uint16_t);
1130         case panda_file::Type::TypeId::I32:
1131         case panda_file::Type::TypeId::U32:
1132         case panda_file::Type::TypeId::F32:
1133             return sizeof(uint32_t);
1134         case panda_file::Type::TypeId::I64:
1135         case panda_file::Type::TypeId::U64:
1136         case panda_file::Type::TypeId::F64:
1137             return sizeof(uint64_t);
1138         case panda_file::Type::TypeId::REFERENCE:
1139             return ID_SIZE;
1140         case panda_file::Type::TypeId::VOID:
1141             return 0;
1142         default: {
1143             UNREACHABLE();
1144             // Avoid cpp warning
1145             return 0;
1146         }
1147     }
1148 }
1149 
CalculateSize() const1150 size_t LiteralItem::CalculateSize() const
1151 {
1152     size_t size = 0;
1153     switch (GetType()) {
1154         case Type::B1: {
1155             size = sizeof(uint8_t);
1156             break;
1157         }
1158 
1159         case Type::B2: {
1160             size = sizeof(uint16_t);
1161             break;
1162         }
1163 
1164         case Type::B4: {
1165             size = sizeof(uint32_t);
1166             break;
1167         }
1168 
1169         case Type::B8: {
1170             size = sizeof(uint64_t);
1171             break;
1172         }
1173 
1174         case Type::STRING:
1175         case Type::METHOD:
1176         case Type::LITERALARRAY: {
1177             size = ID_SIZE;
1178             break;
1179         }
1180 
1181         default: {
1182             UNREACHABLE();
1183             break;
1184         }
1185     }
1186 
1187     return size;
1188 }
1189 
Alignment()1190 size_t LiteralItem::Alignment()
1191 {
1192     return GetSize();
1193 }
1194 
GetLiteralArrayFileId() const1195 File::EntityId LiteralItem::GetLiteralArrayFileId() const
1196 {
1197     return File::EntityId(GetValue<LiteralArrayItem *>()->GetOffset());
1198 }
1199 
SetDependencyMark()1200 void LiteralItem::SetDependencyMark()
1201 {
1202     BaseItem::SetDependencyMark();
1203     if (type_ == Type::STRING) {
1204         auto stringItem = GetValue<StringItem *>();
1205         stringItem->SetDependencyMark();
1206     } else if (type_ == Type::METHOD) {
1207         auto methodItem = GetValue<MethodItem *>();
1208         methodItem->SetDependencyMark();
1209     }
1210 }
1211 
Write(Writer * writer)1212 bool LiteralItem::Write(Writer *writer)
1213 {
1214     ASSERT(GetOffset() == writer->GetOffset());
1215 
1216     switch (GetType()) {
1217         case Type::B1: {
1218             return writer->Write(GetValue<uint8_t>());
1219         }
1220         case Type::B2: {
1221             return writer->Write(GetValue<uint16_t>());
1222         }
1223         case Type::B4: {
1224             return writer->Write(GetValue<uint32_t>());
1225         }
1226         case Type::B8: {
1227             return writer->Write(GetValue<uint64_t>());
1228         }
1229         case Type::STRING: {
1230             ASSERT(GetId().IsValid());
1231             return writer->Write(GetId().GetOffset());
1232         }
1233         case Type::METHOD: {
1234             ASSERT(GetMethodId().IsValid());
1235             return writer->Write(GetMethodId().GetOffset());
1236         }
1237         case Type::LITERALARRAY: {
1238             ASSERT(GetLiteralArrayFileId().IsValid());
1239             return writer->Write(GetLiteralArrayFileId().GetOffset());
1240         }
1241         default: {
1242             UNREACHABLE();
1243             break;
1244         }
1245     }
1246 
1247     return true;
1248 }
1249 
AddItems(const std::vector<LiteralItem> & item)1250 void LiteralArrayItem::AddItems(const std::vector<LiteralItem> &item)
1251 {
1252     items_.assign(item.begin(), item.end());
1253 }
1254 
CalculateSize() const1255 size_t LiteralArrayItem::CalculateSize() const
1256 {
1257     size_t size = sizeof(uint32_t);
1258     for (auto &item : items_) {
1259         size += item.CalculateSize();
1260     }
1261 
1262     return size;
1263 }
1264 
ComputeLayout()1265 void LiteralArrayItem::ComputeLayout()
1266 {
1267     uint32_t offset = GetOffset();
1268 
1269     ASSERT(offset != 0);
1270 
1271     offset += sizeof(uint32_t);
1272 
1273     for (auto &item : items_) {
1274         item.SetOffset(offset);
1275         offset += item.CalculateSize();
1276     }
1277 }
1278 
Write(Writer * writer)1279 bool LiteralArrayItem::Write(Writer *writer)
1280 {
1281     ASSERT(GetOffset() == writer->GetOffset());
1282 
1283     if (!writer->Write(static_cast<uint32_t>(items_.size()))) {
1284         return false;
1285     }
1286 
1287     for (auto &item : items_) {
1288         if (!item.Write(writer)) {
1289             return false;
1290         }
1291     }
1292 
1293     return true;
1294 }
1295 
SetDependencyMark()1296 void LiteralArrayItem::SetDependencyMark()
1297 {
1298     BaseItem::SetDependencyMark();
1299     for (auto &it : items_) {
1300         it.SetDependencyMark();
1301     }
1302 }
1303 
BaseFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type,uint32_t accessFlags=0U)1304 BaseFieldItem::BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags = 0U)
1305     : class_(cls), name_(name), type_(type), accessFlags_(accessFlags)
1306 {
1307     AddIndexDependency(cls);
1308     AddIndexDependency(type);
1309 }
1310 
CalculateSize() const1311 size_t BaseFieldItem::CalculateSize() const
1312 {
1313     // class id + type id + name id
1314     return IDX_SIZE + IDX_SIZE + ID_SIZE + leb128::UnsignedEncodingSize(GetAccessFlags());
1315 }
1316 
Write(Writer * writer)1317 bool BaseFieldItem::Write(Writer *writer)
1318 {
1319     ASSERT(GetOffset() == writer->GetOffset());
1320     ASSERT(class_->HasIndex(this));
1321     ASSERT(type_->HasIndex(this));
1322 
1323     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1324         return false;
1325     }
1326 
1327     if (!writer->Write<uint16_t>(type_->GetIndex(this))) {
1328         return false;
1329     }
1330 
1331     if (!writer->Write(name_->GetOffset())) {
1332         return false;
1333     }
1334 
1335     return writer->WriteUleb128(accessFlags_);
1336 }
1337 
SetDependencyMark()1338 void BaseFieldItem::SetDependencyMark()
1339 {
1340     BaseItem::SetDependencyMark();
1341     if (class_ != nullptr) {
1342         if (!class_->GetDependencyMark()) {
1343             class_->SetDependencyMark();
1344         }
1345     }
1346     if (name_ != nullptr) {
1347         name_->SetDependencyMark();
1348     }
1349     if (type_ != nullptr) {
1350         type_->SetDependencyMark();
1351     }
1352 }
1353 
FieldItem(ClassItem * cls,StringItem * name,TypeItem * type,uint32_t accessFlags)1354 FieldItem::FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags)
1355     : BaseFieldItem(cls, name, type, accessFlags)
1356 {
1357 }
1358 
SetValue(ValueItem * value)1359 void FieldItem::SetValue(ValueItem *value)
1360 {
1361     value_ = value;
1362     value_->SetNeedsEmit(!value_->Is32bit());
1363 }
1364 
CalculateSize() const1365 size_t FieldItem::CalculateSize() const
1366 {
1367     size_t size = BaseFieldItem::CalculateSize();
1368 
1369     if (value_ != nullptr) {
1370         if (value_->GetType() == ValueItem::Type::INTEGER) {
1371             size += TAG_SIZE + value_->GetAsScalar()->GetSLeb128EncodedSize();
1372         } else {
1373             size += TAG_SIZE + ID_SIZE;
1374         }
1375     }
1376 
1377     size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
1378     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
1379     size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
1380     size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
1381 
1382     size += TAG_SIZE;  // null tag
1383 
1384     return size;
1385 }
1386 
WriteValue(Writer * writer)1387 bool FieldItem::WriteValue(Writer *writer)
1388 {
1389     if (value_ == nullptr) {
1390         return true;
1391     }
1392 
1393     if (value_->GetType() == ValueItem::Type::INTEGER) {
1394         auto v = static_cast<int32_t>(value_->GetAsScalar()->GetValue<uint32_t>());
1395         if (!WriteSlebTaggedValue(writer, FieldTag::INT_VALUE, v)) {
1396             return false;
1397         }
1398     } else if (value_->GetType() == ValueItem::Type::FLOAT) {
1399         auto v = bit_cast<uint32_t>(value_->GetAsScalar()->GetValue<float>());
1400         if (!WriteTaggedValue(writer, FieldTag::VALUE, v)) {
1401             return false;
1402         }
1403     } else if (value_->GetType() == ValueItem::Type::ID) {
1404         auto id = value_->GetAsScalar()->GetId();
1405         ASSERT(id.GetOffset() != 0);
1406         if (!WriteTaggedValue(writer, FieldTag::VALUE, id.GetOffset())) {
1407             return false;
1408         }
1409     } else {
1410         ASSERT(!value_->Is32bit());
1411         if (!WriteIdTaggedValue(writer, FieldTag::VALUE, value_)) {
1412             return false;
1413         }
1414     }
1415 
1416     return true;
1417 }
1418 
WriteAnnotations(Writer * writer)1419 bool FieldItem::WriteAnnotations(Writer *writer)
1420 {
1421     for (auto runtimeAnnotation : runtimeAnnotations_) {
1422         if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
1423             return false;
1424         }
1425     }
1426 
1427     for (auto annotation : annotations_) {
1428         if (!WriteIdTaggedValue(writer, FieldTag::ANNOTATION, annotation)) {
1429             return false;
1430         }
1431     }
1432 
1433     for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
1434         if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
1435             return false;
1436         }
1437     }
1438 
1439     for (auto typeAnnotation : typeAnnotations_) {
1440         if (!WriteIdTaggedValue(writer, FieldTag::TYPE_ANNOTATION, typeAnnotation)) {
1441             return false;
1442         }
1443     }
1444 
1445     return true;
1446 }
1447 
WriteTaggedData(Writer * writer)1448 bool FieldItem::WriteTaggedData(Writer *writer)
1449 {
1450     if (!WriteValue(writer)) {
1451         return false;
1452     }
1453 
1454     if (!WriteAnnotations(writer)) {
1455         return false;
1456     }
1457 
1458     return writer->WriteByte(static_cast<uint8_t>(FieldTag::NOTHING));
1459 }
1460 
Write(Writer * writer)1461 bool FieldItem::Write(Writer *writer)
1462 {
1463     if (!BaseFieldItem::Write(writer)) {
1464         return false;
1465     }
1466 
1467     return WriteTaggedData(writer);
1468 }
1469 
SetDependencyMark()1470 void FieldItem::SetDependencyMark()
1471 {
1472     BaseFieldItem::SetDependencyMark();
1473     if (value_ != nullptr) {
1474         value_->SetDependencyMark();
1475     }
1476     for (auto &item : annotations_) {
1477         item->SetDependencyMark();
1478     }
1479     for (auto &item : runtimeAnnotations_) {
1480         item->SetDependencyMark();
1481     }
1482     for (auto &item : typeAnnotations_) {
1483         item->SetDependencyMark();
1484     }
1485     for (auto &item : runtimeTypeAnnotations_) {
1486         item->SetDependencyMark();
1487     }
1488 }
1489 
CalculateSize() const1490 size_t AnnotationItem::CalculateSize() const
1491 {
1492     // class id + count + (name id + value id) * count + tag size * count
1493     size_t size = IDX_SIZE + sizeof(uint16_t) + (ID_SIZE + ID_SIZE) * elements_.size() + sizeof(uint8_t) * tags_.size();
1494 
1495     return size;
1496 }
1497 
Write(Writer * writer)1498 bool AnnotationItem::Write(Writer *writer)
1499 {
1500     ASSERT(GetOffset() == writer->GetOffset());
1501     ASSERT(class_->HasIndex(this));
1502 
1503     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1504         return false;
1505     }
1506 
1507     if (!writer->Write(static_cast<uint16_t>(elements_.size()))) {
1508         return false;
1509     }
1510 
1511     for (auto elem : elements_) {
1512         ASSERT(elem.GetName()->GetOffset() != 0);
1513         if (!writer->Write(elem.GetName()->GetOffset())) {
1514             return false;
1515         }
1516 
1517         ValueItem *valueItem = elem.GetValue();
1518 
1519         switch (valueItem->GetType()) {
1520             case ValueItem::Type::INTEGER: {
1521                 if (!writer->Write(valueItem->GetAsScalar()->GetValue<uint32_t>())) {
1522                     return false;
1523                 }
1524                 break;
1525             }
1526             case ValueItem::Type::FLOAT: {
1527                 if (!writer->Write(bit_cast<uint32_t>(valueItem->GetAsScalar()->GetValue<float>()))) {
1528                     return false;
1529                 }
1530                 break;
1531             }
1532             case ValueItem::Type::ID: {
1533                 if (!writer->Write(valueItem->GetAsScalar()->GetId().GetOffset())) {
1534                     return false;
1535                 }
1536                 break;
1537             }
1538             default: {
1539                 ASSERT(valueItem->GetOffset() != 0);
1540                 if (!writer->Write(valueItem->GetOffset())) {
1541                     return false;
1542                 }
1543                 break;
1544             }
1545         }
1546     }
1547 
1548     for (auto tag : tags_) {
1549         if (!writer->Write(tag.GetItem())) {
1550             return false;
1551         }
1552     }
1553 
1554     return true;
1555 }
1556 
SetDependencyMark()1557 void AnnotationItem::SetDependencyMark()
1558 {
1559     BaseItem::SetDependencyMark();
1560     if (class_ != nullptr) {
1561         if (!class_->GetDependencyMark()) {
1562             class_->SetDependencyMark();
1563         }
1564     }
1565     for (auto &it : elements_) {
1566         it.SetDependencyMark();
1567     }
1568 }
1569 
EmitEnd()1570 void LineNumberProgramItemBase::EmitEnd()
1571 {
1572     EmitOpcode(Opcode::END_SEQUENCE);
1573 }
1574 
EmitAdvancePc(std::vector<uint8_t> * constantPool,uint32_t value)1575 void LineNumberProgramItemBase::EmitAdvancePc(std::vector<uint8_t> *constantPool, uint32_t value)
1576 {
1577     EmitOpcode(Opcode::ADVANCE_PC);
1578     EmitUleb128(constantPool, value);
1579 }
1580 
EmitAdvanceLine(std::vector<uint8_t> * constantPool,int32_t value)1581 void LineNumberProgramItemBase::EmitAdvanceLine(std::vector<uint8_t> *constantPool, int32_t value)
1582 {
1583     EmitOpcode(Opcode::ADVANCE_LINE);
1584     EmitSleb128(constantPool, value);
1585 }
1586 
EmitColumn(std::vector<uint8_t> * constantPool,uint32_t pcInc,uint32_t column)1587 void LineNumberProgramItemBase::EmitColumn(std::vector<uint8_t> *constantPool, uint32_t pcInc, uint32_t column)
1588 {
1589     if (pcInc != 0U) {
1590         EmitAdvancePc(constantPool, pcInc);
1591     }
1592     EmitOpcode(Opcode::SET_COLUMN);
1593     EmitUleb128(constantPool, column);
1594 }
1595 
EmitStartLocal(std::vector<uint8_t> * constantPool,int32_t registerNumber,StringItem * name,StringItem * type)1596 void LineNumberProgramItemBase::EmitStartLocal(std::vector<uint8_t> *constantPool, int32_t registerNumber,
1597                                                StringItem *name, StringItem *type)
1598 {
1599     EmitStartLocalExtended(constantPool, registerNumber, name, type, nullptr);
1600 }
1601 
EmitStartLocalExtended(std::vector<uint8_t> * constantPool,int32_t registerNumber,StringItem * name,StringItem * type,StringItem * typeSignature)1602 void LineNumberProgramItemBase::EmitStartLocalExtended(std::vector<uint8_t> *constantPool, int32_t registerNumber,
1603                                                        StringItem *name, StringItem *type, StringItem *typeSignature)
1604 {
1605     if (type == nullptr) {
1606         return;
1607     }
1608 
1609     ASSERT(name != nullptr);
1610     ASSERT(name->GetOffset() != 0);
1611     ASSERT(type->GetOffset() != 0);
1612 
1613     EmitOpcode(typeSignature == nullptr ? Opcode::START_LOCAL : Opcode::START_LOCAL_EXTENDED);
1614     EmitRegister(registerNumber);
1615     EmitUleb128(constantPool, name->GetOffset());
1616     EmitUleb128(constantPool, type->GetOffset());
1617 
1618     if (typeSignature != nullptr) {
1619         ASSERT(typeSignature->GetOffset() != 0);
1620         EmitUleb128(constantPool, typeSignature->GetOffset());
1621     }
1622 }
1623 
EmitEndLocal(int32_t registerNumber)1624 void LineNumberProgramItemBase::EmitEndLocal(int32_t registerNumber)
1625 {
1626     EmitOpcode(Opcode::END_LOCAL);
1627     EmitRegister(registerNumber);
1628 }
1629 
EmitRestartLocal(int32_t registerNumber)1630 void LineNumberProgramItemBase::EmitRestartLocal(int32_t registerNumber)
1631 {
1632     EmitOpcode(Opcode::RESTART_LOCAL);
1633     EmitRegister(registerNumber);
1634 }
1635 
EmitSpecialOpcode(uint32_t pcInc,int32_t lineInc)1636 bool LineNumberProgramItemBase::EmitSpecialOpcode(uint32_t pcInc, int32_t lineInc)
1637 {
1638     if (lineInc < LINE_BASE || (lineInc - LINE_BASE) >= LINE_RANGE) {
1639         return false;
1640     }
1641 
1642     auto opcode = static_cast<size_t>(lineInc - LINE_BASE) + static_cast<size_t>(pcInc * LINE_RANGE) + OPCODE_BASE;
1643     if (opcode > std::numeric_limits<uint8_t>::max()) {
1644         return false;
1645     }
1646 
1647     EmitOpcode(static_cast<uint8_t>(opcode));
1648     return true;
1649 }
1650 
EmitPrologueEnd()1651 void LineNumberProgramItemBase::EmitPrologueEnd()
1652 {
1653     EmitOpcode(Opcode::SET_PROLOGUE_END);
1654 }
1655 
EmitEpilogueBegin()1656 void LineNumberProgramItemBase::EmitEpilogueBegin()
1657 {
1658     EmitOpcode(Opcode::SET_EPILOGUE_BEGIN);
1659 }
1660 
EmitSetFile(std::vector<uint8_t> * constantPool,StringItem * sourceFile)1661 void LineNumberProgramItemBase::EmitSetFile(std::vector<uint8_t> *constantPool, StringItem *sourceFile)
1662 {
1663     ASSERT(sourceFile);
1664     ASSERT(sourceFile->GetOffset() != 0);
1665 
1666     EmitOpcode(Opcode::SET_FILE);
1667     EmitUleb128(constantPool, sourceFile->GetOffset());
1668 }
1669 
EmitSetSourceCode(std::vector<uint8_t> * constantPool,StringItem * sourceCode)1670 void LineNumberProgramItemBase::EmitSetSourceCode(std::vector<uint8_t> *constantPool, StringItem *sourceCode)
1671 {
1672     ASSERT(sourceCode);
1673     ASSERT(sourceCode->GetOffset() != 0);
1674 
1675     EmitOpcode(Opcode::SET_SOURCE_CODE);
1676     EmitUleb128(constantPool, sourceCode->GetOffset());
1677 }
1678 
EmitOpcode(Opcode opcode)1679 void LineNumberProgramItemBase::EmitOpcode(Opcode opcode)
1680 {
1681     EmitOpcode(static_cast<uint8_t>(opcode));
1682 }
1683 
1684 /* static */
EmitUleb128(std::vector<uint8_t> * data,uint32_t value)1685 void LineNumberProgramItemBase::EmitUleb128(std::vector<uint8_t> *data, uint32_t value)
1686 {
1687     ASSERT(data);
1688 
1689     size_t n = leb128::UnsignedEncodingSize(value);
1690     std::vector<uint8_t> out(n);
1691     leb128::EncodeUnsigned(value, out.data());
1692     data->insert(data->end(), out.cbegin(), out.cend());
1693 }
1694 
1695 /* static */
EmitSleb128(std::vector<uint8_t> * data,int32_t value)1696 void LineNumberProgramItemBase::EmitSleb128(std::vector<uint8_t> *data, int32_t value)
1697 {
1698     ASSERT(data);
1699 
1700     size_t n = leb128::SignedEncodingSize(value);
1701     std::vector<uint8_t> out(n);
1702     leb128::EncodeSigned(value, out.data());
1703     data->insert(data->end(), out.cbegin(), out.cend());
1704 }
1705 
EmitOpcode(uint8_t opcode)1706 void LineNumberProgramItem::EmitOpcode(uint8_t opcode)
1707 {
1708     data_.push_back(opcode);
1709 }
1710 
EmitRegister(int32_t registerNumber)1711 void LineNumberProgramItem::EmitRegister(int32_t registerNumber)
1712 {
1713     EmitSleb128(&data_, registerNumber);
1714 }
1715 
CalculateSize() const1716 size_t LineNumberProgramItem::CalculateSize() const
1717 {
1718     return data_.size();
1719 }
1720 
Write(Writer * writer)1721 bool LineNumberProgramItem::Write(Writer *writer)
1722 {
1723     ASSERT(GetOffset() == writer->GetOffset());
1724 
1725     return writer->WriteBytes(data_);
1726 }
1727 
SetData(std::vector<uint8_t> && data)1728 void LineNumberProgramItem::SetData(std::vector<uint8_t> &&data)
1729 {
1730     data_ = std::move(data);
1731 }
1732 
CalculateSize() const1733 size_t DebugInfoItem::CalculateSize() const
1734 {
1735     size_t n = leb128::UnsignedEncodingSize(lineNum_) + leb128::UnsignedEncodingSize(parameters_.size());
1736 
1737     for (auto *p : parameters_) {
1738         ASSERT(p == nullptr || p->GetOffset() != 0);
1739         n += leb128::UnsignedEncodingSize(p == nullptr ? 0 : p->GetOffset());
1740     }
1741 
1742     n += leb128::UnsignedEncodingSize(constantPool_.size());
1743     n += constantPool_.size();
1744 
1745     n += leb128::UnsignedEncodingSize(program_->GetIndex(this));
1746 
1747     return n;
1748 }
1749 
Write(Writer * writer)1750 bool DebugInfoItem::Write(Writer *writer)
1751 {
1752     ASSERT(GetOffset() == writer->GetOffset());
1753 
1754     if (!writer->WriteUleb128(lineNum_)) {
1755         return false;
1756     }
1757 
1758     if (!writer->WriteUleb128(parameters_.size())) {
1759         return false;
1760     }
1761 
1762     for (auto *p : parameters_) {
1763         ASSERT(p == nullptr || p->GetOffset() != 0);
1764 
1765         if (!writer->WriteUleb128(p == nullptr ? 0 : p->GetOffset())) {
1766             return false;
1767         }
1768     }
1769 
1770     if (!writer->WriteUleb128(constantPool_.size())) {
1771         return false;
1772     }
1773 
1774     if (!writer->WriteBytes(constantPool_)) {
1775         return false;
1776     }
1777 
1778     ASSERT(program_ != nullptr);
1779     ASSERT(program_->HasIndex(this));
1780 
1781     return writer->WriteUleb128(program_->GetIndex(this));
1782 }
1783 
Dump(std::ostream & os) const1784 void DebugInfoItem::Dump(std::ostream &os) const
1785 {
1786     os << "line_start = " << lineNum_ << std::endl;
1787 
1788     os << "num_parameters = " << parameters_.size() << std::endl;
1789     for (auto *item : parameters_) {
1790         if (item != nullptr) {
1791             os << "  string_item[" << item->GetOffset() << "]" << std::endl;
1792         } else {
1793             os << "  string_item[INVALID_OFFSET]" << std::endl;
1794         }
1795     }
1796 
1797     os << "constant_pool = [";
1798     for (size_t i = 0; i < constantPool_.size(); i++) {
1799         size_t b = constantPool_[i];
1800         os << "0x" << std::setfill('0') << std::setw(2U) << std::right << std::hex << b << std::dec;
1801         if (i < constantPool_.size() - 1) {
1802             os << ", ";
1803         }
1804     }
1805     os << "]" << std::endl;
1806 
1807     os << "line_number_program = line_number_program_idx[";
1808     if (program_ != nullptr && program_->HasIndex(this)) {
1809         os << program_->GetIndex(this);
1810     } else {
1811         os << "NO_INDEX";
1812     }
1813     os << "]";
1814 }
1815 
Write(Writer * writer)1816 bool MethodHandleItem::Write(Writer *writer)
1817 {
1818     ASSERT(GetOffset() == writer->GetOffset());
1819 
1820     if (!writer->WriteByte(static_cast<uint8_t>(type_))) {
1821         return false;
1822     }
1823 
1824     return writer->WriteUleb128(entity_->GetOffset());
1825 }
1826 
1827 }  // namespace ark::panda_file
1828