1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #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 panda::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
694 if (!writer->WriteUleb128(typeOff)) {
695 return false;
696 }
697
698 if (!writer->WriteUleb128(handlerPc_)) {
699 return false;
700 }
701
702 if (!writer->WriteUleb128(codeSize_)) {
703 return false;
704 }
705
706 return true;
707 }
708
ComputeLayout()709 void CodeItem::TryBlock::ComputeLayout()
710 {
711 size_t offset = GetOffset();
712 offset += CalculateSizeWithoutCatchBlocks();
713
714 for (auto &catchBlock : catchBlocks_) {
715 catchBlock.SetOffset(offset);
716 catchBlock.ComputeLayout();
717 offset += catchBlock.GetSize();
718 }
719 }
720
CalculateSizeWithoutCatchBlocks() const721 size_t CodeItem::TryBlock::CalculateSizeWithoutCatchBlocks() const
722 {
723 return leb128::UnsignedEncodingSize(startPc_) + leb128::UnsignedEncodingSize(length_) +
724 leb128::UnsignedEncodingSize(catchBlocks_.size());
725 }
726
CalculateSize() const727 size_t CodeItem::TryBlock::CalculateSize() const
728 {
729 size_t size = CalculateSizeWithoutCatchBlocks();
730
731 for (auto &catchBlock : catchBlocks_) {
732 size += catchBlock.GetSize();
733 }
734
735 return size;
736 }
737
Write(Writer * writer)738 bool CodeItem::TryBlock::Write(Writer *writer)
739 {
740 ASSERT(GetOffset() == writer->GetOffset());
741
742 if (!writer->WriteUleb128(startPc_)) {
743 return false;
744 }
745
746 if (!writer->WriteUleb128(length_)) {
747 return false;
748 }
749
750 if (!writer->WriteUleb128(catchBlocks_.size())) {
751 return false;
752 }
753
754 for (auto &catchBlock : catchBlocks_) {
755 if (!catchBlock.Write(writer)) {
756 return false;
757 }
758 }
759
760 return true;
761 }
762
ComputeLayout()763 void CodeItem::ComputeLayout()
764 {
765 uint32_t offset = GetOffset();
766
767 offset += CalculateSizeWithoutTryBlocks();
768
769 for (auto &tryBlock : tryBlocks_) {
770 tryBlock.SetOffset(offset);
771 tryBlock.ComputeLayout();
772 offset += tryBlock.GetSize();
773 }
774 }
775
CalculateSizeWithoutTryBlocks() const776 size_t CodeItem::CalculateSizeWithoutTryBlocks() const
777 {
778 size_t size = leb128::UnsignedEncodingSize(numVregs_) + leb128::UnsignedEncodingSize(numArgs_) +
779 leb128::UnsignedEncodingSize(instructions_.size()) + leb128::UnsignedEncodingSize(tryBlocks_.size());
780
781 size += instructions_.size();
782
783 return size;
784 }
785
GetCodeSize() const786 size_t CodeItem::GetCodeSize() const
787 {
788 return instructions_.size();
789 }
790
CalculateSize() const791 size_t CodeItem::CalculateSize() const
792 {
793 size_t size = CalculateSizeWithoutTryBlocks();
794
795 for (auto &tryBlock : tryBlocks_) {
796 size += tryBlock.GetSize();
797 }
798
799 return size;
800 }
801
Write(Writer * writer)802 bool CodeItem::Write(Writer *writer)
803 {
804 ASSERT(GetOffset() == writer->GetOffset());
805
806 if (!writer->WriteUleb128(numVregs_)) {
807 return false;
808 }
809
810 if (!writer->WriteUleb128(numArgs_)) {
811 return false;
812 }
813
814 if (!writer->WriteUleb128(instructions_.size())) {
815 return false;
816 }
817
818 if (!writer->WriteUleb128(tryBlocks_.size())) {
819 return false;
820 }
821
822 if (!writer->WriteBytes(instructions_)) {
823 return false;
824 }
825
826 for (auto &tryBlock : tryBlocks_) {
827 if (!tryBlock.Write(writer)) {
828 return false;
829 }
830 }
831
832 return true;
833 }
834
GetAsScalar()835 ScalarValueItem *ValueItem::GetAsScalar()
836 {
837 ASSERT(!IsArray());
838 return static_cast<ScalarValueItem *>(this);
839 }
840
GetAsArray()841 ArrayValueItem *ValueItem::GetAsArray()
842 {
843 ASSERT(IsArray());
844 return static_cast<ArrayValueItem *>(this);
845 }
846
GetULeb128EncodedSize()847 size_t ScalarValueItem::GetULeb128EncodedSize()
848 {
849 switch (GetType()) {
850 case Type::INTEGER:
851 return leb128::UnsignedEncodingSize(GetValue<uint32_t>());
852
853 case Type::LONG:
854 return leb128::UnsignedEncodingSize(GetValue<uint64_t>());
855
856 case Type::ID:
857 return leb128::UnsignedEncodingSize(GetId().GetOffset());
858
859 default:
860 return 0;
861 }
862 }
863
GetSLeb128EncodedSize()864 size_t ScalarValueItem::GetSLeb128EncodedSize()
865 {
866 switch (GetType()) {
867 case Type::INTEGER:
868 return leb128::SignedEncodingSize(static_cast<int32_t>(GetValue<uint32_t>()));
869
870 case Type::LONG:
871 return leb128::SignedEncodingSize(static_cast<int64_t>(GetValue<uint64_t>()));
872
873 default:
874 return 0;
875 }
876 }
877
CalculateSize() const878 size_t ScalarValueItem::CalculateSize() const
879 {
880 size_t size = 0;
881 switch (GetType()) {
882 case Type::INTEGER: {
883 size = sizeof(uint32_t);
884 break;
885 }
886
887 case Type::LONG: {
888 size = sizeof(uint64_t);
889 break;
890 }
891
892 case Type::FLOAT: {
893 size = sizeof(float);
894 break;
895 }
896
897 case Type::DOUBLE: {
898 size = sizeof(double);
899 break;
900 }
901
902 case Type::ID: {
903 size = ID_SIZE;
904 break;
905 }
906 default: {
907 UNREACHABLE();
908 break;
909 }
910 }
911
912 return size;
913 }
914
Alignment()915 size_t ScalarValueItem::Alignment()
916 {
917 return GetSize();
918 }
919
Write(Writer * writer)920 bool ScalarValueItem::Write(Writer *writer)
921 {
922 ASSERT(GetOffset() == writer->GetOffset());
923
924 switch (GetType()) {
925 case Type::INTEGER:
926 return writer->Write(GetValue<uint32_t>());
927
928 case Type::LONG:
929 return writer->Write(GetValue<uint64_t>());
930
931 case Type::FLOAT:
932 return writer->Write(bit_cast<uint32_t>(GetValue<float>()));
933
934 case Type::DOUBLE:
935 return writer->Write(bit_cast<uint64_t>(GetValue<double>()));
936
937 case Type::ID: {
938 ASSERT(GetId().IsValid());
939 return writer->Write(GetId().GetOffset());
940 }
941 default: {
942 UNREACHABLE();
943 break;
944 }
945 }
946
947 return true;
948 }
949
WriteAsUleb128(Writer * writer)950 bool ScalarValueItem::WriteAsUleb128(Writer *writer)
951 {
952 ASSERT(GetOffset() == writer->GetOffset());
953
954 switch (GetType()) {
955 case Type::INTEGER:
956 return writer->WriteUleb128(GetValue<uint32_t>());
957
958 case Type::LONG:
959 return writer->WriteUleb128(GetValue<uint64_t>());
960
961 case Type::ID: {
962 ASSERT(GetId().IsValid());
963 return writer->WriteUleb128(GetId().GetOffset());
964 }
965 default:
966 return false;
967 }
968 }
969
CalculateSize() const970 size_t ArrayValueItem::CalculateSize() const
971 {
972 size_t size = leb128::UnsignedEncodingSize(items_.size()) + items_.size() * GetComponentSize();
973 return size;
974 }
975
ComputeLayout()976 void ArrayValueItem::ComputeLayout()
977 {
978 uint32_t offset = GetOffset();
979
980 ASSERT(offset != 0);
981
982 offset += leb128::UnsignedEncodingSize(items_.size());
983
984 for (auto &item : items_) {
985 item.SetOffset(offset);
986 offset += GetComponentSize();
987 }
988 }
989
Write(Writer * writer)990 bool ArrayValueItem::Write(Writer *writer)
991 {
992 ASSERT(GetOffset() == writer->GetOffset());
993
994 if (!writer->WriteUleb128(items_.size())) {
995 return false;
996 }
997
998 switch (componentType_.GetId()) {
999 case panda_file::Type::TypeId::U1:
1000 case panda_file::Type::TypeId::I8:
1001 case panda_file::Type::TypeId::U8: {
1002 for (auto &item : items_) {
1003 auto value = static_cast<uint8_t>(item.GetValue<uint32_t>());
1004 if (!writer->Write(value)) {
1005 return false;
1006 }
1007 }
1008 break;
1009 }
1010 case panda_file::Type::TypeId::I16:
1011 case panda_file::Type::TypeId::U16: {
1012 for (auto &item : items_) {
1013 auto value = static_cast<uint16_t>(item.GetValue<uint32_t>());
1014 if (!writer->Write(value)) {
1015 return false;
1016 }
1017 }
1018 break;
1019 }
1020 default: {
1021 for (auto &item : items_) {
1022 if (!item.Write(writer)) {
1023 return false;
1024 }
1025 }
1026 break;
1027 }
1028 }
1029
1030 return true;
1031 }
1032
GetComponentSize() const1033 size_t ArrayValueItem::GetComponentSize() const
1034 {
1035 switch (componentType_.GetId()) {
1036 case panda_file::Type::TypeId::U1:
1037 case panda_file::Type::TypeId::I8:
1038 case panda_file::Type::TypeId::U8:
1039 return sizeof(uint8_t);
1040 case panda_file::Type::TypeId::I16:
1041 case panda_file::Type::TypeId::U16:
1042 return sizeof(uint16_t);
1043 case panda_file::Type::TypeId::I32:
1044 case panda_file::Type::TypeId::U32:
1045 case panda_file::Type::TypeId::F32:
1046 return sizeof(uint32_t);
1047 case panda_file::Type::TypeId::I64:
1048 case panda_file::Type::TypeId::U64:
1049 case panda_file::Type::TypeId::F64:
1050 return sizeof(uint64_t);
1051 case panda_file::Type::TypeId::REFERENCE:
1052 return ID_SIZE;
1053 case panda_file::Type::TypeId::VOID:
1054 return 0;
1055 default: {
1056 UNREACHABLE();
1057 // Avoid cpp warning
1058 return 0;
1059 }
1060 }
1061 }
1062
CalculateSize() const1063 size_t LiteralItem::CalculateSize() const
1064 {
1065 size_t size = 0;
1066 switch (GetType()) {
1067 case Type::B1: {
1068 size = sizeof(uint8_t);
1069 break;
1070 }
1071
1072 case Type::B2: {
1073 size = sizeof(uint16_t);
1074 break;
1075 }
1076
1077 case Type::B4: {
1078 size = sizeof(uint32_t);
1079 break;
1080 }
1081
1082 case Type::B8: {
1083 size = sizeof(uint64_t);
1084 break;
1085 }
1086
1087 case Type::STRING:
1088 case Type::METHOD: {
1089 size = ID_SIZE;
1090 break;
1091 }
1092
1093 default: {
1094 UNREACHABLE();
1095 break;
1096 }
1097 }
1098
1099 return size;
1100 }
1101
Alignment()1102 size_t LiteralItem::Alignment()
1103 {
1104 return GetSize();
1105 }
1106
Write(Writer * writer)1107 bool LiteralItem::Write(Writer *writer)
1108 {
1109 ASSERT(GetOffset() == writer->GetOffset());
1110
1111 switch (GetType()) {
1112 case Type::B1: {
1113 return writer->Write(GetValue<uint8_t>());
1114 }
1115 case Type::B2: {
1116 return writer->Write(GetValue<uint16_t>());
1117 }
1118 case Type::B4: {
1119 return writer->Write(GetValue<uint32_t>());
1120 }
1121 case Type::B8: {
1122 return writer->Write(GetValue<uint64_t>());
1123 }
1124 case Type::STRING: {
1125 ASSERT(GetId().IsValid());
1126 return writer->Write(GetId().GetOffset());
1127 }
1128 case Type::METHOD: {
1129 ASSERT(GetMethodId().IsValid());
1130 return writer->Write(GetMethodId().GetOffset());
1131 }
1132 default: {
1133 UNREACHABLE();
1134 break;
1135 }
1136 }
1137
1138 return true;
1139 }
1140
AddItems(const std::vector<LiteralItem> & item)1141 void LiteralArrayItem::AddItems(const std::vector<LiteralItem> &item)
1142 {
1143 items_.assign(item.begin(), item.end());
1144 }
1145
CalculateSize() const1146 size_t LiteralArrayItem::CalculateSize() const
1147 {
1148 size_t size = sizeof(uint32_t);
1149 for (auto &item : items_) {
1150 size += item.CalculateSize();
1151 }
1152
1153 return size;
1154 }
1155
ComputeLayout()1156 void LiteralArrayItem::ComputeLayout()
1157 {
1158 uint32_t offset = GetOffset();
1159
1160 ASSERT(offset != 0);
1161
1162 offset += sizeof(uint32_t);
1163
1164 for (auto &item : items_) {
1165 item.SetOffset(offset);
1166 offset += item.CalculateSize();
1167 }
1168 }
1169
Write(Writer * writer)1170 bool LiteralArrayItem::Write(Writer *writer)
1171 {
1172 ASSERT(GetOffset() == writer->GetOffset());
1173
1174 if (!writer->Write(static_cast<uint32_t>(items_.size()))) {
1175 return false;
1176 }
1177
1178 for (auto &item : items_) {
1179 if (!item.Write(writer)) {
1180 return false;
1181 }
1182 }
1183
1184 return true;
1185 }
1186
BaseFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type)1187 BaseFieldItem::BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type)
1188 : class_(cls), name_(name), type_(type)
1189 {
1190 AddIndexDependency(cls);
1191 AddIndexDependency(type);
1192 }
1193
CalculateSize() const1194 size_t BaseFieldItem::CalculateSize() const
1195 {
1196 // class id + type id + name id
1197 return IDX_SIZE + IDX_SIZE + ID_SIZE;
1198 }
1199
Write(Writer * writer)1200 bool BaseFieldItem::Write(Writer *writer)
1201 {
1202 ASSERT(GetOffset() == writer->GetOffset());
1203 ASSERT(class_->HasIndex(this));
1204 ASSERT(type_->HasIndex(this));
1205
1206 if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1207 return false;
1208 }
1209
1210 if (!writer->Write<uint16_t>(type_->GetIndex(this))) {
1211 return false;
1212 }
1213
1214 return writer->Write(name_->GetOffset());
1215 }
1216
FieldItem(ClassItem * cls,StringItem * name,TypeItem * type,uint32_t accessFlags)1217 FieldItem::FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags)
1218 : BaseFieldItem(cls, name, type), accessFlags_(accessFlags)
1219 {
1220 }
1221
SetValue(ValueItem * value)1222 void FieldItem::SetValue(ValueItem *value)
1223 {
1224 value_ = value;
1225 value_->SetNeedsEmit(!value_->Is32bit());
1226 }
1227
CalculateSize() const1228 size_t FieldItem::CalculateSize() const
1229 {
1230 size_t size = BaseFieldItem::CalculateSize() + leb128::UnsignedEncodingSize(accessFlags_);
1231
1232 if (value_ != nullptr) {
1233 if (value_->GetType() == ValueItem::Type::INTEGER) {
1234 size += TAG_SIZE + value_->GetAsScalar()->GetSLeb128EncodedSize();
1235 } else {
1236 size += TAG_SIZE + ID_SIZE;
1237 }
1238 }
1239
1240 size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
1241 size += (TAG_SIZE + ID_SIZE) * annotations_.size();
1242 size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
1243 size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
1244
1245 size += TAG_SIZE; // null tag
1246
1247 return size;
1248 }
1249
WriteValue(Writer * writer)1250 bool FieldItem::WriteValue(Writer *writer)
1251 {
1252 if (value_ == nullptr) {
1253 return true;
1254 }
1255
1256 if (value_->GetType() == ValueItem::Type::INTEGER) {
1257 auto v = static_cast<int32_t>(value_->GetAsScalar()->GetValue<uint32_t>());
1258 if (!WriteSlebTaggedValue(writer, FieldTag::INT_VALUE, v)) {
1259 return false;
1260 }
1261 } else if (value_->GetType() == ValueItem::Type::FLOAT) {
1262 auto v = bit_cast<uint32_t>(value_->GetAsScalar()->GetValue<float>());
1263 if (!WriteTaggedValue(writer, FieldTag::VALUE, v)) {
1264 return false;
1265 }
1266 } else if (value_->GetType() == ValueItem::Type::ID) {
1267 auto id = value_->GetAsScalar()->GetId();
1268 ASSERT(id.GetOffset() != 0);
1269 if (!WriteTaggedValue(writer, FieldTag::VALUE, id.GetOffset())) {
1270 return false;
1271 }
1272 } else {
1273 ASSERT(!value_->Is32bit());
1274 if (!WriteIdTaggedValue(writer, FieldTag::VALUE, value_)) {
1275 return false;
1276 }
1277 }
1278
1279 return true;
1280 }
1281
WriteAnnotations(Writer * writer)1282 bool FieldItem::WriteAnnotations(Writer *writer)
1283 {
1284 for (auto runtimeAnnotation : runtimeAnnotations_) {
1285 if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
1286 return false;
1287 }
1288 }
1289
1290 for (auto annotation : annotations_) {
1291 if (!WriteIdTaggedValue(writer, FieldTag::ANNOTATION, annotation)) {
1292 return false;
1293 }
1294 }
1295
1296 for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
1297 if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
1298 return false;
1299 }
1300 }
1301
1302 for (auto typeAnnotation : typeAnnotations_) {
1303 if (!WriteIdTaggedValue(writer, FieldTag::TYPE_ANNOTATION, typeAnnotation)) {
1304 return false;
1305 }
1306 }
1307
1308 return true;
1309 }
1310
WriteTaggedData(Writer * writer)1311 bool FieldItem::WriteTaggedData(Writer *writer)
1312 {
1313 if (!WriteValue(writer)) {
1314 return false;
1315 }
1316
1317 if (!WriteAnnotations(writer)) {
1318 return false;
1319 }
1320
1321 return writer->WriteByte(static_cast<uint8_t>(FieldTag::NOTHING));
1322 }
1323
Write(Writer * writer)1324 bool FieldItem::Write(Writer *writer)
1325 {
1326 if (!BaseFieldItem::Write(writer)) {
1327 return false;
1328 }
1329
1330 if (!writer->WriteUleb128(accessFlags_)) {
1331 return false;
1332 }
1333
1334 return WriteTaggedData(writer);
1335 }
1336
CalculateSize() const1337 size_t AnnotationItem::CalculateSize() const
1338 {
1339 // class id + count + (name id + value id) * count + tag size * count
1340 size_t size = IDX_SIZE + sizeof(uint16_t) + (ID_SIZE + ID_SIZE) * elements_.size() + sizeof(uint8_t) * tags_.size();
1341
1342 return size;
1343 }
1344
Write(Writer * writer)1345 bool AnnotationItem::Write(Writer *writer)
1346 {
1347 ASSERT(GetOffset() == writer->GetOffset());
1348 ASSERT(class_->HasIndex(this));
1349
1350 if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1351 return false;
1352 }
1353
1354 if (!writer->Write(static_cast<uint16_t>(elements_.size()))) {
1355 return false;
1356 }
1357
1358 for (auto elem : elements_) {
1359 ASSERT(elem.GetName()->GetOffset() != 0);
1360 if (!writer->Write(elem.GetName()->GetOffset())) {
1361 return false;
1362 }
1363
1364 ValueItem *valueItem = elem.GetValue();
1365
1366 switch (valueItem->GetType()) {
1367 case ValueItem::Type::INTEGER: {
1368 if (!writer->Write(valueItem->GetAsScalar()->GetValue<uint32_t>())) {
1369 return false;
1370 }
1371 break;
1372 }
1373 case ValueItem::Type::FLOAT: {
1374 if (!writer->Write(bit_cast<uint32_t>(valueItem->GetAsScalar()->GetValue<float>()))) {
1375 return false;
1376 }
1377 break;
1378 }
1379 case ValueItem::Type::ID: {
1380 if (!writer->Write(valueItem->GetAsScalar()->GetId().GetOffset())) {
1381 return false;
1382 }
1383 break;
1384 }
1385 default: {
1386 ASSERT(valueItem->GetOffset() != 0);
1387 if (!writer->Write(valueItem->GetOffset())) {
1388 return false;
1389 }
1390 break;
1391 }
1392 }
1393 }
1394
1395 for (auto tag : tags_) {
1396 if (!writer->Write(tag.GetItem())) {
1397 return false;
1398 }
1399 }
1400
1401 return true;
1402 }
1403
EmitEnd()1404 void LineNumberProgramItem::EmitEnd()
1405 {
1406 EmitOpcode(Opcode::END_SEQUENCE);
1407 }
1408
EmitAdvancePc(std::vector<uint8_t> * constantPool,uint32_t value)1409 void LineNumberProgramItem::EmitAdvancePc(std::vector<uint8_t> *constantPool, uint32_t value)
1410 {
1411 EmitOpcode(Opcode::ADVANCE_PC);
1412 EmitUleb128(constantPool, value);
1413 }
1414
EmitAdvanceLine(std::vector<uint8_t> * constantPool,int32_t value)1415 void LineNumberProgramItem::EmitAdvanceLine(std::vector<uint8_t> *constantPool, int32_t value)
1416 {
1417 EmitOpcode(Opcode::ADVANCE_LINE);
1418 EmitSleb128(constantPool, value);
1419 }
1420
EmitColumn(std::vector<uint8_t> * constantPool,uint32_t pcInc,uint32_t column)1421 void LineNumberProgramItem::EmitColumn(std::vector<uint8_t> *constantPool, uint32_t pcInc, uint32_t column)
1422 {
1423 if (pcInc != 0U) {
1424 EmitAdvancePc(constantPool, pcInc);
1425 }
1426 EmitOpcode(Opcode::SET_COLUMN);
1427 EmitUleb128(constantPool, column);
1428 }
1429
EmitStartLocal(std::vector<uint8_t> * constantPool,int32_t registerNumber,StringItem * name,StringItem * type)1430 void LineNumberProgramItem::EmitStartLocal(std::vector<uint8_t> *constantPool, int32_t registerNumber, StringItem *name,
1431 StringItem *type)
1432 {
1433 EmitStartLocalExtended(constantPool, registerNumber, name, type, nullptr);
1434 }
1435
EmitStartLocalExtended(std::vector<uint8_t> * constantPool,int32_t registerNumber,StringItem * name,StringItem * type,StringItem * typeSignature)1436 void LineNumberProgramItem::EmitStartLocalExtended(std::vector<uint8_t> *constantPool, int32_t registerNumber,
1437 StringItem *name, StringItem *type, StringItem *typeSignature)
1438 {
1439 if (type == nullptr) {
1440 return;
1441 }
1442
1443 ASSERT(name != nullptr);
1444 ASSERT(name->GetOffset() != 0);
1445 ASSERT(type->GetOffset() != 0);
1446
1447 EmitOpcode(typeSignature == nullptr ? Opcode::START_LOCAL : Opcode::START_LOCAL_EXTENDED);
1448 EmitRegister(registerNumber);
1449 EmitUleb128(constantPool, name->GetOffset());
1450 EmitUleb128(constantPool, type->GetOffset());
1451
1452 if (typeSignature != nullptr) {
1453 ASSERT(typeSignature->GetOffset() != 0);
1454 EmitUleb128(constantPool, typeSignature->GetOffset());
1455 }
1456 }
1457
EmitEndLocal(int32_t registerNumber)1458 void LineNumberProgramItem::EmitEndLocal(int32_t registerNumber)
1459 {
1460 EmitOpcode(Opcode::END_LOCAL);
1461 EmitRegister(registerNumber);
1462 }
1463
EmitRestartLocal(int32_t registerNumber)1464 void LineNumberProgramItem::EmitRestartLocal(int32_t registerNumber)
1465 {
1466 EmitOpcode(Opcode::RESTART_LOCAL);
1467 EmitRegister(registerNumber);
1468 }
1469
EmitSpecialOpcode(uint32_t pcInc,int32_t lineInc)1470 bool LineNumberProgramItem::EmitSpecialOpcode(uint32_t pcInc, int32_t lineInc)
1471 {
1472 if (lineInc < LINE_BASE || (lineInc - LINE_BASE) >= LINE_RANGE) {
1473 return false;
1474 }
1475
1476 auto opcode = static_cast<size_t>(lineInc - LINE_BASE) + static_cast<size_t>(pcInc * LINE_RANGE) + OPCODE_BASE;
1477 if (opcode > std::numeric_limits<uint8_t>::max()) {
1478 return false;
1479 }
1480
1481 data_.push_back(static_cast<uint8_t>(opcode));
1482 return true;
1483 }
1484
EmitPrologEnd()1485 void LineNumberProgramItem::EmitPrologEnd()
1486 {
1487 EmitOpcode(Opcode::SET_PROLOGUE_END);
1488 }
1489
EmitEpilogBegin()1490 void LineNumberProgramItem::EmitEpilogBegin()
1491 {
1492 EmitOpcode(Opcode::SET_EPILOGUE_BEGIN);
1493 }
1494
EmitSetFile(std::vector<uint8_t> * constantPool,StringItem * sourceFile)1495 void LineNumberProgramItem::EmitSetFile(std::vector<uint8_t> *constantPool, StringItem *sourceFile)
1496 {
1497 EmitOpcode(Opcode::SET_FILE);
1498
1499 if (sourceFile == nullptr) {
1500 return;
1501 }
1502
1503 ASSERT(sourceFile->GetOffset() != 0);
1504
1505 EmitUleb128(constantPool, sourceFile->GetOffset());
1506 }
1507
EmitSetSourceCode(std::vector<uint8_t> * constantPool,StringItem * sourceCode)1508 void LineNumberProgramItem::EmitSetSourceCode(std::vector<uint8_t> *constantPool, StringItem *sourceCode)
1509 {
1510 EmitOpcode(Opcode::SET_SOURCE_CODE);
1511
1512 if (sourceCode == nullptr) {
1513 return;
1514 }
1515
1516 ASSERT(sourceCode->GetOffset() != 0);
1517 EmitUleb128(constantPool, sourceCode->GetOffset());
1518 }
1519
EmitOpcode(Opcode opcode)1520 void LineNumberProgramItem::EmitOpcode(Opcode opcode)
1521 {
1522 data_.push_back(static_cast<uint8_t>(opcode));
1523 }
1524
EmitRegister(int32_t registerNumber)1525 void LineNumberProgramItem::EmitRegister(int32_t registerNumber)
1526 {
1527 EmitSleb128(&data_, registerNumber);
1528 }
1529
1530 /* static */
EmitUleb128(std::vector<uint8_t> * data,uint32_t value)1531 void LineNumberProgramItem::EmitUleb128(std::vector<uint8_t> *data, uint32_t value)
1532 {
1533 size_t n = leb128::UnsignedEncodingSize(value);
1534 std::vector<uint8_t> out(n);
1535 leb128::EncodeUnsigned(value, out.data());
1536
1537 if (data == nullptr) {
1538 return;
1539 }
1540
1541 data->insert(data->end(), out.cbegin(), out.cend());
1542 }
1543
1544 /* static */
EmitSleb128(std::vector<uint8_t> * data,int32_t value)1545 void LineNumberProgramItem::EmitSleb128(std::vector<uint8_t> *data, int32_t value)
1546 {
1547 size_t n = leb128::SignedEncodingSize(value);
1548 std::vector<uint8_t> out(n);
1549 leb128::EncodeSigned(value, out.data());
1550 data->insert(data->end(), out.cbegin(), out.cend());
1551 }
1552
CalculateSize() const1553 size_t LineNumberProgramItem::CalculateSize() const
1554 {
1555 return data_.size();
1556 }
1557
Write(Writer * writer)1558 bool LineNumberProgramItem::Write(Writer *writer)
1559 {
1560 ASSERT(GetOffset() == writer->GetOffset());
1561
1562 return writer->WriteBytes(data_);
1563 }
1564
SetData(std::vector<uint8_t> && data)1565 void LineNumberProgramItem::SetData(std::vector<uint8_t> &&data)
1566 {
1567 data_ = std::move(data);
1568 }
1569
CalculateSize() const1570 size_t DebugInfoItem::CalculateSize() const
1571 {
1572 size_t n = leb128::UnsignedEncodingSize(lineNum_) + leb128::UnsignedEncodingSize(parameters_.size());
1573
1574 for (auto *p : parameters_) {
1575 ASSERT(p == nullptr || p->GetOffset() != 0);
1576 n += leb128::UnsignedEncodingSize(p == nullptr ? 0 : p->GetOffset());
1577 }
1578
1579 n += leb128::UnsignedEncodingSize(constantPool_.size());
1580 n += constantPool_.size();
1581
1582 n += leb128::UnsignedEncodingSize(program_->GetIndex(this));
1583
1584 return n;
1585 }
1586
Write(Writer * writer)1587 bool DebugInfoItem::Write(Writer *writer)
1588 {
1589 ASSERT(GetOffset() == writer->GetOffset());
1590
1591 if (!writer->WriteUleb128(lineNum_)) {
1592 return false;
1593 }
1594
1595 if (!writer->WriteUleb128(parameters_.size())) {
1596 return false;
1597 }
1598
1599 for (auto *p : parameters_) {
1600 ASSERT(p == nullptr || p->GetOffset() != 0);
1601
1602 if (!writer->WriteUleb128(p == nullptr ? 0 : p->GetOffset())) {
1603 return false;
1604 }
1605 }
1606
1607 if (!writer->WriteUleb128(constantPool_.size())) {
1608 return false;
1609 }
1610
1611 if (!writer->WriteBytes(constantPool_)) {
1612 return false;
1613 }
1614
1615 ASSERT(program_ != nullptr);
1616 ASSERT(program_->HasIndex(this));
1617
1618 return writer->WriteUleb128(program_->GetIndex(this));
1619 }
1620
Dump(std::ostream & os) const1621 void DebugInfoItem::Dump(std::ostream &os) const
1622 {
1623 os << "line_start = " << lineNum_ << std::endl;
1624
1625 os << "num_parameters = " << parameters_.size() << std::endl;
1626 for (auto *item : parameters_) {
1627 if (item != nullptr) {
1628 os << " string_item[" << item->GetOffset() << "]" << std::endl;
1629 } else {
1630 os << " string_item[INVALID_OFFSET]" << std::endl;
1631 }
1632 }
1633
1634 os << "constant_pool = [";
1635 for (size_t i = 0; i < constantPool_.size(); i++) {
1636 size_t b = constantPool_[i];
1637 os << "0x" << std::setfill('0') << std::setw(2U) << std::right << std::hex << b << std::dec;
1638 if (i < constantPool_.size() - 1) {
1639 os << ", ";
1640 }
1641 }
1642 os << "]" << std::endl;
1643
1644 os << "line_number_program = line_number_program_idx[";
1645 if (program_ != nullptr && program_->HasIndex(this)) {
1646 os << program_->GetIndex(this);
1647 } else {
1648 os << "NO_INDEX";
1649 }
1650 os << "]";
1651 }
1652
Write(Writer * writer)1653 bool MethodHandleItem::Write(Writer *writer)
1654 {
1655 ASSERT(GetOffset() == writer->GetOffset());
1656
1657 if (!writer->WriteByte(static_cast<uint8_t>(type_))) {
1658 return false;
1659 }
1660
1661 return writer->WriteUleb128(entity_->GetOffset());
1662 }
1663
1664 } // namespace panda::panda_file
1665