• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param : 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 &param_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 &param_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> &params)
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