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