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