1 /*
2 * Copyright (c) 2021 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 size_t IndexedItem::indexed_item_count_ = 0;
27
28 template <class Tag, class Val>
WriteUlebTaggedValue(Writer * writer,Tag tag,Val v)29 static bool WriteUlebTaggedValue(Writer *writer, Tag tag, Val v)
30 {
31 if (!writer->WriteByte(static_cast<uint8_t>(tag))) {
32 return false;
33 }
34
35 if (!writer->WriteUleb128(v)) {
36 return false;
37 }
38
39 return true;
40 }
41
42 template <class Tag, class Val>
WriteSlebTaggedValue(Writer * writer,Tag tag,Val v)43 static bool WriteSlebTaggedValue(Writer *writer, Tag tag, Val v)
44 {
45 if (!writer->WriteByte(static_cast<uint8_t>(tag))) {
46 return false;
47 }
48
49 if (!writer->WriteSleb128(v)) {
50 return false;
51 }
52
53 return true;
54 }
55
56 template <class Tag, class Val>
WriteTaggedValue(Writer * writer,Tag tag,Val v)57 static bool WriteTaggedValue(Writer *writer, Tag tag, Val v)
58 {
59 if (!writer->WriteByte(static_cast<uint8_t>(tag))) {
60 return false;
61 }
62
63 if (!writer->Write(v)) {
64 return false;
65 }
66
67 return true;
68 }
69
70 template <class Tag>
WriteIdTaggedValue(Writer * writer,Tag tag,BaseItem * item)71 static bool WriteIdTaggedValue(Writer *writer, Tag tag, BaseItem *item)
72 {
73 ASSERT(item->GetOffset() != 0);
74 return WriteTaggedValue(writer, tag, item->GetOffset());
75 }
76
StringItem(std::string str)77 StringItem::StringItem(std::string str) : str_(std::move(str))
78 {
79 str_.push_back(0);
80 utf16_length_ = utf::MUtf8ToUtf16Size(utf::CStringAsMutf8(str_.data()));
81 is_ascii_ = 1;
82
83 for (auto c : str_) {
84 if (static_cast<uint8_t>(c) > utf::MUTF8_1B_MAX) {
85 is_ascii_ = 0;
86 break;
87 }
88 }
89 }
90
CalculateSize() const91 size_t StringItem::CalculateSize() const
92 {
93 return leb128::UnsignedEncodingSize((utf16_length_ << 1U) | is_ascii_) + str_.size();
94 }
95
Write(Writer * writer)96 bool StringItem::Write(Writer *writer)
97 {
98 ASSERT(GetOffset() == writer->GetOffset());
99
100 constexpr size_t max_string_length = 0x7fffffffU;
101 if (utf16_length_ > max_string_length) {
102 LOG(ERROR, PANDAFILE) << "Writing StringItem with size greater than 0x7fffffffU is not supported!";
103 return false;
104 }
105
106 if (!writer->WriteUleb128((utf16_length_ << 1U) | is_ascii_)) {
107 return false;
108 }
109
110 for (auto c : str_) {
111 if (!writer->WriteByte(static_cast<uint8_t>(c))) {
112 return false;
113 }
114 }
115 return true;
116 }
117
CalculateSize() const118 size_t BaseClassItem::CalculateSize() const
119 {
120 return name_.GetSize();
121 }
122
ComputeLayout()123 void BaseClassItem::ComputeLayout()
124 {
125 uint32_t offset = GetOffset();
126
127 ASSERT(offset != 0);
128
129 name_.SetOffset(offset);
130 }
131
Write(Writer * writer)132 bool BaseClassItem::Write(Writer *writer)
133 {
134 ASSERT(GetOffset() == writer->GetOffset());
135 return name_.Write(writer);
136 }
137
CalculateSizeWithoutFieldsAndMethods() const138 size_t ClassItem::CalculateSizeWithoutFieldsAndMethods() const
139 {
140 size_t size = BaseClassItem::CalculateSize() + ID_SIZE + leb128::UnsignedEncodingSize(access_flags_);
141
142 size += leb128::UnsignedEncodingSize(fields_.size());
143 size += leb128::UnsignedEncodingSize(methods_.size());
144
145 if (!ifaces_.empty()) {
146 size += TAG_SIZE + leb128::UnsignedEncodingSize(ifaces_.size()) + IDX_SIZE * ifaces_.size();
147 }
148
149 if (source_lang_ != SourceLang::PANDA_ASSEMBLY) {
150 size += TAG_SIZE + sizeof(SourceLang);
151 }
152
153 size += (TAG_SIZE + ID_SIZE) * runtime_annotations_.size();
154 size += (TAG_SIZE + ID_SIZE) * annotations_.size();
155 size += (TAG_SIZE + ID_SIZE) * runtime_type_annotations_.size();
156 size += (TAG_SIZE + ID_SIZE) * type_annotations_.size();
157
158 if (source_file_ != nullptr) {
159 size += TAG_SIZE + ID_SIZE;
160 }
161
162 size += TAG_SIZE; // null tag
163
164 return size;
165 }
166
CalculateSize() const167 size_t ClassItem::CalculateSize() const
168 {
169 size_t size = CalculateSizeWithoutFieldsAndMethods();
170
171 for (auto &field : fields_) {
172 size += field->GetSize();
173 }
174
175 for (auto &method : methods_) {
176 size += method->GetSize();
177 }
178
179 return size;
180 }
181
ComputeLayout()182 void ClassItem::ComputeLayout()
183 {
184 BaseClassItem::ComputeLayout();
185
186 uint32_t offset = GetOffset();
187
188 offset += CalculateSizeWithoutFieldsAndMethods();
189
190 for (auto &field : fields_) {
191 field->SetOffset(offset);
192 field->ComputeLayout();
193 offset += field->GetSize();
194 }
195
196 for (auto &method : methods_) {
197 method->SetOffset(offset);
198 method->ComputeLayout();
199 offset += method->GetSize();
200 }
201 }
202
WriteIfaces(Writer * writer)203 bool ClassItem::WriteIfaces(Writer *writer)
204 {
205 if (!ifaces_.empty()) {
206 if (!writer->WriteByte(static_cast<uint8_t>(ClassTag::INTERFACES))) {
207 return false;
208 }
209
210 if (!writer->WriteUleb128(ifaces_.size())) {
211 return false;
212 }
213
214 for (auto iface : ifaces_) {
215 ASSERT(iface->HasIndex(this));
216 if (!writer->Write<uint16_t>(iface->GetIndex(this))) {
217 return false;
218 }
219 }
220 }
221
222 return true;
223 }
224
WriteAnnotations(Writer * writer)225 bool ClassItem::WriteAnnotations(Writer *writer)
226 {
227 for (auto runtime_annotation : runtime_annotations_) {
228 if (!WriteIdTaggedValue(writer, ClassTag::RUNTIME_ANNOTATION, runtime_annotation)) {
229 return false;
230 }
231 }
232
233 for (auto annotation : annotations_) {
234 if (!WriteIdTaggedValue(writer, ClassTag::ANNOTATION, annotation)) {
235 return false;
236 }
237 }
238
239 for (auto runtime_type_annotation : runtime_type_annotations_) {
240 if (!WriteIdTaggedValue(writer, ClassTag::RUNTIME_TYPE_ANNOTATION, runtime_type_annotation)) {
241 return false;
242 }
243 }
244
245 for (auto type_annotation : type_annotations_) {
246 if (!WriteIdTaggedValue(writer, ClassTag::TYPE_ANNOTATION, type_annotation)) {
247 return false;
248 }
249 }
250
251 return true;
252 }
253
WriteTaggedData(Writer * writer)254 bool ClassItem::WriteTaggedData(Writer *writer)
255 {
256 if (!WriteIfaces(writer)) {
257 return false;
258 }
259
260 if (source_lang_ != SourceLang::PANDA_ASSEMBLY) {
261 if (!WriteTaggedValue(writer, ClassTag::SOURCE_LANG, static_cast<uint8_t>(source_lang_))) {
262 return false;
263 }
264 }
265
266 if (!WriteAnnotations(writer)) {
267 return false;
268 }
269
270 if (source_file_ != nullptr) {
271 if (!WriteIdTaggedValue(writer, ClassTag::SOURCE_FILE, source_file_)) {
272 return false;
273 }
274 }
275
276 return writer->WriteByte(static_cast<uint8_t>(ClassTag::NOTHING));
277 }
278
Write(Writer * writer)279 bool ClassItem::Write(Writer *writer)
280 {
281 if (!BaseClassItem::Write(writer)) {
282 return false;
283 }
284
285 uint32_t offset = super_class_ != nullptr ? super_class_->GetOffset() : 0;
286 if (!writer->Write(offset)) {
287 return false;
288 }
289
290 if (!writer->WriteUleb128(access_flags_)) {
291 return false;
292 }
293
294 if (!writer->WriteUleb128(fields_.size())) {
295 return false;
296 }
297
298 if (!writer->WriteUleb128(methods_.size())) {
299 return false;
300 }
301
302 if (!WriteTaggedData(writer)) {
303 return false;
304 }
305
306 for (auto &field : fields_) {
307 if (!field->Write(writer)) {
308 return false;
309 }
310 }
311
312 for (auto &method : methods_) {
313 if (!method->Write(writer)) {
314 return false;
315 }
316 }
317
318 return true;
319 }
320
ParamAnnotationsItem(MethodItem * method,bool is_runtime_annotations)321 ParamAnnotationsItem::ParamAnnotationsItem(MethodItem *method, bool is_runtime_annotations)
322 {
323 for (const auto ¶m : method->GetParams()) {
324 if (is_runtime_annotations) {
325 annotations_.push_back(param.GetRuntimeAnnotations());
326 } else {
327 annotations_.push_back(param.GetAnnotations());
328 }
329 }
330
331 if (is_runtime_annotations) {
332 method->SetRuntimeParamAnnotationItem(this);
333 } else {
334 method->SetParamAnnotationItem(this);
335 }
336 }
337
CalculateSize() const338 size_t ParamAnnotationsItem::CalculateSize() const
339 {
340 size_t size = sizeof(uint32_t); // size
341
342 for (const auto ¶m_annotations : annotations_) {
343 size += sizeof(uint32_t); // count
344 size += param_annotations.size() * ID_SIZE;
345 }
346
347 return size;
348 }
349
Write(Writer * writer)350 bool ParamAnnotationsItem::Write(Writer *writer)
351 {
352 ASSERT(GetOffset() == writer->GetOffset());
353
354 if (!writer->Write(static_cast<uint32_t>(annotations_.size()))) {
355 return false;
356 }
357
358 for (const auto ¶m_annotations : annotations_) {
359 if (!writer->Write(static_cast<uint32_t>(param_annotations.size()))) {
360 return false;
361 }
362
363 for (auto *item : param_annotations) {
364 ASSERT(item->GetOffset() != 0);
365
366 if (!writer->Write(item->GetOffset())) {
367 return false;
368 }
369 }
370 }
371
372 return true;
373 }
374
ProtoItem(TypeItem * ret_type,const std::vector<MethodParamItem> & params)375 ProtoItem::ProtoItem(TypeItem *ret_type, const std::vector<MethodParamItem> ¶ms)
376 {
377 size_t n = 0;
378 shorty_.push_back(0);
379 AddType(ret_type, &n);
380 for (auto &p : params) {
381 AddType(p.GetType(), &n);
382 }
383 }
384
AddType(TypeItem * type,size_t * n)385 void ProtoItem::AddType(TypeItem *type, size_t *n)
386 {
387 constexpr size_t SHORTY_ELEMS_COUNT = std::numeric_limits<uint16_t>::digits / SHORTY_ELEM_SIZE;
388
389 uint16_t v = shorty_.back();
390
391 size_t shift = (*n % SHORTY_ELEMS_COUNT) * SHORTY_ELEM_SIZE;
392
393 v |= static_cast<uint16_t>(static_cast<uint16_t>(type->GetType().GetEncoding()) << shift);
394 shorty_.back() = v;
395
396 if (!type->GetType().IsPrimitive()) {
397 reference_types_.push_back(type);
398 AddIndexDependency(type);
399 }
400
401 *n += 1;
402
403 if (*n % SHORTY_ELEMS_COUNT == 0) {
404 shorty_.push_back(0);
405 }
406 }
407
Write(Writer * writer)408 bool ProtoItem::Write(Writer *writer)
409 {
410 ASSERT(GetOffset() == writer->GetOffset());
411 for (auto s : shorty_) {
412 if (!writer->Write(s)) {
413 return false;
414 }
415 }
416
417 for (auto r : reference_types_) {
418 ASSERT(r->HasIndex(this));
419 if (!writer->Write<uint16_t>(r->GetIndex(this))) {
420 return false;
421 }
422 }
423
424 return true;
425 }
426
BaseMethodItem(BaseClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t access_flags)427 BaseMethodItem::BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags)
428 : class_(cls), name_(name), proto_(proto), access_flags_(access_flags)
429 {
430 AddIndexDependency(cls);
431 AddIndexDependency(proto);
432 }
433
CalculateSize() const434 size_t BaseMethodItem::CalculateSize() const
435 {
436 // class id + proto id + name id + access flags
437 return IDX_SIZE + IDX_SIZE + ID_SIZE + leb128::UnsignedEncodingSize(access_flags_);
438 }
439
Write(Writer * writer)440 bool BaseMethodItem::Write(Writer *writer)
441 {
442 ASSERT(GetOffset() == writer->GetOffset());
443 ASSERT(class_ != nullptr);
444 ASSERT(class_->HasIndex(this));
445
446 if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
447 return false;
448 }
449
450 ASSERT(proto_->HasIndex(this));
451
452 if (!writer->Write<uint16_t>(proto_->GetIndex(this))) {
453 return false;
454 }
455
456 ASSERT(name_->GetOffset() != 0);
457
458 if (!writer->Write(name_->GetOffset())) {
459 return false;
460 }
461
462 return writer->WriteUleb128(access_flags_);
463 }
464
MethodItem(ClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t access_flags,std::vector<MethodParamItem> params)465 MethodItem::MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags,
466 std::vector<MethodParamItem> params)
467 : BaseMethodItem(cls, name, proto, access_flags),
468 params_(std::move(params)),
469 source_lang_(SourceLang::PANDA_ASSEMBLY),
470 code_(nullptr),
471 debug_info_(nullptr)
472 {
473 }
474
CalculateSize() const475 size_t MethodItem::CalculateSize() const
476 {
477 size_t size = BaseMethodItem::CalculateSize();
478
479 if (code_ != nullptr) {
480 size += TAG_SIZE + ID_SIZE;
481 }
482
483 if (source_lang_ != SourceLang::PANDA_ASSEMBLY) {
484 size += TAG_SIZE + sizeof(SourceLang);
485 }
486
487 size += (TAG_SIZE + ID_SIZE) * runtime_annotations_.size();
488
489 if (runtime_param_annotations_ != nullptr) {
490 size += TAG_SIZE + ID_SIZE;
491 }
492
493 size += (TAG_SIZE + ID_SIZE) * annotations_.size();
494
495 if (param_annotations_ != nullptr) {
496 size += TAG_SIZE + ID_SIZE;
497 }
498
499 size += (TAG_SIZE + ID_SIZE) * runtime_type_annotations_.size();
500 size += (TAG_SIZE + ID_SIZE) * type_annotations_.size();
501
502 if (debug_info_ != nullptr) {
503 size += TAG_SIZE + ID_SIZE;
504 }
505
506 size += TAG_SIZE; // null tag
507
508 return size;
509 }
510
WriteRuntimeAnnotations(Writer * writer)511 bool MethodItem::WriteRuntimeAnnotations(Writer *writer)
512 {
513 for (auto runtime_annotation : runtime_annotations_) {
514 if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_ANNOTATION, runtime_annotation)) {
515 return false;
516 }
517 }
518
519 if (runtime_param_annotations_ != nullptr) {
520 if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_PARAM_ANNOTATION, runtime_param_annotations_)) {
521 return false;
522 }
523 }
524
525 return true;
526 }
527
WriteTypeAnnotations(Writer * writer)528 bool MethodItem::WriteTypeAnnotations(Writer *writer)
529 {
530 for (auto runtime_type_annotation : runtime_type_annotations_) {
531 if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_TYPE_ANNOTATION, runtime_type_annotation)) {
532 return false;
533 }
534 }
535
536 for (auto type_annotation : type_annotations_) {
537 if (!WriteIdTaggedValue(writer, MethodTag::TYPE_ANNOTATION, type_annotation)) {
538 return false;
539 }
540 }
541
542 return true;
543 }
544
WriteTaggedData(Writer * writer)545 bool MethodItem::WriteTaggedData(Writer *writer)
546 {
547 if (code_ != nullptr) {
548 if (!WriteIdTaggedValue(writer, MethodTag::CODE, code_)) {
549 return false;
550 }
551 }
552
553 if (source_lang_ != SourceLang::PANDA_ASSEMBLY) {
554 if (!WriteTaggedValue(writer, MethodTag::SOURCE_LANG, static_cast<uint8_t>(source_lang_))) {
555 return false;
556 }
557 }
558
559 if (!WriteRuntimeAnnotations(writer)) {
560 return false;
561 }
562
563 if (debug_info_ != nullptr) {
564 if (!WriteIdTaggedValue(writer, MethodTag::DEBUG_INFO, debug_info_)) {
565 return false;
566 }
567 }
568
569 for (auto annotation : annotations_) {
570 if (!WriteIdTaggedValue(writer, MethodTag::ANNOTATION, annotation)) {
571 return false;
572 }
573 }
574
575 if (!WriteTypeAnnotations(writer)) {
576 return false;
577 }
578
579 if (param_annotations_ != nullptr) {
580 if (!WriteIdTaggedValue(writer, MethodTag::PARAM_ANNOTATION, param_annotations_)) {
581 return false;
582 }
583 }
584
585 return writer->WriteByte(static_cast<uint8_t>(MethodTag::NOTHING));
586 }
587
Write(Writer * writer)588 bool MethodItem::Write(Writer *writer)
589 {
590 if (!BaseMethodItem::Write(writer)) {
591 return false;
592 }
593
594 return WriteTaggedData(writer);
595 }
596
CalculateSize() const597 size_t CodeItem::CatchBlock::CalculateSize() const
598 {
599 ASSERT(type_ == nullptr || type_->HasIndex(method_));
600 uint32_t type_off = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
601 return leb128::UnsignedEncodingSize(type_off) + leb128::UnsignedEncodingSize(handler_pc_) +
602 leb128::UnsignedEncodingSize(code_size_);
603 }
604
Write(Writer * writer)605 bool CodeItem::CatchBlock::Write(Writer *writer)
606 {
607 ASSERT(GetOffset() == writer->GetOffset());
608 ASSERT(type_ == nullptr || type_->HasIndex(method_));
609
610 uint32_t type_off = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
611
612 if (!writer->WriteUleb128(type_off)) {
613 return false;
614 }
615
616 if (!writer->WriteUleb128(handler_pc_)) {
617 return false;
618 }
619
620 if (!writer->WriteUleb128(code_size_)) {
621 return false;
622 }
623
624 return true;
625 }
626
ComputeLayout()627 void CodeItem::TryBlock::ComputeLayout()
628 {
629 size_t offset = GetOffset();
630 offset += CalculateSizeWithoutCatchBlocks();
631
632 for (auto &catch_block : catch_blocks_) {
633 catch_block.SetOffset(offset);
634 catch_block.ComputeLayout();
635 offset += catch_block.GetSize();
636 }
637 }
638
CalculateSizeWithoutCatchBlocks() const639 size_t CodeItem::TryBlock::CalculateSizeWithoutCatchBlocks() const
640 {
641 return leb128::UnsignedEncodingSize(start_pc_) + leb128::UnsignedEncodingSize(length_) +
642 leb128::UnsignedEncodingSize(catch_blocks_.size());
643 }
644
CalculateSize() const645 size_t CodeItem::TryBlock::CalculateSize() const
646 {
647 size_t size = CalculateSizeWithoutCatchBlocks();
648
649 for (auto &catch_block : catch_blocks_) {
650 size += catch_block.GetSize();
651 }
652
653 return size;
654 }
655
Write(Writer * writer)656 bool CodeItem::TryBlock::Write(Writer *writer)
657 {
658 ASSERT(GetOffset() == writer->GetOffset());
659
660 if (!writer->WriteUleb128(start_pc_)) {
661 return false;
662 }
663
664 if (!writer->WriteUleb128(length_)) {
665 return false;
666 }
667
668 if (!writer->WriteUleb128(catch_blocks_.size())) {
669 return false;
670 }
671
672 for (auto &catch_block : catch_blocks_) {
673 if (!catch_block.Write(writer)) {
674 return false;
675 }
676 }
677
678 return true;
679 }
680
ComputeLayout()681 void CodeItem::ComputeLayout()
682 {
683 uint32_t offset = GetOffset();
684
685 offset += CalculateSizeWithoutTryBlocks();
686
687 for (auto &try_block : try_blocks_) {
688 try_block.SetOffset(offset);
689 try_block.ComputeLayout();
690 offset += try_block.GetSize();
691 }
692 }
693
CalculateSizeWithoutTryBlocks() const694 size_t CodeItem::CalculateSizeWithoutTryBlocks() const
695 {
696 size_t size = leb128::UnsignedEncodingSize(num_vregs_) + leb128::UnsignedEncodingSize(num_args_) +
697 leb128::UnsignedEncodingSize(instructions_.size()) + leb128::UnsignedEncodingSize(try_blocks_.size());
698
699 size += instructions_.size();
700
701 return size;
702 }
703
GetCodeSize() const704 size_t CodeItem::GetCodeSize() const
705 {
706 return instructions_.size();
707 }
708
CalculateSize() const709 size_t CodeItem::CalculateSize() const
710 {
711 size_t size = CalculateSizeWithoutTryBlocks();
712
713 for (auto &try_block : try_blocks_) {
714 size += try_block.GetSize();
715 }
716
717 return size;
718 }
719
Write(Writer * writer)720 bool CodeItem::Write(Writer *writer)
721 {
722 ASSERT(GetOffset() == writer->GetOffset());
723
724 if (!writer->WriteUleb128(num_vregs_)) {
725 return false;
726 }
727
728 if (!writer->WriteUleb128(num_args_)) {
729 return false;
730 }
731
732 if (!writer->WriteUleb128(instructions_.size())) {
733 return false;
734 }
735
736 if (!writer->WriteUleb128(try_blocks_.size())) {
737 return false;
738 }
739
740 if (!writer->WriteBytes(instructions_)) {
741 return false;
742 }
743
744 for (auto &try_block : try_blocks_) {
745 if (!try_block.Write(writer)) {
746 return false;
747 }
748 }
749
750 return true;
751 }
752
GetAsScalar() const753 const ScalarValueItem *ValueItem::GetAsScalar() const
754 {
755 ASSERT(!IsArray());
756 return static_cast<const ScalarValueItem *>(this);
757 }
758
GetAsArray() const759 const ArrayValueItem *ValueItem::GetAsArray() const
760 {
761 ASSERT(IsArray());
762 return static_cast<const ArrayValueItem *>(this);
763 }
764
GetULeb128EncodedSize()765 size_t ScalarValueItem::GetULeb128EncodedSize()
766 {
767 switch (GetType()) {
768 case Type::INTEGER:
769 return leb128::UnsignedEncodingSize(GetValue<uint32_t>());
770
771 case Type::LONG:
772 return leb128::UnsignedEncodingSize(GetValue<uint64_t>());
773
774 case Type::ID:
775 return leb128::UnsignedEncodingSize(GetId().GetOffset());
776
777 default:
778 return 0;
779 }
780 }
781
GetSLeb128EncodedSize() const782 size_t ScalarValueItem::GetSLeb128EncodedSize() const
783 {
784 switch (GetType()) {
785 case Type::INTEGER:
786 return leb128::SignedEncodingSize(static_cast<int32_t>(GetValue<uint32_t>()));
787
788 case Type::LONG:
789 return leb128::SignedEncodingSize(static_cast<int64_t>(GetValue<uint64_t>()));
790
791 default:
792 return 0;
793 }
794 }
795
CalculateSize() const796 size_t ScalarValueItem::CalculateSize() const
797 {
798 size_t size = 0;
799 switch (GetType()) {
800 case Type::INTEGER: {
801 size = sizeof(uint32_t);
802 break;
803 }
804
805 case Type::LONG: {
806 size = sizeof(uint64_t);
807 break;
808 }
809
810 case Type::FLOAT: {
811 size = sizeof(float);
812 break;
813 }
814
815 case Type::DOUBLE: {
816 size = sizeof(double);
817 break;
818 }
819
820 case Type::ID: {
821 size = ID_SIZE;
822 break;
823 }
824 default: {
825 UNREACHABLE();
826 break;
827 }
828 }
829
830 return size;
831 }
832
Alignment()833 size_t ScalarValueItem::Alignment()
834 {
835 return GetSize();
836 }
837
Write(Writer * writer)838 bool ScalarValueItem::Write(Writer *writer)
839 {
840 ASSERT(GetOffset() == writer->GetOffset());
841
842 switch (GetType()) {
843 case Type::INTEGER:
844 return writer->Write(GetValue<uint32_t>());
845
846 case Type::LONG:
847 return writer->Write(GetValue<uint64_t>());
848
849 case Type::FLOAT:
850 return writer->Write(bit_cast<uint32_t>(GetValue<float>()));
851
852 case Type::DOUBLE:
853 return writer->Write(bit_cast<uint64_t>(GetValue<double>()));
854
855 case Type::ID: {
856 ASSERT(GetId().IsValid());
857 return writer->Write(GetId().GetOffset());
858 }
859 default: {
860 UNREACHABLE();
861 break;
862 }
863 }
864
865 return true;
866 }
867
WriteAsUleb128(Writer * writer)868 bool ScalarValueItem::WriteAsUleb128(Writer *writer)
869 {
870 ASSERT(GetOffset() == writer->GetOffset());
871
872 switch (GetType()) {
873 case Type::INTEGER:
874 return writer->WriteUleb128(GetValue<uint32_t>());
875
876 case Type::LONG:
877 return writer->WriteUleb128(GetValue<uint64_t>());
878
879 case Type::ID: {
880 ASSERT(GetId().IsValid());
881 return writer->WriteUleb128(GetId().GetOffset());
882 }
883 default:
884 return false;
885 }
886 }
887
CalculateSize() const888 size_t ArrayValueItem::CalculateSize() const
889 {
890 return leb128::UnsignedEncodingSize(items_.size()) + items_.size() * GetComponentSize();
891 }
892
ComputeLayout()893 void ArrayValueItem::ComputeLayout()
894 {
895 uint32_t offset = GetOffset();
896
897 ASSERT(offset != 0);
898
899 offset += leb128::UnsignedEncodingSize(items_.size());
900
901 for (auto &item : items_) {
902 item.SetOffset(offset);
903 offset += GetComponentSize();
904 }
905 }
906
Write(Writer * writer)907 bool ArrayValueItem::Write(Writer *writer)
908 {
909 ASSERT(GetOffset() == writer->GetOffset());
910
911 if (!writer->WriteUleb128(items_.size())) {
912 return false;
913 }
914
915 switch (component_type_.GetId()) {
916 case panda_file::Type::TypeId::U1:
917 case panda_file::Type::TypeId::I8:
918 case panda_file::Type::TypeId::U8: {
919 for (auto &item : items_) {
920 auto value = static_cast<uint8_t>(item.GetValue<uint32_t>());
921 if (!writer->Write(value)) {
922 return false;
923 }
924 }
925 break;
926 }
927 case panda_file::Type::TypeId::I16:
928 case panda_file::Type::TypeId::U16: {
929 for (auto &item : items_) {
930 auto value = static_cast<uint16_t>(item.GetValue<uint32_t>());
931 if (!writer->Write(value)) {
932 return false;
933 }
934 }
935 break;
936 }
937 default: {
938 for (auto &item : items_) {
939 if (!item.Write(writer)) {
940 return false;
941 }
942 }
943 break;
944 }
945 }
946
947 return true;
948 }
949
GetComponentSize() const950 size_t ArrayValueItem::GetComponentSize() const
951 {
952 switch (component_type_.GetId()) {
953 case panda_file::Type::TypeId::U1:
954 case panda_file::Type::TypeId::I8:
955 case panda_file::Type::TypeId::U8:
956 return sizeof(uint8_t);
957 case panda_file::Type::TypeId::I16:
958 case panda_file::Type::TypeId::U16:
959 return sizeof(uint16_t);
960 case panda_file::Type::TypeId::I32:
961 case panda_file::Type::TypeId::U32:
962 case panda_file::Type::TypeId::F32:
963 return sizeof(uint32_t);
964 case panda_file::Type::TypeId::I64:
965 case panda_file::Type::TypeId::U64:
966 case panda_file::Type::TypeId::F64:
967 return sizeof(uint64_t);
968 case panda_file::Type::TypeId::REFERENCE:
969 return ID_SIZE;
970 case panda_file::Type::TypeId::VOID:
971 return 0;
972 default: {
973 UNREACHABLE();
974 return 0;
975 }
976 }
977 }
978
CalculateSize() const979 size_t LiteralItem::CalculateSize() const
980 {
981 size_t size = 0;
982 switch (GetType()) {
983 case Type::B1: {
984 size = sizeof(uint8_t);
985 break;
986 }
987
988 case Type::B2: {
989 size = sizeof(uint16_t);
990 break;
991 }
992
993 case Type::B4: {
994 size = sizeof(uint32_t);
995 break;
996 }
997
998 case Type::B8: {
999 size = sizeof(uint64_t);
1000 break;
1001 }
1002
1003 case Type::STRING:
1004 case Type::METHOD: {
1005 size = ID_SIZE;
1006 break;
1007 }
1008
1009 default: {
1010 UNREACHABLE();
1011 break;
1012 }
1013 }
1014
1015 return size;
1016 }
1017
Alignment()1018 size_t LiteralItem::Alignment()
1019 {
1020 return GetSize();
1021 }
1022
Write(Writer * writer)1023 bool LiteralItem::Write(Writer *writer)
1024 {
1025 ASSERT(GetOffset() == writer->GetOffset());
1026
1027 switch (GetType()) {
1028 case Type::B1: {
1029 return writer->Write(GetValue<uint8_t>());
1030 }
1031 case Type::B2: {
1032 return writer->Write(GetValue<uint16_t>());
1033 }
1034 case Type::B4: {
1035 return writer->Write(GetValue<uint32_t>());
1036 }
1037 case Type::B8: {
1038 return writer->Write(GetValue<uint64_t>());
1039 }
1040 case Type::STRING: {
1041 ASSERT(GetId().IsValid());
1042 return writer->Write(GetId().GetOffset());
1043 }
1044 case Type::METHOD: {
1045 ASSERT(GetMethodId().IsValid());
1046 return writer->Write(GetMethodId().GetOffset());
1047 }
1048 default: {
1049 UNREACHABLE();
1050 break;
1051 }
1052 }
1053
1054 return true;
1055 }
1056
AddItems(const std::vector<LiteralItem> & item)1057 void LiteralArrayItem::AddItems(const std::vector<LiteralItem> &item)
1058 {
1059 items_.assign(item.begin(), item.end());
1060 }
1061
CalculateSize() const1062 size_t LiteralArrayItem::CalculateSize() const
1063 {
1064 size_t size = sizeof(uint32_t);
1065 for (auto &item : items_) {
1066 size += item.CalculateSize();
1067 }
1068
1069 return size;
1070 }
1071
ComputeLayout()1072 void LiteralArrayItem::ComputeLayout()
1073 {
1074 uint32_t offset = GetOffset();
1075
1076 ASSERT(offset != 0);
1077
1078 offset += sizeof(uint32_t);
1079
1080 for (auto &item : items_) {
1081 item.SetOffset(offset);
1082 offset += item.CalculateSize();
1083 }
1084 }
1085
Write(Writer * writer)1086 bool LiteralArrayItem::Write(Writer *writer)
1087 {
1088 ASSERT(GetOffset() == writer->GetOffset());
1089
1090 if (!writer->Write(static_cast<uint32_t>(items_.size()))) {
1091 return false;
1092 }
1093
1094 for (auto &item : items_) {
1095 if (!item.Write(writer)) {
1096 return false;
1097 }
1098 }
1099
1100 return true;
1101 }
1102
BaseFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type)1103 BaseFieldItem::BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type)
1104 : class_(cls), name_(name), type_(type)
1105 {
1106 AddIndexDependency(cls);
1107 AddIndexDependency(type);
1108 }
1109
CalculateSize() const1110 size_t BaseFieldItem::CalculateSize() const
1111 {
1112 // class id + type id + name id
1113 return IDX_SIZE + IDX_SIZE + ID_SIZE;
1114 }
1115
Write(Writer * writer)1116 bool BaseFieldItem::Write(Writer *writer)
1117 {
1118 ASSERT(GetOffset() == writer->GetOffset());
1119 ASSERT(class_->HasIndex(this));
1120 ASSERT(type_->HasIndex(this));
1121
1122 if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1123 return false;
1124 }
1125
1126 if (!writer->Write<uint16_t>(type_->GetIndex(this))) {
1127 return false;
1128 }
1129
1130 return writer->Write(name_->GetOffset());
1131 }
1132
FieldItem(ClassItem * cls,StringItem * name,TypeItem * type,uint32_t access_flags)1133 FieldItem::FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t access_flags)
1134 : BaseFieldItem(cls, name, type), access_flags_(access_flags), value_(nullptr)
1135 {
1136 }
1137
SetValue(ValueItem * value)1138 void FieldItem::SetValue(ValueItem *value)
1139 {
1140 value_ = value;
1141 value_->SetNeedsEmit(!value_->Is32bit());
1142 }
1143
CalculateSize() const1144 size_t FieldItem::CalculateSize() const
1145 {
1146 size_t size = BaseFieldItem::CalculateSize() + leb128::UnsignedEncodingSize(access_flags_);
1147
1148 if (value_ != nullptr) {
1149 if (value_->GetType() == ValueItem::Type::INTEGER) {
1150 size += TAG_SIZE + value_->GetAsScalar()->GetSLeb128EncodedSize();
1151 } else {
1152 size += TAG_SIZE + ID_SIZE;
1153 }
1154 }
1155
1156 size += (TAG_SIZE + ID_SIZE) * runtime_annotations_.size();
1157 size += (TAG_SIZE + ID_SIZE) * annotations_.size();
1158 size += (TAG_SIZE + ID_SIZE) * runtime_type_annotations_.size();
1159 size += (TAG_SIZE + ID_SIZE) * type_annotations_.size();
1160
1161 size += TAG_SIZE; // null tag
1162
1163 return size;
1164 }
1165
WriteValue(Writer * writer)1166 bool FieldItem::WriteValue(Writer *writer)
1167 {
1168 if (value_ == nullptr) {
1169 return true;
1170 }
1171
1172 if (value_->GetType() == ValueItem::Type::INTEGER) {
1173 auto v = static_cast<int32_t>(value_->GetAsScalar()->GetValue<uint32_t>());
1174 if (!WriteSlebTaggedValue(writer, FieldTag::INT_VALUE, v)) {
1175 return false;
1176 }
1177 } else if (value_->GetType() == ValueItem::Type::FLOAT) {
1178 auto v = bit_cast<uint32_t>(value_->GetAsScalar()->GetValue<float>());
1179 if (!WriteTaggedValue(writer, FieldTag::VALUE, v)) {
1180 return false;
1181 }
1182 } else if (value_->GetType() == ValueItem::Type::ID) {
1183 auto id = value_->GetAsScalar()->GetId();
1184 ASSERT(id.GetOffset() != 0);
1185 if (!WriteTaggedValue(writer, FieldTag::VALUE, id.GetOffset())) {
1186 return false;
1187 }
1188 } else {
1189 ASSERT(!value_->Is32bit());
1190 if (!WriteIdTaggedValue(writer, FieldTag::VALUE, value_)) {
1191 return false;
1192 }
1193 }
1194
1195 return true;
1196 }
1197
WriteAnnotations(Writer * writer)1198 bool FieldItem::WriteAnnotations(Writer *writer)
1199 {
1200 for (auto runtime_annotation : runtime_annotations_) {
1201 if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_ANNOTATION, runtime_annotation)) {
1202 return false;
1203 }
1204 }
1205
1206 for (auto annotation : annotations_) {
1207 if (!WriteIdTaggedValue(writer, FieldTag::ANNOTATION, annotation)) {
1208 return false;
1209 }
1210 }
1211
1212 for (auto runtime_type_annotation : runtime_type_annotations_) {
1213 if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_TYPE_ANNOTATION, runtime_type_annotation)) {
1214 return false;
1215 }
1216 }
1217
1218 for (auto type_annotation : type_annotations_) {
1219 if (!WriteIdTaggedValue(writer, FieldTag::TYPE_ANNOTATION, type_annotation)) {
1220 return false;
1221 }
1222 }
1223
1224 return true;
1225 }
1226
WriteTaggedData(Writer * writer)1227 bool FieldItem::WriteTaggedData(Writer *writer)
1228 {
1229 if (!WriteValue(writer)) {
1230 return false;
1231 }
1232
1233 if (!WriteAnnotations(writer)) {
1234 return false;
1235 }
1236
1237 return writer->WriteByte(static_cast<uint8_t>(FieldTag::NOTHING));
1238 }
1239
Write(Writer * writer)1240 bool FieldItem::Write(Writer *writer)
1241 {
1242 if (!BaseFieldItem::Write(writer)) {
1243 return false;
1244 }
1245
1246 if (!writer->WriteUleb128(access_flags_)) {
1247 return false;
1248 }
1249
1250 return WriteTaggedData(writer);
1251 }
1252
CalculateSize() const1253 size_t AnnotationItem::CalculateSize() const
1254 {
1255 // class id + count + (name id + value id) * count + tag size * count
1256 return IDX_SIZE + sizeof(uint16_t) + (ID_SIZE + ID_SIZE) * elements_.size() + sizeof(uint8_t) * tags_.size();
1257 }
1258
Write(Writer * writer)1259 bool AnnotationItem::Write(Writer *writer)
1260 {
1261 ASSERT(GetOffset() == writer->GetOffset());
1262 ASSERT(class_->HasIndex(this));
1263
1264 if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1265 return false;
1266 }
1267
1268 if (!writer->Write(static_cast<uint16_t>(elements_.size()))) {
1269 return false;
1270 }
1271
1272 for (auto elem : elements_) {
1273 ASSERT(elem.GetName()->GetOffset() != 0);
1274 if (!writer->Write(elem.GetName()->GetOffset())) {
1275 return false;
1276 }
1277
1278 ValueItem *value_item = elem.GetValue();
1279
1280 switch (value_item->GetType()) {
1281 case ValueItem::Type::INTEGER: {
1282 if (!writer->Write(value_item->GetAsScalar()->GetValue<uint32_t>())) {
1283 return false;
1284 }
1285 break;
1286 }
1287 case ValueItem::Type::FLOAT: {
1288 if (!writer->Write(bit_cast<uint32_t>(value_item->GetAsScalar()->GetValue<float>()))) {
1289 return false;
1290 }
1291 break;
1292 }
1293 case ValueItem::Type::ID: {
1294 if (!writer->Write(value_item->GetAsScalar()->GetId().GetOffset())) {
1295 return false;
1296 }
1297 break;
1298 }
1299 default: {
1300 ASSERT(value_item->GetOffset() != 0);
1301 if (!writer->Write(value_item->GetOffset())) {
1302 return false;
1303 }
1304 break;
1305 }
1306 }
1307 }
1308
1309 for (auto tag : tags_) {
1310 if (!writer->Write(tag.GetItem())) {
1311 return false;
1312 }
1313 }
1314
1315 return true;
1316 }
1317
EmitEnd()1318 void LineNumberProgramItem::EmitEnd()
1319 {
1320 EmitOpcode(Opcode::END_SEQUENCE);
1321 }
1322
EmitAdvancePc(std::vector<uint8_t> * constant_pool,uint32_t value)1323 void LineNumberProgramItem::EmitAdvancePc(std::vector<uint8_t> *constant_pool, uint32_t value)
1324 {
1325 EmitOpcode(Opcode::ADVANCE_PC);
1326 EmitUleb128(constant_pool, value);
1327 }
1328
EmitAdvanceLine(std::vector<uint8_t> * constant_pool,int32_t value)1329 void LineNumberProgramItem::EmitAdvanceLine(std::vector<uint8_t> *constant_pool, int32_t value)
1330 {
1331 EmitOpcode(Opcode::ADVANCE_LINE);
1332 EmitSleb128(constant_pool, value);
1333 }
1334
EmitStartLocal(std::vector<uint8_t> * constant_pool,int32_t register_number,StringItem * name,StringItem * type)1335 void LineNumberProgramItem::EmitStartLocal(std::vector<uint8_t> *constant_pool, int32_t register_number,
1336 StringItem *name, StringItem *type)
1337 {
1338 EmitStartLocalExtended(constant_pool, register_number, name, type, nullptr);
1339 }
1340
EmitStartLocalExtended(std::vector<uint8_t> * constant_pool,int32_t register_number,StringItem * name,StringItem * type,StringItem * type_signature)1341 void LineNumberProgramItem::EmitStartLocalExtended(std::vector<uint8_t> *constant_pool, int32_t register_number,
1342 StringItem *name, StringItem *type, StringItem *type_signature)
1343 {
1344 if (type == nullptr) {
1345 return;
1346 }
1347
1348 ASSERT(name->GetOffset() != 0);
1349 ASSERT(type->GetOffset() != 0);
1350
1351 EmitOpcode(type_signature == nullptr ? Opcode::START_LOCAL : Opcode::START_LOCAL_EXTENDED);
1352 EmitRegister(register_number);
1353 EmitUleb128(constant_pool, name->GetOffset());
1354 EmitUleb128(constant_pool, type->GetOffset());
1355
1356 if (type_signature != nullptr) {
1357 ASSERT(type_signature->GetOffset() != 0);
1358 EmitUleb128(constant_pool, type_signature->GetOffset());
1359 }
1360 }
1361
EmitEndLocal(int32_t register_number)1362 void LineNumberProgramItem::EmitEndLocal(int32_t register_number)
1363 {
1364 EmitOpcode(Opcode::END_LOCAL);
1365 EmitRegister(register_number);
1366 }
1367
EmitRestartLocal(int32_t register_number)1368 void LineNumberProgramItem::EmitRestartLocal(int32_t register_number)
1369 {
1370 EmitOpcode(Opcode::RESTART_LOCAL);
1371 EmitRegister(register_number);
1372 }
1373
EmitSpecialOpcode(uint32_t pc_inc,int32_t line_inc)1374 bool LineNumberProgramItem::EmitSpecialOpcode(uint32_t pc_inc, int32_t line_inc)
1375 {
1376 if (line_inc < LINE_BASE || (line_inc - LINE_BASE) >= LINE_RANGE) {
1377 return false;
1378 }
1379
1380 size_t opcode = (line_inc - LINE_BASE) + (pc_inc * LINE_RANGE) + OPCODE_BASE;
1381 if (opcode > std::numeric_limits<uint8_t>::max()) {
1382 return false;
1383 }
1384
1385 data_.push_back(static_cast<uint8_t>(opcode));
1386 return true;
1387 }
1388
EmitColumn(std::vector<uint8_t> * constant_pool,uint32_t pc_inc,int32_t column)1389 void LineNumberProgramItem::EmitColumn(std::vector<uint8_t> *constant_pool, uint32_t pc_inc, int32_t column)
1390 {
1391 if (pc_inc != 0U) {
1392 EmitAdvancePc(constant_pool, pc_inc);
1393 }
1394 EmitOpcode(Opcode::SET_COLUMN);
1395 EmitUleb128(constant_pool, column);
1396 }
1397
EmitPrologEnd()1398 void LineNumberProgramItem::EmitPrologEnd()
1399 {
1400 EmitOpcode(Opcode::SET_PROLOGUE_END);
1401 }
1402
EmitEpilogBegin()1403 void LineNumberProgramItem::EmitEpilogBegin()
1404 {
1405 EmitOpcode(Opcode::SET_EPILOGUE_BEGIN);
1406 }
1407
EmitSetFile(std::vector<uint8_t> * constant_pool,StringItem * source_file)1408 void LineNumberProgramItem::EmitSetFile(std::vector<uint8_t> *constant_pool, StringItem *source_file)
1409 {
1410 EmitOpcode(Opcode::SET_FILE);
1411
1412 if (source_file == nullptr) {
1413 return;
1414 }
1415
1416 ASSERT(source_file->GetOffset() != 0);
1417 EmitUleb128(constant_pool, source_file->GetOffset());
1418 }
1419
EmitSetSourceCode(std::vector<uint8_t> * constant_pool,StringItem * source_code)1420 void LineNumberProgramItem::EmitSetSourceCode(std::vector<uint8_t> *constant_pool, StringItem *source_code)
1421 {
1422 EmitOpcode(Opcode::SET_SOURCE_CODE);
1423
1424 if (source_code == nullptr) {
1425 return;
1426 }
1427
1428 ASSERT(source_code->GetOffset() != 0);
1429 EmitUleb128(constant_pool, source_code->GetOffset());
1430 }
1431
EmitOpcode(Opcode opcode)1432 void LineNumberProgramItem::EmitOpcode(Opcode opcode)
1433 {
1434 data_.push_back(static_cast<uint8_t>(opcode));
1435 }
1436
EmitRegister(int32_t register_number)1437 void LineNumberProgramItem::EmitRegister(int32_t register_number)
1438 {
1439 EmitSleb128(&data_, register_number);
1440 }
1441
1442 /* static */
EmitUleb128(std::vector<uint8_t> * data,uint32_t value)1443 void LineNumberProgramItem::EmitUleb128(std::vector<uint8_t> *data, uint32_t value)
1444 {
1445 size_t n = leb128::UnsignedEncodingSize(value);
1446 std::vector<uint8_t> out(n);
1447 leb128::EncodeUnsigned(value, out.data());
1448
1449 if (data == nullptr) {
1450 return;
1451 }
1452
1453 data->insert(data->end(), out.cbegin(), out.cend());
1454 }
1455
1456 /* static */
EmitSleb128(std::vector<uint8_t> * data,int32_t value)1457 void LineNumberProgramItem::EmitSleb128(std::vector<uint8_t> *data, int32_t value)
1458 {
1459 size_t n = leb128::SignedEncodingSize(value);
1460 std::vector<uint8_t> out(n);
1461 leb128::EncodeSigned(value, out.data());
1462 data->insert(data->end(), out.cbegin(), out.cend());
1463 }
1464
CalculateSize() const1465 size_t LineNumberProgramItem::CalculateSize() const
1466 {
1467 return data_.size();
1468 }
1469
Write(Writer * writer)1470 bool LineNumberProgramItem::Write(Writer *writer)
1471 {
1472 ASSERT(GetOffset() == writer->GetOffset());
1473
1474 return writer->WriteBytes(data_);
1475 }
1476
CalculateSize() const1477 size_t DebugInfoItem::CalculateSize() const
1478 {
1479 size_t n = leb128::UnsignedEncodingSize(line_num_) + leb128::UnsignedEncodingSize(parameters_.size());
1480
1481 for (auto *p : parameters_) {
1482 ASSERT(p == nullptr || p->GetOffset() != 0);
1483 n += leb128::UnsignedEncodingSize(p == nullptr ? 0 : p->GetOffset());
1484 }
1485
1486 n += leb128::UnsignedEncodingSize(constant_pool_.size());
1487 n += constant_pool_.size();
1488
1489 n += leb128::UnsignedEncodingSize(program_->GetIndex(this));
1490
1491 return n;
1492 }
1493
Write(Writer * writer)1494 bool DebugInfoItem::Write(Writer *writer)
1495 {
1496 ASSERT(GetOffset() == writer->GetOffset());
1497
1498 if (!writer->WriteUleb128(line_num_)) {
1499 return false;
1500 }
1501
1502 if (!writer->WriteUleb128(parameters_.size())) {
1503 return false;
1504 }
1505
1506 for (auto *p : parameters_) {
1507 ASSERT(p == nullptr || p->GetOffset() != 0);
1508
1509 if (!writer->WriteUleb128(p == nullptr ? 0 : p->GetOffset())) {
1510 return false;
1511 }
1512 }
1513
1514 if (!writer->WriteUleb128(constant_pool_.size())) {
1515 return false;
1516 }
1517
1518 if (!writer->WriteBytes(constant_pool_)) {
1519 return false;
1520 }
1521
1522 ASSERT(program_ != nullptr);
1523 ASSERT(program_->HasIndex(this));
1524
1525 return writer->WriteUleb128(program_->GetIndex(this));
1526 }
1527
Dump(std::ostream & os) const1528 void DebugInfoItem::Dump(std::ostream &os) const
1529 {
1530 os << "line_start = " << line_num_ << std::endl;
1531
1532 os << "num_parameters = " << parameters_.size() << std::endl;
1533 for (auto *item : parameters_) {
1534 if (item != nullptr) {
1535 os << " string_item[" << item->GetOffset() << "]" << std::endl;
1536 } else {
1537 os << " string_item[INVALID_OFFSET]" << std::endl;
1538 }
1539 }
1540
1541 os << "constant_pool = [";
1542 for (size_t i = 0; i < constant_pool_.size(); i++) {
1543 size_t b = constant_pool_[i];
1544 os << "0x" << std::setfill('0') << std::setw(2U) << std::right << std::hex << b << std::dec;
1545 if (i < constant_pool_.size() - 1) {
1546 os << ", ";
1547 }
1548 }
1549 os << "]" << std::endl;
1550
1551 os << "line_number_program = line_number_program_idx[";
1552 if (program_ != nullptr && program_->HasIndex(this)) {
1553 os << program_->GetIndex(this);
1554 } else {
1555 os << "NO_INDEX";
1556 }
1557 os << "]";
1558 }
1559
Write(Writer * writer)1560 bool MethodHandleItem::Write(Writer *writer)
1561 {
1562 ASSERT(GetOffset() == writer->GetOffset());
1563
1564 if (!writer->WriteByte(static_cast<uint8_t>(type_))) {
1565 return false;
1566 }
1567
1568 return writer->WriteUleb128(entity_->GetOffset());
1569 }
1570
1571 } // namespace panda::panda_file
1572