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