• 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 
79 // CC-OFFNXT(G.FUN.01-CPP, huge_cyclomatic_complexity[C++], huge_method[C++]) big switch case
ItemTypeToString(ItemTypes type)80 std::string ItemTypeToString(ItemTypes type)
81 {
82     switch (type) {
83         case ItemTypes::ANNOTATION_ITEM:
84             return "annotation_item";
85         case ItemTypes::CATCH_BLOCK_ITEM:
86             return "catch_block_item";
87         case ItemTypes::CLASS_INDEX_ITEM:
88             return "class_index_item";
89         case ItemTypes::CLASS_ITEM:
90             return "class_item";
91         case ItemTypes::CODE_ITEM:
92             return "code_item";
93         case ItemTypes::DEBUG_INFO_ITEM:
94             return "debug_info_item";
95         case ItemTypes::END_ITEM:
96             return "end_item";
97         case ItemTypes::FIELD_INDEX_ITEM:
98             return "field_index_item";
99         case ItemTypes::FIELD_ITEM:
100             return "field_item";
101         case ItemTypes::FOREIGN_CLASS_ITEM:
102             return "foreign_class_item";
103         case ItemTypes::FOREIGN_FIELD_ITEM:
104             return "foreign_field_item";
105         case ItemTypes::FOREIGN_METHOD_ITEM:
106             return "foreign_method_item";
107         case ItemTypes::LINE_NUMBER_PROGRAM_INDEX_ITEM:
108             return "line_number_program_index_item";
109         case ItemTypes::LINE_NUMBER_PROGRAM_ITEM:
110             return "line_number_program_item";
111         case ItemTypes::LITERAL_ARRAY_ITEM:
112             return "literal_array_item";
113         case ItemTypes::LITERAL_ITEM:
114             return "literal_item";
115         case ItemTypes::METHOD_HANDLE_ITEM:
116             return "method_handle_item";
117         case ItemTypes::METHOD_INDEX_ITEM:
118             return "method_index_item";
119         case ItemTypes::METHOD_ITEM:
120             return "method_item";
121         case ItemTypes::PARAM_ANNOTATIONS_ITEM:
122             return "param_annotations_item";
123         case ItemTypes::PRIMITIVE_TYPE_ITEM:
124             return "primitive_type_item";
125         case ItemTypes::PROTO_INDEX_ITEM:
126             return "proto_index_item";
127         case ItemTypes::PROTO_ITEM:
128             return "proto_item";
129         case ItemTypes::REGION_HEADER:
130             return "region_header";
131         case ItemTypes::REGION_SECTION:
132             return "region_section";
133         case ItemTypes::STRING_ITEM:
134             return "string_item";
135         case ItemTypes::TRY_BLOCK_ITEM:
136             return "try_block_item";
137         case ItemTypes::VALUE_ITEM:
138             return "value_item";
139         default:
140             return "";
141     }
142 }
143 
GetName() const144 std::string BaseItem::GetName() const
145 {
146     return ItemTypeToString(GetItemType());
147 }
148 
StringItem(std::string str)149 StringItem::StringItem(std::string str) : str_(std::move(str))
150 {
151     str_.push_back(0);
152     utf16Length_ = utf::MUtf8ToUtf16Size(utf::CStringAsMutf8(str_.data()));
153     isAscii_ = 1;
154 
155     for (auto c : str_) {
156         if (static_cast<uint8_t>(c) > utf::UTF8_1B_MAX) {
157             isAscii_ = 0;
158             break;
159         }
160     }
161 }
162 
StringItem(File::StringData data)163 StringItem::StringItem(File::StringData data)
164     : str_(reinterpret_cast<const char *>(data.data)), utf16Length_(data.utf16Length)
165 {
166 }
167 
CalculateSize() const168 size_t StringItem::CalculateSize() const
169 {
170     size_t n = str_.size();
171     return leb128::UnsignedEncodingSize((utf16Length_ << 1U) | isAscii_) + n;
172 }
173 
Write(Writer * writer)174 bool StringItem::Write(Writer *writer)
175 {
176     ASSERT(GetOffset() == writer->GetOffset());
177     constexpr size_t MAX_LENGTH = 0x7fffffffU;
178     if (utf16Length_ > MAX_LENGTH) {
179         LOG(ERROR, PANDAFILE) << "Writing StringItem with size greater than 0x7fffffffU is not supported!";
180         return false;
181     }
182 
183     if (!writer->WriteUleb128((utf16Length_ << 1U) | isAscii_)) {
184         return false;
185     }
186 
187     for (auto c : str_) {
188         if (!writer->WriteByte(static_cast<uint8_t>(c))) {
189             return false;
190         }
191     }
192     return true;
193 }
194 
CalculateSize() const195 size_t BaseClassItem::CalculateSize() const
196 {
197     return name_.GetSize();
198 }
199 
ComputeLayout()200 void BaseClassItem::ComputeLayout()
201 {
202     uint32_t offset = GetOffset();
203 
204     ASSERT(offset != 0);
205 
206     name_.SetOffset(offset);
207 }
208 
Write(Writer * writer)209 bool BaseClassItem::Write(Writer *writer)
210 {
211     ASSERT(GetOffset() == writer->GetOffset());
212     return name_.Write(writer);
213 }
214 
CalculateSizeWithoutFieldsAndMethods() const215 size_t ClassItem::CalculateSizeWithoutFieldsAndMethods() const
216 {
217     size_t size = BaseClassItem::CalculateSize() + ID_SIZE + leb128::UnsignedEncodingSize(accessFlags_);
218 
219     size += leb128::UnsignedEncodingSize(fields_.size());
220     size += leb128::UnsignedEncodingSize(methods_.size());
221 
222     if (!ifaces_.empty()) {
223         size += TAG_SIZE + leb128::UnsignedEncodingSize(ifaces_.size()) + IDX_SIZE * ifaces_.size();
224     }
225 
226     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
227         size += TAG_SIZE + sizeof(SourceLang);
228     }
229 
230     size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
231     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
232     size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
233     size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
234 
235     if (sourceFile_ != nullptr) {
236         size += TAG_SIZE + ID_SIZE;
237     }
238 
239     size += TAG_SIZE;  // null tag
240 
241     return size;
242 }
243 
CalculateSize() const244 size_t ClassItem::CalculateSize() const
245 {
246     size_t size = CalculateSizeWithoutFieldsAndMethods();
247 
248     for (auto &field : fields_) {
249         size += field->GetSize();
250     }
251 
252     for (auto &method : methods_) {
253         size += method->GetSize();
254     }
255 
256     return size;
257 }
258 
ComputeLayout()259 void ClassItem::ComputeLayout()
260 {
261     BaseClassItem::ComputeLayout();
262 
263     uint32_t offset = GetOffset();
264 
265     offset += CalculateSizeWithoutFieldsAndMethods();
266 
267     for (auto &field : fields_) {
268         field->SetOffset(offset);
269         field->ComputeLayout();
270         offset += field->GetSize();
271     }
272 
273     for (auto &method : methods_) {
274         method->SetOffset(offset);
275         method->ComputeLayout();
276         offset += method->GetSize();
277     }
278 }
279 
WriteIfaces(Writer * writer)280 bool ClassItem::WriteIfaces(Writer *writer)
281 {
282     if (!ifaces_.empty()) {
283         if (!writer->WriteByte(static_cast<uint8_t>(ClassTag::INTERFACES))) {
284             return false;
285         }
286 
287         if (!writer->WriteUleb128(ifaces_.size())) {
288             return false;
289         }
290 
291         for (auto iface : ifaces_) {
292             ASSERT(iface->HasIndex(this));
293             if (!writer->Write<uint16_t>(iface->GetIndex(this))) {
294                 return false;
295             }
296         }
297     }
298 
299     return true;
300 }
301 
WriteAnnotations(Writer * writer)302 bool ClassItem::WriteAnnotations(Writer *writer)
303 {
304     for (auto runtimeAnnotation : runtimeAnnotations_) {
305         if (!WriteIdTaggedValue(writer, ClassTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
306             return false;
307         }
308     }
309 
310     for (auto annotation : annotations_) {
311         if (!WriteIdTaggedValue(writer, ClassTag::ANNOTATION, annotation)) {
312             return false;
313         }
314     }
315 
316     for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
317         if (!WriteIdTaggedValue(writer, ClassTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
318             return false;
319         }
320     }
321 
322     for (auto typeAnnotation : typeAnnotations_) {
323         if (!WriteIdTaggedValue(writer, ClassTag::TYPE_ANNOTATION, typeAnnotation)) {
324             return false;
325         }
326     }
327 
328     return true;
329 }
330 
WriteTaggedData(Writer * writer)331 bool ClassItem::WriteTaggedData(Writer *writer)
332 {
333     if (!WriteIfaces(writer)) {
334         return false;
335     }
336 
337     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
338         if (!WriteTaggedValue(writer, ClassTag::SOURCE_LANG, static_cast<uint8_t>(sourceLang_))) {
339             return false;
340         }
341     }
342 
343     if (!WriteAnnotations(writer)) {
344         return false;
345     }
346 
347     if (sourceFile_ != nullptr) {
348         if (!WriteIdTaggedValue(writer, ClassTag::SOURCE_FILE, sourceFile_)) {
349             return false;
350         }
351     }
352 
353     return writer->WriteByte(static_cast<uint8_t>(ClassTag::NOTHING));
354 }
355 
Write(Writer * writer)356 bool ClassItem::Write(Writer *writer)
357 {
358     if (!BaseClassItem::Write(writer)) {
359         return false;
360     }
361 
362     uint32_t offset = superClass_ != nullptr ? superClass_->GetOffset() : 0;
363     if (!writer->Write(offset)) {
364         return false;
365     }
366 
367     if (!writer->WriteUleb128(accessFlags_)) {
368         return false;
369     }
370 
371     if (!writer->WriteUleb128(fields_.size())) {
372         return false;
373     }
374 
375     if (!writer->WriteUleb128(methods_.size())) {
376         return false;
377     }
378 
379     if (!WriteTaggedData(writer)) {
380         return false;
381     }
382 
383     for (auto &field : fields_) {
384         if (!field->Write(writer)) {
385             return false;
386         }
387     }
388 
389     for (auto &method : methods_) {
390         if (!method->Write(writer)) {
391             return false;
392         }
393     }
394 
395     return true;
396 }
397 
ParamAnnotationsItem(MethodItem * method,bool isRuntimeAnnotations)398 ParamAnnotationsItem::ParamAnnotationsItem(MethodItem *method, bool isRuntimeAnnotations)
399 {
400     for (const auto &param : method->GetParams()) {
401         if (isRuntimeAnnotations) {
402             annotations_.push_back(param.GetRuntimeAnnotations());
403         } else {
404             annotations_.push_back(param.GetAnnotations());
405         }
406     }
407 
408     if (isRuntimeAnnotations) {
409         method->SetRuntimeParamAnnotationItem(this);
410     } else {
411         method->SetParamAnnotationItem(this);
412     }
413 }
414 
CalculateSize() const415 size_t ParamAnnotationsItem::CalculateSize() const
416 {
417     size_t size = sizeof(uint32_t);  // size
418 
419     for (const auto &paramAnnotations : annotations_) {
420         size += sizeof(uint32_t);  // count
421         size += paramAnnotations.size() * ID_SIZE;
422     }
423 
424     return size;
425 }
426 
Write(Writer * writer)427 bool ParamAnnotationsItem::Write(Writer *writer)
428 {
429     ASSERT(GetOffset() == writer->GetOffset());
430 
431     if (!writer->Write(static_cast<uint32_t>(annotations_.size()))) {
432         return false;
433     }
434 
435     for (const auto &paramAnnotations : annotations_) {
436         if (!writer->Write(static_cast<uint32_t>(paramAnnotations.size()))) {
437             return false;
438         }
439 
440         for (auto *item : paramAnnotations) {
441             ASSERT(item->GetOffset() != 0);
442 
443             if (!writer->Write(item->GetOffset())) {
444                 return false;
445             }
446         }
447     }
448 
449     return true;
450 }
451 
ProtoItem(TypeItem * retType,const std::vector<MethodParamItem> & params)452 ProtoItem::ProtoItem(TypeItem *retType, const std::vector<MethodParamItem> &params)
453 {
454     size_t n = 0;
455     shorty_.push_back(0);
456     AddType(retType, &n);
457     for (auto &p : params) {
458         AddType(p.GetType(), &n);
459     }
460 }
461 
AddType(TypeItem * type,size_t * n)462 void ProtoItem::AddType(TypeItem *type, size_t *n)
463 {
464     constexpr size_t SHORTY_ELEMS_COUNT = std::numeric_limits<uint16_t>::digits / SHORTY_ELEM_SIZE;
465 
466     uint16_t v = shorty_.back();
467 
468     size_t shift = (*n % SHORTY_ELEMS_COUNT) * SHORTY_ELEM_SIZE;
469 
470     v |= static_cast<uint16_t>(static_cast<uint16_t>(type->GetType().GetEncoding()) << shift);
471     shorty_.back() = v;
472 
473     if (!type->GetType().IsPrimitive()) {
474         referenceTypes_.push_back(type);
475         AddIndexDependency(type);
476     }
477 
478     *n += 1;
479 
480     if (*n % SHORTY_ELEMS_COUNT == 0) {
481         shorty_.push_back(0);
482     }
483 }
484 
Write(Writer * writer)485 bool ProtoItem::Write(Writer *writer)
486 {
487     ASSERT(GetOffset() == writer->GetOffset());
488     for (auto s : shorty_) {
489         if (!writer->Write(s)) {
490             return false;
491         }
492     }
493 
494     for (auto r : referenceTypes_) {
495         ASSERT(r->HasIndex(this));
496         if (!writer->Write<uint16_t>(r->GetIndex(this))) {
497             return false;
498         }
499     }
500 
501     return true;
502 }
503 
BaseMethodItem(BaseClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t accessFlags)504 BaseMethodItem::BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags)
505     : class_(cls), name_(name), proto_(proto), accessFlags_(accessFlags)
506 {
507     AddIndexDependency(cls);
508     AddIndexDependency(proto);
509 }
510 
CalculateSize() const511 size_t BaseMethodItem::CalculateSize() const
512 {
513     // class id + proto id + name id + access flags
514     return IDX_SIZE + IDX_SIZE + ID_SIZE + leb128::UnsignedEncodingSize(accessFlags_);
515 }
516 
Write(Writer * writer)517 bool BaseMethodItem::Write(Writer *writer)
518 {
519     ASSERT(GetOffset() == writer->GetOffset());
520     ASSERT(class_ != nullptr);
521     ASSERT(class_->HasIndex(this));
522 
523     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
524         return false;
525     }
526 
527     ASSERT(proto_->HasIndex(this));
528 
529     if (!writer->Write<uint16_t>(proto_->GetIndex(this))) {
530         return false;
531     }
532 
533     ASSERT(name_->GetOffset() != 0);
534 
535     if (!writer->Write(name_->GetOffset())) {
536         return false;
537     }
538 
539     return writer->WriteUleb128(accessFlags_);
540 }
541 
MethodItem(ClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t accessFlags,std::vector<MethodParamItem> params)542 MethodItem::MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags,
543                        std::vector<MethodParamItem> params)
544     : BaseMethodItem(cls, name, proto, accessFlags), params_(std::move(params))
545 {
546 }
547 
CalculateSize() const548 size_t MethodItem::CalculateSize() const
549 {
550     size_t size = BaseMethodItem::CalculateSize();
551 
552     if (code_ != nullptr) {
553         size += TAG_SIZE + ID_SIZE;
554     }
555 
556     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
557         size += TAG_SIZE + sizeof(SourceLang);
558     }
559 
560     size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
561 
562     if (runtimeParamAnnotations_ != nullptr) {
563         size += TAG_SIZE + ID_SIZE;
564     }
565 
566     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
567 
568     if (paramAnnotations_ != nullptr) {
569         size += TAG_SIZE + ID_SIZE;
570     }
571 
572     size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
573     size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
574 
575     if (debugInfo_ != nullptr) {
576         size += TAG_SIZE + ID_SIZE;
577     }
578 
579     if (profileSize_ != 0) {
580         size += TAG_SIZE + sizeof(profileSize_);
581     }
582 
583     size += TAG_SIZE;  // null tag
584 
585     return size;
586 }
587 
WriteRuntimeAnnotations(Writer * writer)588 bool MethodItem::WriteRuntimeAnnotations(Writer *writer)
589 {
590     for (auto runtimeAnnotation : runtimeAnnotations_) {
591         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
592             return false;
593         }
594     }
595 
596     if (runtimeParamAnnotations_ != nullptr) {
597         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_PARAM_ANNOTATION, runtimeParamAnnotations_)) {
598             return false;
599         }
600     }
601 
602     return true;
603 }
604 
WriteTypeAnnotations(Writer * writer)605 bool MethodItem::WriteTypeAnnotations(Writer *writer)
606 {
607     for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
608         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
609             return false;
610         }
611     }
612 
613     for (auto typeAnnotation : typeAnnotations_) {
614         if (!WriteIdTaggedValue(writer, MethodTag::TYPE_ANNOTATION, typeAnnotation)) {
615             return false;
616         }
617     }
618 
619     return true;
620 }
621 
WriteTaggedData(Writer * writer)622 bool MethodItem::WriteTaggedData(Writer *writer)
623 {
624     if (code_ != nullptr) {
625         if (!WriteIdTaggedValue(writer, MethodTag::CODE, code_)) {
626             return false;
627         }
628     }
629 
630     if (sourceLang_ != SourceLang::PANDA_ASSEMBLY) {
631         if (!WriteTaggedValue(writer, MethodTag::SOURCE_LANG, static_cast<uint8_t>(sourceLang_))) {
632             return false;
633         }
634     }
635 
636     if (!WriteRuntimeAnnotations(writer)) {
637         return false;
638     }
639 
640     if (debugInfo_ != nullptr) {
641         if (!WriteIdTaggedValue(writer, MethodTag::DEBUG_INFO, debugInfo_)) {
642             return false;
643         }
644     }
645 
646     for (auto annotation : annotations_) {
647         if (!WriteIdTaggedValue(writer, MethodTag::ANNOTATION, annotation)) {
648             return false;
649         }
650     }
651 
652     if (!WriteTypeAnnotations(writer)) {
653         return false;
654     }
655 
656     if (paramAnnotations_ != nullptr) {
657         if (!WriteIdTaggedValue(writer, MethodTag::PARAM_ANNOTATION, paramAnnotations_)) {
658             return false;
659         }
660     }
661 
662     if (profileSize_ != 0) {
663         if (!WriteTaggedValue(writer, MethodTag::PROFILE_INFO, static_cast<uint16_t>(profileSize_))) {
664             return false;
665         }
666     }
667 
668     return writer->WriteByte(static_cast<uint8_t>(MethodTag::NOTHING));
669 }
670 
Write(Writer * writer)671 bool MethodItem::Write(Writer *writer)
672 {
673     if (!BaseMethodItem::Write(writer)) {
674         return false;
675     }
676 
677     return WriteTaggedData(writer);
678 }
679 
CalculateSize() const680 size_t CodeItem::CatchBlock::CalculateSize() const
681 {
682     ASSERT(type_ == nullptr || type_->HasIndex(method_));
683     uint32_t typeOff = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
684     return leb128::UnsignedEncodingSize(typeOff) + leb128::UnsignedEncodingSize(handlerPc_) +
685            leb128::UnsignedEncodingSize(codeSize_);
686 }
687 
Write(Writer * writer)688 bool CodeItem::CatchBlock::Write(Writer *writer)
689 {
690     ASSERT(GetOffset() == writer->GetOffset());
691     ASSERT(type_ == nullptr || type_->HasIndex(method_));
692 
693     uint32_t typeOff = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
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         case Type::LITERALARRAY: {
1090             size = ID_SIZE;
1091             break;
1092         }
1093 
1094         default: {
1095             UNREACHABLE();
1096             break;
1097         }
1098     }
1099 
1100     return size;
1101 }
1102 
Alignment()1103 size_t LiteralItem::Alignment()
1104 {
1105     return GetSize();
1106 }
1107 
GetLiteralArrayFileId() const1108 File::EntityId LiteralItem::GetLiteralArrayFileId() const
1109 {
1110     return File::EntityId(GetValue<LiteralArrayItem *>()->GetOffset());
1111 }
1112 
Write(Writer * writer)1113 bool LiteralItem::Write(Writer *writer)
1114 {
1115     ASSERT(GetOffset() == writer->GetOffset());
1116 
1117     switch (GetType()) {
1118         case Type::B1: {
1119             return writer->Write(GetValue<uint8_t>());
1120         }
1121         case Type::B2: {
1122             return writer->Write(GetValue<uint16_t>());
1123         }
1124         case Type::B4: {
1125             return writer->Write(GetValue<uint32_t>());
1126         }
1127         case Type::B8: {
1128             return writer->Write(GetValue<uint64_t>());
1129         }
1130         case Type::STRING: {
1131             ASSERT(GetId().IsValid());
1132             return writer->Write(GetId().GetOffset());
1133         }
1134         case Type::METHOD: {
1135             ASSERT(GetMethodId().IsValid());
1136             return writer->Write(GetMethodId().GetOffset());
1137         }
1138         case Type::LITERALARRAY: {
1139             ASSERT(GetLiteralArrayFileId().IsValid());
1140             return writer->Write(GetLiteralArrayFileId().GetOffset());
1141         }
1142         default: {
1143             UNREACHABLE();
1144             break;
1145         }
1146     }
1147 
1148     return true;
1149 }
1150 
AddItems(const std::vector<LiteralItem> & item)1151 void LiteralArrayItem::AddItems(const std::vector<LiteralItem> &item)
1152 {
1153     items_.assign(item.begin(), item.end());
1154 }
1155 
CalculateSize() const1156 size_t LiteralArrayItem::CalculateSize() const
1157 {
1158     size_t size = sizeof(uint32_t);
1159     for (auto &item : items_) {
1160         size += item.CalculateSize();
1161     }
1162 
1163     return size;
1164 }
1165 
ComputeLayout()1166 void LiteralArrayItem::ComputeLayout()
1167 {
1168     uint32_t offset = GetOffset();
1169 
1170     ASSERT(offset != 0);
1171 
1172     offset += sizeof(uint32_t);
1173 
1174     for (auto &item : items_) {
1175         item.SetOffset(offset);
1176         offset += item.CalculateSize();
1177     }
1178 }
1179 
Write(Writer * writer)1180 bool LiteralArrayItem::Write(Writer *writer)
1181 {
1182     ASSERT(GetOffset() == writer->GetOffset());
1183 
1184     if (!writer->Write(static_cast<uint32_t>(items_.size()))) {
1185         return false;
1186     }
1187 
1188     for (auto &item : items_) {
1189         if (!item.Write(writer)) {
1190             return false;
1191         }
1192     }
1193 
1194     return true;
1195 }
1196 
BaseFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type)1197 BaseFieldItem::BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type)
1198     : class_(cls), name_(name), type_(type)
1199 {
1200     AddIndexDependency(cls);
1201     AddIndexDependency(type);
1202 }
1203 
CalculateSize() const1204 size_t BaseFieldItem::CalculateSize() const
1205 {
1206     // class id + type id + name id
1207     return IDX_SIZE + IDX_SIZE + ID_SIZE;
1208 }
1209 
Write(Writer * writer)1210 bool BaseFieldItem::Write(Writer *writer)
1211 {
1212     ASSERT(GetOffset() == writer->GetOffset());
1213     ASSERT(class_->HasIndex(this));
1214     ASSERT(type_->HasIndex(this));
1215 
1216     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1217         return false;
1218     }
1219 
1220     if (!writer->Write<uint16_t>(type_->GetIndex(this))) {
1221         return false;
1222     }
1223 
1224     return writer->Write(name_->GetOffset());
1225 }
1226 
FieldItem(ClassItem * cls,StringItem * name,TypeItem * type,uint32_t accessFlags)1227 FieldItem::FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags)
1228     : BaseFieldItem(cls, name, type), accessFlags_(accessFlags)
1229 {
1230 }
1231 
SetValue(ValueItem * value)1232 void FieldItem::SetValue(ValueItem *value)
1233 {
1234     value_ = value;
1235     value_->SetNeedsEmit(!value_->Is32bit());
1236 }
1237 
CalculateSize() const1238 size_t FieldItem::CalculateSize() const
1239 {
1240     size_t size = BaseFieldItem::CalculateSize() + leb128::UnsignedEncodingSize(accessFlags_);
1241 
1242     if (value_ != nullptr) {
1243         if (value_->GetType() == ValueItem::Type::INTEGER) {
1244             size += TAG_SIZE + value_->GetAsScalar()->GetSLeb128EncodedSize();
1245         } else {
1246             size += TAG_SIZE + ID_SIZE;
1247         }
1248     }
1249 
1250     size += (TAG_SIZE + ID_SIZE) * runtimeAnnotations_.size();
1251     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
1252     size += (TAG_SIZE + ID_SIZE) * runtimeTypeAnnotations_.size();
1253     size += (TAG_SIZE + ID_SIZE) * typeAnnotations_.size();
1254 
1255     size += TAG_SIZE;  // null tag
1256 
1257     return size;
1258 }
1259 
WriteValue(Writer * writer)1260 bool FieldItem::WriteValue(Writer *writer)
1261 {
1262     if (value_ == nullptr) {
1263         return true;
1264     }
1265 
1266     if (value_->GetType() == ValueItem::Type::INTEGER) {
1267         auto v = static_cast<int32_t>(value_->GetAsScalar()->GetValue<uint32_t>());
1268         if (!WriteSlebTaggedValue(writer, FieldTag::INT_VALUE, v)) {
1269             return false;
1270         }
1271     } else if (value_->GetType() == ValueItem::Type::FLOAT) {
1272         auto v = bit_cast<uint32_t>(value_->GetAsScalar()->GetValue<float>());
1273         if (!WriteTaggedValue(writer, FieldTag::VALUE, v)) {
1274             return false;
1275         }
1276     } else if (value_->GetType() == ValueItem::Type::ID) {
1277         auto id = value_->GetAsScalar()->GetId();
1278         ASSERT(id.GetOffset() != 0);
1279         if (!WriteTaggedValue(writer, FieldTag::VALUE, id.GetOffset())) {
1280             return false;
1281         }
1282     } else {
1283         ASSERT(!value_->Is32bit());
1284         if (!WriteIdTaggedValue(writer, FieldTag::VALUE, value_)) {
1285             return false;
1286         }
1287     }
1288 
1289     return true;
1290 }
1291 
WriteAnnotations(Writer * writer)1292 bool FieldItem::WriteAnnotations(Writer *writer)
1293 {
1294     for (auto runtimeAnnotation : runtimeAnnotations_) {
1295         if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_ANNOTATION, runtimeAnnotation)) {
1296             return false;
1297         }
1298     }
1299 
1300     for (auto annotation : annotations_) {
1301         if (!WriteIdTaggedValue(writer, FieldTag::ANNOTATION, annotation)) {
1302             return false;
1303         }
1304     }
1305 
1306     for (auto runtimeTypeAnnotation : runtimeTypeAnnotations_) {
1307         if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_TYPE_ANNOTATION, runtimeTypeAnnotation)) {
1308             return false;
1309         }
1310     }
1311 
1312     for (auto typeAnnotation : typeAnnotations_) {
1313         if (!WriteIdTaggedValue(writer, FieldTag::TYPE_ANNOTATION, typeAnnotation)) {
1314             return false;
1315         }
1316     }
1317 
1318     return true;
1319 }
1320 
WriteTaggedData(Writer * writer)1321 bool FieldItem::WriteTaggedData(Writer *writer)
1322 {
1323     if (!WriteValue(writer)) {
1324         return false;
1325     }
1326 
1327     if (!WriteAnnotations(writer)) {
1328         return false;
1329     }
1330 
1331     return writer->WriteByte(static_cast<uint8_t>(FieldTag::NOTHING));
1332 }
1333 
Write(Writer * writer)1334 bool FieldItem::Write(Writer *writer)
1335 {
1336     if (!BaseFieldItem::Write(writer)) {
1337         return false;
1338     }
1339 
1340     if (!writer->WriteUleb128(accessFlags_)) {
1341         return false;
1342     }
1343 
1344     return WriteTaggedData(writer);
1345 }
1346 
CalculateSize() const1347 size_t AnnotationItem::CalculateSize() const
1348 {
1349     // class id + count + (name id + value id) * count + tag size * count
1350     size_t size = IDX_SIZE + sizeof(uint16_t) + (ID_SIZE + ID_SIZE) * elements_.size() + sizeof(uint8_t) * tags_.size();
1351 
1352     return size;
1353 }
1354 
Write(Writer * writer)1355 bool AnnotationItem::Write(Writer *writer)
1356 {
1357     ASSERT(GetOffset() == writer->GetOffset());
1358     ASSERT(class_->HasIndex(this));
1359 
1360     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1361         return false;
1362     }
1363 
1364     if (!writer->Write(static_cast<uint16_t>(elements_.size()))) {
1365         return false;
1366     }
1367 
1368     for (auto elem : elements_) {
1369         ASSERT(elem.GetName()->GetOffset() != 0);
1370         if (!writer->Write(elem.GetName()->GetOffset())) {
1371             return false;
1372         }
1373 
1374         ValueItem *valueItem = elem.GetValue();
1375 
1376         switch (valueItem->GetType()) {
1377             case ValueItem::Type::INTEGER: {
1378                 if (!writer->Write(valueItem->GetAsScalar()->GetValue<uint32_t>())) {
1379                     return false;
1380                 }
1381                 break;
1382             }
1383             case ValueItem::Type::FLOAT: {
1384                 if (!writer->Write(bit_cast<uint32_t>(valueItem->GetAsScalar()->GetValue<float>()))) {
1385                     return false;
1386                 }
1387                 break;
1388             }
1389             case ValueItem::Type::ID: {
1390                 if (!writer->Write(valueItem->GetAsScalar()->GetId().GetOffset())) {
1391                     return false;
1392                 }
1393                 break;
1394             }
1395             default: {
1396                 ASSERT(valueItem->GetOffset() != 0);
1397                 if (!writer->Write(valueItem->GetOffset())) {
1398                     return false;
1399                 }
1400                 break;
1401             }
1402         }
1403     }
1404 
1405     for (auto tag : tags_) {
1406         if (!writer->Write(tag.GetItem())) {
1407             return false;
1408         }
1409     }
1410 
1411     return true;
1412 }
1413 
EmitEnd()1414 void LineNumberProgramItemBase::EmitEnd()
1415 {
1416     EmitOpcode(Opcode::END_SEQUENCE);
1417 }
1418 
EmitAdvancePc(std::vector<uint8_t> * constantPool,uint32_t value)1419 void LineNumberProgramItemBase::EmitAdvancePc(std::vector<uint8_t> *constantPool, uint32_t value)
1420 {
1421     EmitOpcode(Opcode::ADVANCE_PC);
1422     EmitUleb128(constantPool, value);
1423 }
1424 
EmitAdvanceLine(std::vector<uint8_t> * constantPool,int32_t value)1425 void LineNumberProgramItemBase::EmitAdvanceLine(std::vector<uint8_t> *constantPool, int32_t value)
1426 {
1427     EmitOpcode(Opcode::ADVANCE_LINE);
1428     EmitSleb128(constantPool, value);
1429 }
1430 
EmitColumn(std::vector<uint8_t> * constantPool,uint32_t pcInc,uint32_t column)1431 void LineNumberProgramItemBase::EmitColumn(std::vector<uint8_t> *constantPool, uint32_t pcInc, uint32_t column)
1432 {
1433     if (pcInc != 0U) {
1434         EmitAdvancePc(constantPool, pcInc);
1435     }
1436     EmitOpcode(Opcode::SET_COLUMN);
1437     EmitUleb128(constantPool, column);
1438 }
1439 
EmitStartLocal(std::vector<uint8_t> * constantPool,int32_t registerNumber,StringItem * name,StringItem * type)1440 void LineNumberProgramItemBase::EmitStartLocal(std::vector<uint8_t> *constantPool, int32_t registerNumber,
1441                                                StringItem *name, StringItem *type)
1442 {
1443     EmitStartLocalExtended(constantPool, registerNumber, name, type, nullptr);
1444 }
1445 
EmitStartLocalExtended(std::vector<uint8_t> * constantPool,int32_t registerNumber,StringItem * name,StringItem * type,StringItem * typeSignature)1446 void LineNumberProgramItemBase::EmitStartLocalExtended(std::vector<uint8_t> *constantPool, int32_t registerNumber,
1447                                                        StringItem *name, StringItem *type, StringItem *typeSignature)
1448 {
1449     if (type == nullptr) {
1450         return;
1451     }
1452 
1453     ASSERT(name != nullptr);
1454     ASSERT(name->GetOffset() != 0);
1455     ASSERT(type->GetOffset() != 0);
1456 
1457     EmitOpcode(typeSignature == nullptr ? Opcode::START_LOCAL : Opcode::START_LOCAL_EXTENDED);
1458     EmitRegister(registerNumber);
1459     EmitUleb128(constantPool, name->GetOffset());
1460     EmitUleb128(constantPool, type->GetOffset());
1461 
1462     if (typeSignature != nullptr) {
1463         ASSERT(typeSignature->GetOffset() != 0);
1464         EmitUleb128(constantPool, typeSignature->GetOffset());
1465     }
1466 }
1467 
EmitEndLocal(int32_t registerNumber)1468 void LineNumberProgramItemBase::EmitEndLocal(int32_t registerNumber)
1469 {
1470     EmitOpcode(Opcode::END_LOCAL);
1471     EmitRegister(registerNumber);
1472 }
1473 
EmitRestartLocal(int32_t registerNumber)1474 void LineNumberProgramItemBase::EmitRestartLocal(int32_t registerNumber)
1475 {
1476     EmitOpcode(Opcode::RESTART_LOCAL);
1477     EmitRegister(registerNumber);
1478 }
1479 
EmitSpecialOpcode(uint32_t pcInc,int32_t lineInc)1480 bool LineNumberProgramItemBase::EmitSpecialOpcode(uint32_t pcInc, int32_t lineInc)
1481 {
1482     if (lineInc < LINE_BASE || (lineInc - LINE_BASE) >= LINE_RANGE) {
1483         return false;
1484     }
1485 
1486     auto opcode = static_cast<size_t>(lineInc - LINE_BASE) + static_cast<size_t>(pcInc * LINE_RANGE) + OPCODE_BASE;
1487     if (opcode > std::numeric_limits<uint8_t>::max()) {
1488         return false;
1489     }
1490 
1491     EmitOpcode(static_cast<uint8_t>(opcode));
1492     return true;
1493 }
1494 
EmitPrologueEnd()1495 void LineNumberProgramItemBase::EmitPrologueEnd()
1496 {
1497     EmitOpcode(Opcode::SET_PROLOGUE_END);
1498 }
1499 
EmitEpilogueBegin()1500 void LineNumberProgramItemBase::EmitEpilogueBegin()
1501 {
1502     EmitOpcode(Opcode::SET_EPILOGUE_BEGIN);
1503 }
1504 
EmitSetFile(std::vector<uint8_t> * constantPool,StringItem * sourceFile)1505 void LineNumberProgramItemBase::EmitSetFile(std::vector<uint8_t> *constantPool, StringItem *sourceFile)
1506 {
1507     ASSERT(sourceFile);
1508     ASSERT(sourceFile->GetOffset() != 0);
1509 
1510     EmitOpcode(Opcode::SET_FILE);
1511     EmitUleb128(constantPool, sourceFile->GetOffset());
1512 }
1513 
EmitSetSourceCode(std::vector<uint8_t> * constantPool,StringItem * sourceCode)1514 void LineNumberProgramItemBase::EmitSetSourceCode(std::vector<uint8_t> *constantPool, StringItem *sourceCode)
1515 {
1516     ASSERT(sourceCode);
1517     ASSERT(sourceCode->GetOffset() != 0);
1518 
1519     EmitOpcode(Opcode::SET_SOURCE_CODE);
1520     EmitUleb128(constantPool, sourceCode->GetOffset());
1521 }
1522 
EmitOpcode(Opcode opcode)1523 void LineNumberProgramItemBase::EmitOpcode(Opcode opcode)
1524 {
1525     EmitOpcode(static_cast<uint8_t>(opcode));
1526 }
1527 
1528 /* static */
EmitUleb128(std::vector<uint8_t> * data,uint32_t value)1529 void LineNumberProgramItemBase::EmitUleb128(std::vector<uint8_t> *data, uint32_t value)
1530 {
1531     ASSERT(data);
1532 
1533     size_t n = leb128::UnsignedEncodingSize(value);
1534     std::vector<uint8_t> out(n);
1535     leb128::EncodeUnsigned(value, out.data());
1536     data->insert(data->end(), out.cbegin(), out.cend());
1537 }
1538 
1539 /* static */
EmitSleb128(std::vector<uint8_t> * data,int32_t value)1540 void LineNumberProgramItemBase::EmitSleb128(std::vector<uint8_t> *data, int32_t value)
1541 {
1542     ASSERT(data);
1543 
1544     size_t n = leb128::SignedEncodingSize(value);
1545     std::vector<uint8_t> out(n);
1546     leb128::EncodeSigned(value, out.data());
1547     data->insert(data->end(), out.cbegin(), out.cend());
1548 }
1549 
EmitOpcode(uint8_t opcode)1550 void LineNumberProgramItem::EmitOpcode(uint8_t opcode)
1551 {
1552     data_.push_back(opcode);
1553 }
1554 
EmitRegister(int32_t registerNumber)1555 void LineNumberProgramItem::EmitRegister(int32_t registerNumber)
1556 {
1557     EmitSleb128(&data_, registerNumber);
1558 }
1559 
CalculateSize() const1560 size_t LineNumberProgramItem::CalculateSize() const
1561 {
1562     return data_.size();
1563 }
1564 
Write(Writer * writer)1565 bool LineNumberProgramItem::Write(Writer *writer)
1566 {
1567     ASSERT(GetOffset() == writer->GetOffset());
1568 
1569     return writer->WriteBytes(data_);
1570 }
1571 
SetData(std::vector<uint8_t> && data)1572 void LineNumberProgramItem::SetData(std::vector<uint8_t> &&data)
1573 {
1574     data_ = std::move(data);
1575 }
1576 
CalculateSize() const1577 size_t DebugInfoItem::CalculateSize() const
1578 {
1579     size_t n = leb128::UnsignedEncodingSize(lineNum_) + leb128::UnsignedEncodingSize(parameters_.size());
1580 
1581     for (auto *p : parameters_) {
1582         ASSERT(p == nullptr || p->GetOffset() != 0);
1583         n += leb128::UnsignedEncodingSize(p == nullptr ? 0 : p->GetOffset());
1584     }
1585 
1586     n += leb128::UnsignedEncodingSize(constantPool_.size());
1587     n += constantPool_.size();
1588 
1589     n += leb128::UnsignedEncodingSize(program_->GetIndex(this));
1590 
1591     return n;
1592 }
1593 
Write(Writer * writer)1594 bool DebugInfoItem::Write(Writer *writer)
1595 {
1596     ASSERT(GetOffset() == writer->GetOffset());
1597 
1598     if (!writer->WriteUleb128(lineNum_)) {
1599         return false;
1600     }
1601 
1602     if (!writer->WriteUleb128(parameters_.size())) {
1603         return false;
1604     }
1605 
1606     for (auto *p : parameters_) {
1607         ASSERT(p == nullptr || p->GetOffset() != 0);
1608 
1609         if (!writer->WriteUleb128(p == nullptr ? 0 : p->GetOffset())) {
1610             return false;
1611         }
1612     }
1613 
1614     if (!writer->WriteUleb128(constantPool_.size())) {
1615         return false;
1616     }
1617 
1618     if (!writer->WriteBytes(constantPool_)) {
1619         return false;
1620     }
1621 
1622     ASSERT(program_ != nullptr);
1623     ASSERT(program_->HasIndex(this));
1624 
1625     return writer->WriteUleb128(program_->GetIndex(this));
1626 }
1627 
Dump(std::ostream & os) const1628 void DebugInfoItem::Dump(std::ostream &os) const
1629 {
1630     os << "line_start = " << lineNum_ << std::endl;
1631 
1632     os << "num_parameters = " << parameters_.size() << std::endl;
1633     for (auto *item : parameters_) {
1634         if (item != nullptr) {
1635             os << "  string_item[" << item->GetOffset() << "]" << std::endl;
1636         } else {
1637             os << "  string_item[INVALID_OFFSET]" << std::endl;
1638         }
1639     }
1640 
1641     os << "constant_pool = [";
1642     for (size_t i = 0; i < constantPool_.size(); i++) {
1643         size_t b = constantPool_[i];
1644         os << "0x" << std::setfill('0') << std::setw(2U) << std::right << std::hex << b << std::dec;
1645         if (i < constantPool_.size() - 1) {
1646             os << ", ";
1647         }
1648     }
1649     os << "]" << std::endl;
1650 
1651     os << "line_number_program = line_number_program_idx[";
1652     if (program_ != nullptr && program_->HasIndex(this)) {
1653         os << program_->GetIndex(this);
1654     } else {
1655         os << "NO_INDEX";
1656     }
1657     os << "]";
1658 }
1659 
Write(Writer * writer)1660 bool MethodHandleItem::Write(Writer *writer)
1661 {
1662     ASSERT(GetOffset() == writer->GetOffset());
1663 
1664     if (!writer->WriteByte(static_cast<uint8_t>(type_))) {
1665         return false;
1666     }
1667 
1668     return writer->WriteUleb128(entity_->GetOffset());
1669 }
1670 
1671 }  // namespace ark::panda_file
1672