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 ¶m : 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 ¶mAnnotations : 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 ¶mAnnotations : 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> ¶ms)
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