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