• 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(const std::string_view & lang)32 std::optional<panda::panda_file::SourceLang> LanguageFromString(const 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     const auto bc_version = GetVersionByApi(ItemContainer::GetApi(), ItemContainer::GetSubApi());
506     if (bc_version.value().front() >= API_12) {
507         // no need to emit protoItem
508         SetNeedsEmit(false);
509     }
510 }
511 
AddType(TypeItem * type,size_t * n)512 void ProtoItem::AddType(TypeItem *type, size_t *n)
513 {
514     constexpr size_t SHORTY_ELEMS_COUNT = std::numeric_limits<uint16_t>::digits / SHORTY_ELEM_SIZE;
515 
516     uint16_t v = shorty_.back();
517 
518     size_t shift = (*n % SHORTY_ELEMS_COUNT) * SHORTY_ELEM_SIZE;
519 
520     v |= static_cast<uint16_t>(static_cast<uint16_t>(type->GetType().GetEncoding()) << shift);
521     shorty_.back() = v;
522 
523     if (!type->GetType().IsPrimitive()) {
524         reference_types_.push_back(type);
525         AddIndexDependency(type);
526     }
527 
528     *n += 1;
529 
530     if (*n % SHORTY_ELEMS_COUNT == 0) {
531         shorty_.push_back(0);
532     }
533 }
534 
Write(Writer * writer)535 bool ProtoItem::Write(Writer *writer)
536 {
537     ASSERT(GetOffset() == writer->GetOffset());
538     for (auto s : shorty_) {
539         if (!writer->Write(s)) {
540             return false;
541         }
542     }
543 
544     for (auto r : reference_types_) {
545         ASSERT(r->HasIndex(this));
546         if (!writer->Write<uint16_t>(r->GetIndex(this))) {
547             return false;
548         }
549     }
550 
551     return true;
552 }
553 
BaseMethodItem(BaseClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t access_flags,ItemContainer * container)554 BaseMethodItem::BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags,
555     ItemContainer *container)
556     : IndexedItem(container), class_(cls), name_(name), proto_(proto), access_flags_(access_flags)
557 {
558     AddIndexDependency(cls);
559     AddIndexDependency(proto);
560 }
561 
CalculateSize() const562 size_t BaseMethodItem::CalculateSize() const
563 {
564     // class id + proto id + name id + access flags
565     return IDX_SIZE + IDX_SIZE + ID_SIZE + leb128::UnsignedEncodingSize(access_flags_);
566 }
567 
Write(Writer * writer)568 bool BaseMethodItem::Write(Writer *writer)
569 {
570     ASSERT(GetOffset() == writer->GetOffset());
571     ASSERT(class_ != nullptr);
572     ASSERT(class_->HasIndex(this));
573 
574     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
575         return false;
576     }
577 
578     const auto bc_version = GetVersionByApi(ItemContainer::GetApi(), ItemContainer::GetSubApi());
579     if (bc_version.value().front() >= API_12) {
580         // reserve [proto_idx] field, write invalid index
581         if (!writer->Write<uint16_t>(INVALID_INDEX_16)) {
582             return false;
583         }
584     } else {
585         ASSERT(proto_->HasIndex(this));
586 
587         if (!writer->Write<uint16_t>(proto_->GetIndex(this))) {
588             return false;
589         }
590     }
591 
592     ASSERT(name_->GetOffset() != 0);
593 
594     if (!writer->Write(name_->GetOffset())) {
595         return false;
596     }
597 
598     return writer->WriteUleb128(access_flags_);
599 }
600 
MethodItem(ClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t access_flags,std::vector<MethodParamItem> params,ItemContainer * container)601 MethodItem::MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags,
602                        std::vector<MethodParamItem> params, ItemContainer *container)
603     : BaseMethodItem(cls, name, proto, access_flags, container),
604       params_(std::move(params)),
605       source_lang_(SourceLang::PANDA_ASSEMBLY),
606       code_(nullptr),
607       debug_info_(nullptr)
608 {
609 }
610 
CalculateSize() const611 size_t MethodItem::CalculateSize() const
612 {
613     size_t size = BaseMethodItem::CalculateSize();
614 
615     if (code_ != nullptr) {
616         size += TAG_SIZE + ID_SIZE;
617     }
618 
619     if (source_lang_ != SourceLang::PANDA_ASSEMBLY) {
620         size += TAG_SIZE + sizeof(SourceLang);
621     }
622 
623     size += (TAG_SIZE + ID_SIZE) * runtime_annotations_.size();
624 
625     if (runtime_param_annotations_ != nullptr) {
626         size += TAG_SIZE + ID_SIZE;
627     }
628 
629     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
630 
631     if (param_annotations_ != nullptr) {
632         size += TAG_SIZE + ID_SIZE;
633     }
634 
635     size += (TAG_SIZE + ID_SIZE) * runtime_type_annotations_.size();
636     size += (TAG_SIZE + ID_SIZE) * type_annotations_.size();
637 
638     if (debug_info_ != nullptr) {
639         size += TAG_SIZE + ID_SIZE;
640     }
641 
642     size += TAG_SIZE;  // null tag
643 
644     return size;
645 }
646 
WriteRuntimeAnnotations(Writer * writer)647 bool MethodItem::WriteRuntimeAnnotations(Writer *writer)
648 {
649     for (auto runtime_annotation : runtime_annotations_) {
650         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_ANNOTATION, runtime_annotation)) {
651             return false;
652         }
653     }
654 
655     if (runtime_param_annotations_ != nullptr) {
656         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_PARAM_ANNOTATION, runtime_param_annotations_)) {
657             return false;
658         }
659     }
660 
661     return true;
662 }
663 
WriteTypeAnnotations(Writer * writer)664 bool MethodItem::WriteTypeAnnotations(Writer *writer)
665 {
666     for (auto runtime_type_annotation : runtime_type_annotations_) {
667         if (!WriteIdTaggedValue(writer, MethodTag::RUNTIME_TYPE_ANNOTATION, runtime_type_annotation)) {
668             return false;
669         }
670     }
671 
672     for (auto type_annotation : type_annotations_) {
673         if (!WriteIdTaggedValue(writer, MethodTag::TYPE_ANNOTATION, type_annotation)) {
674             return false;
675         }
676     }
677 
678     return true;
679 }
680 
WriteTaggedData(Writer * writer)681 bool MethodItem::WriteTaggedData(Writer *writer)
682 {
683     if (code_ != nullptr) {
684         if (!WriteIdTaggedValue(writer, MethodTag::CODE, code_)) {
685             return false;
686         }
687     }
688 
689     if (source_lang_ != SourceLang::PANDA_ASSEMBLY) {
690         if (!WriteTaggedValue(writer, MethodTag::SOURCE_LANG, static_cast<uint8_t>(source_lang_))) {
691             return false;
692         }
693     }
694 
695     if (!WriteRuntimeAnnotations(writer)) {
696         return false;
697     }
698 
699     if (debug_info_ != nullptr) {
700         if (!WriteIdTaggedValue(writer, MethodTag::DEBUG_INFO, debug_info_)) {
701             return false;
702         }
703     }
704 
705     for (auto annotation : annotations_) {
706         if (!WriteIdTaggedValue(writer, MethodTag::ANNOTATION, annotation)) {
707             return false;
708         }
709     }
710 
711     if (!WriteTypeAnnotations(writer)) {
712         return false;
713     }
714 
715     if (param_annotations_ != nullptr) {
716         if (!WriteIdTaggedValue(writer, MethodTag::PARAM_ANNOTATION, param_annotations_)) {
717             return false;
718         }
719     }
720 
721     return writer->WriteByte(static_cast<uint8_t>(MethodTag::NOTHING));
722 }
723 
Write(Writer * writer)724 bool MethodItem::Write(Writer *writer)
725 {
726     if (!BaseMethodItem::Write(writer)) {
727         return false;
728     }
729 
730     return WriteTaggedData(writer);
731 }
732 
CalculateSize() const733 size_t CodeItem::CatchBlock::CalculateSize() const
734 {
735     ASSERT(type_ == nullptr || type_->HasIndex(method_));
736     uint32_t type_off = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
737     return leb128::UnsignedEncodingSize(type_off) + leb128::UnsignedEncodingSize(handler_pc_) +
738            leb128::UnsignedEncodingSize(code_size_);
739 }
740 
Write(Writer * writer)741 bool CodeItem::CatchBlock::Write(Writer *writer)
742 {
743     ASSERT(GetOffset() == writer->GetOffset());
744     ASSERT(type_ == nullptr || type_->HasIndex(method_));
745 
746     uint32_t type_off = type_ != nullptr ? type_->GetIndex(method_) + 1 : 0;
747 
748     if (!writer->WriteUleb128(type_off)) {
749         return false;
750     }
751 
752     if (!writer->WriteUleb128(handler_pc_)) {
753         return false;
754     }
755 
756     if (!writer->WriteUleb128(code_size_)) {
757         return false;
758     }
759 
760     return true;
761 }
762 
ComputeLayout()763 void CodeItem::TryBlock::ComputeLayout()
764 {
765     size_t offset = GetOffset();
766     offset += CalculateSizeWithoutCatchBlocks();
767 
768     for (auto &catch_block : catch_blocks_) {
769         catch_block.SetOffset(offset);
770         catch_block.ComputeLayout();
771         offset += catch_block.GetSize();
772     }
773 }
774 
CalculateSizeWithoutCatchBlocks() const775 size_t CodeItem::TryBlock::CalculateSizeWithoutCatchBlocks() const
776 {
777     return leb128::UnsignedEncodingSize(start_pc_) + leb128::UnsignedEncodingSize(length_) +
778            leb128::UnsignedEncodingSize(catch_blocks_.size());
779 }
780 
CalculateSize() const781 size_t CodeItem::TryBlock::CalculateSize() const
782 {
783     size_t size = CalculateSizeWithoutCatchBlocks();
784 
785     for (auto &catch_block : catch_blocks_) {
786         size += catch_block.GetSize();
787     }
788 
789     return size;
790 }
791 
Write(Writer * writer)792 bool CodeItem::TryBlock::Write(Writer *writer)
793 {
794     ASSERT(GetOffset() == writer->GetOffset());
795 
796     if (!writer->WriteUleb128(start_pc_)) {
797         return false;
798     }
799 
800     if (!writer->WriteUleb128(length_)) {
801         return false;
802     }
803 
804     if (!writer->WriteUleb128(catch_blocks_.size())) {
805         return false;
806     }
807 
808     for (auto &catch_block : catch_blocks_) {
809         if (!catch_block.Write(writer)) {
810             return false;
811         }
812     }
813 
814     return true;
815 }
816 
ComputeLayout()817 void CodeItem::ComputeLayout()
818 {
819     uint32_t offset = GetOffset();
820 
821     offset += CalculateSizeWithoutTryBlocks();
822 
823     for (auto &try_block : try_blocks_) {
824         try_block.SetOffset(offset);
825         try_block.ComputeLayout();
826         offset += try_block.GetSize();
827     }
828 }
829 
CalculateSizeWithoutTryBlocks() const830 size_t CodeItem::CalculateSizeWithoutTryBlocks() const
831 {
832     size_t size = leb128::UnsignedEncodingSize(num_vregs_) + leb128::UnsignedEncodingSize(num_args_) +
833                   leb128::UnsignedEncodingSize(instructions_.size()) + leb128::UnsignedEncodingSize(try_blocks_.size());
834 
835     size += instructions_.size();
836 
837     return size;
838 }
839 
GetCodeSize() const840 size_t CodeItem::GetCodeSize() const
841 {
842     return instructions_.size();
843 }
844 
CalculateSize() const845 size_t CodeItem::CalculateSize() const
846 {
847     size_t size = CalculateSizeWithoutTryBlocks();
848 
849     for (auto &try_block : try_blocks_) {
850         size += try_block.GetSize();
851     }
852 
853     return size;
854 }
855 
Write(Writer * writer)856 bool CodeItem::Write(Writer *writer)
857 {
858     ASSERT(GetOffset() == writer->GetOffset());
859 
860     if (!writer->WriteUleb128(num_vregs_)) {
861         return false;
862     }
863 
864     if (!writer->WriteUleb128(num_args_)) {
865         return false;
866     }
867 
868     if (!writer->WriteUleb128(instructions_.size())) {
869         return false;
870     }
871 
872     if (!writer->WriteUleb128(try_blocks_.size())) {
873         return false;
874     }
875 
876     if (!writer->WriteBytes(instructions_)) {
877         return false;
878     }
879 
880     for (auto &try_block : try_blocks_) {
881         if (!try_block.Write(writer)) {
882             return false;
883         }
884     }
885 
886     return true;
887 }
888 
GetAsScalar()889 ScalarValueItem *ValueItem::GetAsScalar()
890 {
891     ASSERT(!IsArray());
892     return static_cast<ScalarValueItem *>(this);
893 }
894 
GetAsArray()895 ArrayValueItem *ValueItem::GetAsArray()
896 {
897     ASSERT(IsArray());
898     return static_cast<ArrayValueItem *>(this);
899 }
900 
GetULeb128EncodedSize()901 size_t ScalarValueItem::GetULeb128EncodedSize()
902 {
903     switch (GetType()) {
904         case Type::INTEGER:
905             return leb128::UnsignedEncodingSize(GetValue<uint32_t>());
906 
907         case Type::LONG:
908             return leb128::UnsignedEncodingSize(GetValue<uint64_t>());
909 
910         case Type::ID:
911             return leb128::UnsignedEncodingSize(GetId().GetOffset());
912 
913         default:
914             return 0;
915     }
916 }
917 
GetSLeb128EncodedSize()918 size_t ScalarValueItem::GetSLeb128EncodedSize()
919 {
920     switch (GetType()) {
921         case Type::INTEGER:
922             return leb128::SignedEncodingSize(static_cast<int32_t>(GetValue<uint32_t>()));
923 
924         case Type::LONG:
925             return leb128::SignedEncodingSize(static_cast<int64_t>(GetValue<uint64_t>()));
926 
927         default:
928             return 0;
929     }
930 }
931 
CalculateSize() const932 size_t ScalarValueItem::CalculateSize() const
933 {
934     size_t size = 0;
935     switch (GetType()) {
936         case Type::INTEGER: {
937             size = sizeof(uint32_t);
938             break;
939         }
940 
941         case Type::LONG: {
942             size = sizeof(uint64_t);
943             break;
944         }
945 
946         case Type::FLOAT: {
947             size = sizeof(float);
948             break;
949         }
950 
951         case Type::DOUBLE: {
952             size = sizeof(double);
953             break;
954         }
955 
956         case Type::ID: {
957             size = ID_SIZE;
958             break;
959         }
960         default: {
961             UNREACHABLE();
962             break;
963         }
964     }
965 
966     return size;
967 }
968 
Alignment()969 size_t ScalarValueItem::Alignment()
970 {
971     return GetSize();
972 }
973 
Write(Writer * writer)974 bool ScalarValueItem::Write(Writer *writer)
975 {
976     ASSERT(GetOffset() == writer->GetOffset());
977 
978     switch (GetType()) {
979         case Type::INTEGER:
980             return writer->Write(GetValue<uint32_t>());
981 
982         case Type::LONG:
983             return writer->Write(GetValue<uint64_t>());
984 
985         case Type::FLOAT:
986             return writer->Write(bit_cast<uint32_t>(GetValue<float>()));
987 
988         case Type::DOUBLE:
989             return writer->Write(bit_cast<uint64_t>(GetValue<double>()));
990 
991         case Type::ID: {
992             ASSERT(GetId().IsValid());
993             return writer->Write(GetId().GetOffset());
994         }
995         default: {
996             UNREACHABLE();
997             break;
998         }
999     }
1000 
1001     return true;
1002 }
1003 
WriteAsUleb128(Writer * writer)1004 bool ScalarValueItem::WriteAsUleb128(Writer *writer)
1005 {
1006     ASSERT(GetOffset() == writer->GetOffset());
1007 
1008     switch (GetType()) {
1009         case Type::INTEGER:
1010             return writer->WriteUleb128(GetValue<uint32_t>());
1011 
1012         case Type::LONG:
1013             return writer->WriteUleb128(GetValue<uint64_t>());
1014 
1015         case Type::ID: {
1016             ASSERT(GetId().IsValid());
1017             return writer->WriteUleb128(GetId().GetOffset());
1018         }
1019         default:
1020             return false;
1021     }
1022 }
1023 
CalculateSize() const1024 size_t ArrayValueItem::CalculateSize() const
1025 {
1026     size_t size = leb128::UnsignedEncodingSize(items_.size()) + items_.size() * GetComponentSize();
1027     return size;
1028 }
1029 
ComputeLayout()1030 void ArrayValueItem::ComputeLayout()
1031 {
1032     uint32_t offset = GetOffset();
1033 
1034     ASSERT(offset != 0);
1035 
1036     offset += leb128::UnsignedEncodingSize(items_.size());
1037 
1038     for (auto &item : items_) {
1039         item.SetOffset(offset);
1040         offset += GetComponentSize();
1041     }
1042 }
1043 
Write(Writer * writer)1044 bool ArrayValueItem::Write(Writer *writer)
1045 {
1046     ASSERT(GetOffset() == writer->GetOffset());
1047 
1048     if (!writer->WriteUleb128(items_.size())) {
1049         return false;
1050     }
1051 
1052     switch (component_type_.GetId()) {
1053         case panda_file::Type::TypeId::U1:
1054         case panda_file::Type::TypeId::I8:
1055         case panda_file::Type::TypeId::U8: {
1056             for (auto &item : items_) {
1057                 auto value = static_cast<uint8_t>(item.GetValue<uint32_t>());
1058                 if (!writer->Write(value)) {
1059                     return false;
1060                 }
1061             }
1062             break;
1063         }
1064         case panda_file::Type::TypeId::I16:
1065         case panda_file::Type::TypeId::U16: {
1066             for (auto &item : items_) {
1067                 auto value = static_cast<uint16_t>(item.GetValue<uint32_t>());
1068                 if (!writer->Write(value)) {
1069                     return false;
1070                 }
1071             }
1072             break;
1073         }
1074         default: {
1075             for (auto &item : items_) {
1076                 if (!item.Write(writer)) {
1077                     return false;
1078                 }
1079             }
1080             break;
1081         }
1082     }
1083 
1084     return true;
1085 }
1086 
GetComponentSize() const1087 size_t ArrayValueItem::GetComponentSize() const
1088 {
1089     switch (component_type_.GetId()) {
1090         case panda_file::Type::TypeId::U1:
1091         case panda_file::Type::TypeId::I8:
1092         case panda_file::Type::TypeId::U8:
1093             return sizeof(uint8_t);
1094         case panda_file::Type::TypeId::I16:
1095         case panda_file::Type::TypeId::U16:
1096             return sizeof(uint16_t);
1097         case panda_file::Type::TypeId::I32:
1098         case panda_file::Type::TypeId::U32:
1099         case panda_file::Type::TypeId::F32:
1100             return sizeof(uint32_t);
1101         case panda_file::Type::TypeId::I64:
1102         case panda_file::Type::TypeId::U64:
1103         case panda_file::Type::TypeId::F64:
1104             return sizeof(uint64_t);
1105         case panda_file::Type::TypeId::REFERENCE:
1106             return ID_SIZE;
1107         case panda_file::Type::TypeId::VOID:
1108             return 0;
1109         default: {
1110             UNREACHABLE();
1111             // Avoid cpp warning
1112             return 0;
1113         }
1114     }
1115 }
1116 
CalculateSize() const1117 size_t LiteralItem::CalculateSize() const
1118 {
1119     size_t size = 0;
1120     switch (GetType()) {
1121         case Type::B1: {
1122             size = sizeof(uint8_t);
1123             break;
1124         }
1125 
1126         case Type::B2: {
1127             size = sizeof(uint16_t);
1128             break;
1129         }
1130 
1131         case Type::B4: {
1132             size = sizeof(uint32_t);
1133             break;
1134         }
1135 
1136         case Type::B8: {
1137             size = sizeof(uint64_t);
1138             break;
1139         }
1140 
1141         case Type::STRING:
1142         case Type::METHOD:
1143         case Type::LITERALARRAY: {
1144             size = ID_SIZE;
1145             break;
1146         }
1147 
1148         default: {
1149             UNREACHABLE();
1150             break;
1151         }
1152     }
1153 
1154     return size;
1155 }
1156 
Alignment()1157 size_t LiteralItem::Alignment()
1158 {
1159     return GetSize();
1160 }
1161 
GetLiteralArrayFileId() const1162 File::EntityId LiteralItem::GetLiteralArrayFileId() const
1163 {
1164     return File::EntityId(GetValue<LiteralArrayItem *>()->GetOffset());
1165 }
1166 
Write(Writer * writer)1167 bool LiteralItem::Write(Writer *writer)
1168 {
1169     ASSERT(GetOffset() == writer->GetOffset());
1170 
1171     switch (GetType()) {
1172         case Type::B1: {
1173             return writer->Write(GetValue<uint8_t>());
1174         }
1175         case Type::B2: {
1176             return writer->Write(GetValue<uint16_t>());
1177         }
1178         case Type::B4: {
1179             return writer->Write(GetValue<uint32_t>());
1180         }
1181         case Type::B8: {
1182             return writer->Write(GetValue<uint64_t>());
1183         }
1184         case Type::STRING: {
1185             ASSERT(GetId().IsValid());
1186             return writer->Write(GetId().GetOffset());
1187         }
1188         case Type::METHOD: {
1189             ASSERT(GetMethodId().IsValid());
1190             return writer->Write(GetMethodId().GetOffset());
1191         }
1192         case Type::LITERALARRAY: {
1193             ASSERT(GetLiteralArrayFileId().IsValid());
1194             return writer->Write(GetLiteralArrayFileId().GetOffset());
1195         }
1196         default: {
1197             UNREACHABLE();
1198             break;
1199         }
1200     }
1201 
1202     return true;
1203 }
1204 
AddItems(const std::vector<LiteralItem> & item)1205 void LiteralArrayItem::AddItems(const std::vector<LiteralItem> &item)
1206 {
1207     items_.assign(item.begin(), item.end());
1208 }
1209 
CalculateSize() const1210 size_t LiteralArrayItem::CalculateSize() const
1211 {
1212     size_t size = sizeof(uint32_t);
1213     for (auto &item : items_) {
1214         size += item.CalculateSize();
1215     }
1216 
1217     return size;
1218 }
1219 
ComputeLayout()1220 void LiteralArrayItem::ComputeLayout()
1221 {
1222     uint32_t offset = GetOffset();
1223 
1224     ASSERT(offset != 0);
1225 
1226     offset += sizeof(uint32_t);
1227 
1228     for (auto &item : items_) {
1229         item.SetOffset(offset);
1230         offset += item.CalculateSize();
1231     }
1232 }
1233 
Write(Writer * writer)1234 bool LiteralArrayItem::Write(Writer *writer)
1235 {
1236     ASSERT(GetOffset() == writer->GetOffset());
1237 
1238     if (!writer->Write(static_cast<uint32_t>(items_.size()))) {
1239         return false;
1240     }
1241 
1242     for (auto &item : items_) {
1243         if (!item.Write(writer)) {
1244             return false;
1245         }
1246     }
1247 
1248     return true;
1249 }
1250 
BaseFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type,ItemContainer * container)1251 BaseFieldItem::BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, ItemContainer *container)
1252     : IndexedItem(container), class_(cls), name_(name), type_(type)
1253 {
1254     AddIndexDependency(cls);
1255     AddIndexDependency(type);
1256 }
1257 
CalculateSize() const1258 size_t BaseFieldItem::CalculateSize() const
1259 {
1260     // class id + type id + name id
1261     return IDX_SIZE + IDX_SIZE + ID_SIZE;
1262 }
1263 
Write(Writer * writer)1264 bool BaseFieldItem::Write(Writer *writer)
1265 {
1266     ASSERT(GetOffset() == writer->GetOffset());
1267     ASSERT(class_->HasIndex(this));
1268     ASSERT(type_->HasIndex(this));
1269 
1270     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1271         return false;
1272     }
1273 
1274     if (!writer->Write<uint16_t>(type_->GetIndex(this))) {
1275         return false;
1276     }
1277 
1278     return writer->Write(name_->GetOffset());
1279 }
1280 
FieldItem(ClassItem * cls,StringItem * name,TypeItem * type,uint32_t access_flags,ItemContainer * container)1281 FieldItem::FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t access_flags, ItemContainer *container)
1282     : BaseFieldItem(cls, name, type, container), access_flags_(access_flags), value_(nullptr)
1283 {
1284 }
1285 
SetValue(ValueItem * value)1286 void FieldItem::SetValue(ValueItem *value)
1287 {
1288     value_ = value;
1289     value_->SetNeedsEmit(!value_->Is32bit());
1290 }
1291 
CalculateSize() const1292 size_t FieldItem::CalculateSize() const
1293 {
1294     size_t size = BaseFieldItem::CalculateSize() + leb128::UnsignedEncodingSize(access_flags_);
1295 
1296     if (value_ != nullptr) {
1297         if (value_->GetType() == ValueItem::Type::INTEGER) {
1298             size += TAG_SIZE + value_->GetAsScalar()->GetSLeb128EncodedSize();
1299         } else {
1300             size += TAG_SIZE + ID_SIZE;
1301         }
1302     }
1303 
1304     size += (TAG_SIZE + ID_SIZE) * runtime_annotations_.size();
1305     size += (TAG_SIZE + ID_SIZE) * annotations_.size();
1306     size += (TAG_SIZE + ID_SIZE) * runtime_type_annotations_.size();
1307     size += (TAG_SIZE + ID_SIZE) * type_annotations_.size();
1308 
1309     size += TAG_SIZE;  // null tag
1310 
1311     return size;
1312 }
1313 
WriteValue(Writer * writer)1314 bool FieldItem::WriteValue(Writer *writer)
1315 {
1316     if (value_ == nullptr) {
1317         return true;
1318     }
1319 
1320     if (value_->GetType() == ValueItem::Type::INTEGER) {
1321         auto v = static_cast<int32_t>(value_->GetAsScalar()->GetValue<uint32_t>());
1322         if (!WriteSlebTaggedValue(writer, FieldTag::INT_VALUE, v)) {
1323             return false;
1324         }
1325     } else if (value_->GetType() == ValueItem::Type::FLOAT) {
1326         auto v = bit_cast<uint32_t>(value_->GetAsScalar()->GetValue<float>());
1327         if (!WriteTaggedValue(writer, FieldTag::VALUE, v)) {
1328             return false;
1329         }
1330     } else if (value_->GetType() == ValueItem::Type::ID) {
1331         auto id = value_->GetAsScalar()->GetId();
1332         ASSERT(id.GetOffset() != 0);
1333         if (!WriteTaggedValue(writer, FieldTag::VALUE, id.GetOffset())) {
1334             return false;
1335         }
1336     } else {
1337         ASSERT(!value_->Is32bit());
1338         if (!WriteIdTaggedValue(writer, FieldTag::VALUE, value_)) {
1339             return false;
1340         }
1341     }
1342 
1343     return true;
1344 }
1345 
WriteAnnotations(Writer * writer)1346 bool FieldItem::WriteAnnotations(Writer *writer)
1347 {
1348     for (auto runtime_annotation : runtime_annotations_) {
1349         if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_ANNOTATION, runtime_annotation)) {
1350             return false;
1351         }
1352     }
1353 
1354     for (auto annotation : annotations_) {
1355         if (!WriteIdTaggedValue(writer, FieldTag::ANNOTATION, annotation)) {
1356             return false;
1357         }
1358     }
1359 
1360     for (auto runtime_type_annotation : runtime_type_annotations_) {
1361         if (!WriteIdTaggedValue(writer, FieldTag::RUNTIME_TYPE_ANNOTATION, runtime_type_annotation)) {
1362             return false;
1363         }
1364     }
1365 
1366     for (auto type_annotation : type_annotations_) {
1367         if (!WriteIdTaggedValue(writer, FieldTag::TYPE_ANNOTATION, type_annotation)) {
1368             return false;
1369         }
1370     }
1371 
1372     return true;
1373 }
1374 
WriteTaggedData(Writer * writer)1375 bool FieldItem::WriteTaggedData(Writer *writer)
1376 {
1377     if (!WriteValue(writer)) {
1378         return false;
1379     }
1380 
1381     if (!WriteAnnotations(writer)) {
1382         return false;
1383     }
1384 
1385     return writer->WriteByte(static_cast<uint8_t>(FieldTag::NOTHING));
1386 }
1387 
Write(Writer * writer)1388 bool FieldItem::Write(Writer *writer)
1389 {
1390     if (!BaseFieldItem::Write(writer)) {
1391         return false;
1392     }
1393 
1394     if (!writer->WriteUleb128(access_flags_)) {
1395         return false;
1396     }
1397 
1398     return WriteTaggedData(writer);
1399 }
1400 
CalculateSize() const1401 size_t AnnotationItem::CalculateSize() const
1402 {
1403     // class id + count + (name id + value id) * count + tag size * count
1404     size_t size = IDX_SIZE + sizeof(uint16_t) + (ID_SIZE + ID_SIZE) * elements_.size() + sizeof(uint8_t) * tags_.size();
1405 
1406     return size;
1407 }
1408 
Write(Writer * writer)1409 bool AnnotationItem::Write(Writer *writer)
1410 {
1411     ASSERT(GetOffset() == writer->GetOffset());
1412     ASSERT(class_->HasIndex(this));
1413 
1414     if (!writer->Write<uint16_t>(class_->GetIndex(this))) {
1415         return false;
1416     }
1417 
1418     if (!writer->Write(static_cast<uint16_t>(elements_.size()))) {
1419         return false;
1420     }
1421 
1422     for (auto elem : elements_) {
1423         ASSERT(elem.GetName()->GetOffset() != 0);
1424         if (!writer->Write(elem.GetName()->GetOffset())) {
1425             return false;
1426         }
1427 
1428         ValueItem *value_item = elem.GetValue();
1429 
1430         switch (value_item->GetType()) {
1431             case ValueItem::Type::INTEGER: {
1432                 if (!writer->Write(value_item->GetAsScalar()->GetValue<uint32_t>())) {
1433                     return false;
1434                 }
1435                 break;
1436             }
1437             case ValueItem::Type::FLOAT: {
1438                 if (!writer->Write(bit_cast<uint32_t>(value_item->GetAsScalar()->GetValue<float>()))) {
1439                     return false;
1440                 }
1441                 break;
1442             }
1443             case ValueItem::Type::ID: {
1444                 if (!writer->Write(value_item->GetAsScalar()->GetId().GetOffset())) {
1445                     return false;
1446                 }
1447                 break;
1448             }
1449             default: {
1450                 ASSERT(value_item->GetOffset() != 0);
1451                 if (!writer->Write(value_item->GetOffset())) {
1452                     return false;
1453                 }
1454                 break;
1455             }
1456         }
1457     }
1458 
1459     for (auto tag : tags_) {
1460         if (!writer->Write(tag.GetItem())) {
1461             return false;
1462         }
1463     }
1464 
1465     return true;
1466 }
1467 
EmitEnd()1468 void LineNumberProgramItem::EmitEnd()
1469 {
1470     EmitOpcode(Opcode::END_SEQUENCE);
1471 }
1472 
EmitAdvancePc(std::vector<uint8_t> * constant_pool,uint32_t value)1473 void LineNumberProgramItem::EmitAdvancePc(std::vector<uint8_t> *constant_pool, uint32_t value)
1474 {
1475     EmitOpcode(Opcode::ADVANCE_PC);
1476     EmitUleb128(constant_pool, value);
1477 }
1478 
EmitAdvanceLine(std::vector<uint8_t> * constant_pool,int32_t value)1479 void LineNumberProgramItem::EmitAdvanceLine(std::vector<uint8_t> *constant_pool, int32_t value)
1480 {
1481     EmitOpcode(Opcode::ADVANCE_LINE);
1482     EmitSleb128(constant_pool, value);
1483 }
1484 
EmitColumn(std::vector<uint8_t> * constant_pool,uint32_t pc_inc,uint32_t column)1485 void LineNumberProgramItem::EmitColumn(std::vector<uint8_t> *constant_pool, uint32_t pc_inc, uint32_t column)
1486 {
1487     if (pc_inc != 0U) {
1488         EmitAdvancePc(constant_pool, pc_inc);
1489     }
1490     EmitOpcode(Opcode::SET_COLUMN);
1491     EmitUleb128(constant_pool, column);
1492 }
1493 
EmitStartLocal(std::vector<uint8_t> * constant_pool,int32_t register_number,StringItem * name,StringItem * type)1494 void LineNumberProgramItem::EmitStartLocal(std::vector<uint8_t> *constant_pool, int32_t register_number,
1495                                            StringItem *name, StringItem *type)
1496 {
1497     EmitStartLocalExtended(constant_pool, register_number, name, type, nullptr);
1498 }
1499 
EmitStartLocalExtended(std::vector<uint8_t> * constant_pool,int32_t register_number,StringItem * name,StringItem * type,StringItem * type_signature)1500 void LineNumberProgramItem::EmitStartLocalExtended(std::vector<uint8_t> *constant_pool, int32_t register_number,
1501                                                    StringItem *name, StringItem *type, StringItem *type_signature)
1502 {
1503     ASSERT(name != nullptr);
1504     ASSERT(type != nullptr);
1505     EmitOpcode(type_signature == nullptr ? Opcode::START_LOCAL : Opcode::START_LOCAL_EXTENDED);
1506     EmitRegister(register_number);
1507     ASSERT(name->GetOffset() != 0);
1508     EmitUleb128(constant_pool, name->GetOffset());
1509     ASSERT(type->GetOffset() != 0);
1510     EmitUleb128(constant_pool, type->GetOffset());
1511 
1512     if (type_signature != nullptr) {
1513         ASSERT(type_signature->GetOffset() != 0);
1514         EmitUleb128(constant_pool, type_signature->GetOffset());
1515     }
1516 }
1517 
EmitEndLocal(int32_t register_number)1518 void LineNumberProgramItem::EmitEndLocal(int32_t register_number)
1519 {
1520     EmitOpcode(Opcode::END_LOCAL);
1521     EmitRegister(register_number);
1522 }
1523 
EmitRestartLocal(int32_t register_number)1524 void LineNumberProgramItem::EmitRestartLocal(int32_t register_number)
1525 {
1526     EmitOpcode(Opcode::RESTART_LOCAL);
1527     EmitRegister(register_number);
1528 }
1529 
EmitSpecialOpcode(uint32_t pc_inc,int32_t line_inc)1530 bool LineNumberProgramItem::EmitSpecialOpcode(uint32_t pc_inc, int32_t line_inc)
1531 {
1532     if (line_inc < LINE_BASE || (line_inc - LINE_BASE) >= LINE_RANGE) {
1533         return false;
1534     }
1535 
1536     auto opcode = static_cast<size_t>(line_inc - LINE_BASE) + static_cast<size_t>(pc_inc * LINE_RANGE) + OPCODE_BASE;
1537     if (opcode > std::numeric_limits<uint8_t>::max()) {
1538         return false;
1539     }
1540 
1541     data_.push_back(static_cast<uint8_t>(opcode));
1542     return true;
1543 }
1544 
EmitPrologEnd()1545 void LineNumberProgramItem::EmitPrologEnd()
1546 {
1547     EmitOpcode(Opcode::SET_PROLOGUE_END);
1548 }
1549 
EmitEpilogBegin()1550 void LineNumberProgramItem::EmitEpilogBegin()
1551 {
1552     EmitOpcode(Opcode::SET_EPILOGUE_BEGIN);
1553 }
1554 
EmitSetFile(std::vector<uint8_t> * constant_pool,StringItem * source_file)1555 void LineNumberProgramItem::EmitSetFile(std::vector<uint8_t> *constant_pool, StringItem *source_file)
1556 {
1557     EmitOpcode(Opcode::SET_FILE);
1558 
1559     if (source_file == nullptr) {
1560         return;
1561     }
1562     ASSERT(source_file->GetOffset() != 0);
1563     EmitUleb128(constant_pool, source_file->GetOffset());
1564 }
1565 
EmitSetSourceCode(std::vector<uint8_t> * constant_pool,StringItem * source_code)1566 void LineNumberProgramItem::EmitSetSourceCode(std::vector<uint8_t> *constant_pool, StringItem *source_code)
1567 {
1568     EmitOpcode(Opcode::SET_SOURCE_CODE);
1569 
1570     if (source_code == nullptr) {
1571         return;
1572     }
1573 
1574     ASSERT(source_code->GetOffset() != 0);
1575     EmitUleb128(constant_pool, source_code->GetOffset());
1576 }
1577 
EmitOpcode(Opcode opcode)1578 void LineNumberProgramItem::EmitOpcode(Opcode opcode)
1579 {
1580     data_.push_back(static_cast<uint8_t>(opcode));
1581 }
1582 
EmitRegister(int32_t register_number)1583 void LineNumberProgramItem::EmitRegister(int32_t register_number)
1584 {
1585     EmitSleb128(&data_, register_number);
1586 }
1587 
1588 /* static */
EmitUleb128(std::vector<uint8_t> * data,uint32_t value)1589 void LineNumberProgramItem::EmitUleb128(std::vector<uint8_t> *data, uint32_t value)
1590 {
1591     size_t n = leb128::UnsignedEncodingSize(value);
1592     std::vector<uint8_t> out(n);
1593     leb128::EncodeUnsigned(value, out.data());
1594 
1595     if (data == nullptr) {
1596         return;
1597     }
1598 
1599     data->insert(data->end(), out.cbegin(), out.cend());
1600 }
1601 
1602 /* static */
EmitSleb128(std::vector<uint8_t> * data,int32_t value)1603 void LineNumberProgramItem::EmitSleb128(std::vector<uint8_t> *data, int32_t value)
1604 {
1605     size_t n = leb128::SignedEncodingSize(value);
1606     std::vector<uint8_t> out(n);
1607     leb128::EncodeSigned(value, out.data());
1608     data->insert(data->end(), out.cbegin(), out.cend());
1609 }
1610 
CalculateSize() const1611 size_t LineNumberProgramItem::CalculateSize() const
1612 {
1613     return data_.size();
1614 }
1615 
Write(Writer * writer)1616 bool LineNumberProgramItem::Write(Writer *writer)
1617 {
1618     ASSERT(GetOffset() == writer->GetOffset());
1619 
1620     return writer->WriteBytes(data_);
1621 }
1622 
SetData(std::vector<uint8_t> && data)1623 void LineNumberProgramItem::SetData(std::vector<uint8_t> &&data)
1624 {
1625     data_ = std::move(data);
1626 }
1627 
CalculateSize() const1628 size_t DebugInfoItem::CalculateSize() const
1629 {
1630     size_t n = leb128::UnsignedEncodingSize(line_num_) + leb128::UnsignedEncodingSize(parameters_.size());
1631 
1632     for (auto *p : parameters_) {
1633         ASSERT(p == nullptr || p->GetOffset() != 0);
1634         n += leb128::UnsignedEncodingSize(p == nullptr ? 0 : p->GetOffset());
1635     }
1636 
1637     n += leb128::UnsignedEncodingSize(constant_pool_.size());
1638     n += constant_pool_.size();
1639 
1640     n += leb128::UnsignedEncodingSize(program_->GetIndex(this));
1641 
1642     return n;
1643 }
1644 
Write(Writer * writer)1645 bool DebugInfoItem::Write(Writer *writer)
1646 {
1647     ASSERT(GetOffset() == writer->GetOffset());
1648 
1649     if (!writer->WriteUleb128(line_num_)) {
1650         return false;
1651     }
1652 
1653     if (!writer->WriteUleb128(parameters_.size())) {
1654         return false;
1655     }
1656 
1657     for (auto *p : parameters_) {
1658         ASSERT(p == nullptr || p->GetOffset() != 0);
1659 
1660         if (!writer->WriteUleb128(p == nullptr ? 0 : p->GetOffset())) {
1661             return false;
1662         }
1663     }
1664 
1665     if (!writer->WriteUleb128(constant_pool_.size())) {
1666         return false;
1667     }
1668 
1669     if (!writer->WriteBytes(constant_pool_)) {
1670         return false;
1671     }
1672 
1673     ASSERT(program_ != nullptr);
1674     ASSERT(program_->HasIndex(this));
1675 
1676     return writer->WriteUleb128(program_->GetIndex(this));
1677 }
1678 
Dump(std::ostream & os) const1679 void DebugInfoItem::Dump(std::ostream &os) const
1680 {
1681     os << "line_start = " << line_num_ << std::endl;
1682 
1683     os << "num_parameters = " << parameters_.size() << std::endl;
1684     for (auto *item : parameters_) {
1685         if (item != nullptr) {
1686             os << "  string_item[" << item->GetOffset() << "]" << std::endl;
1687         } else {
1688             os << "  string_item[INVALID_OFFSET]" << std::endl;
1689         }
1690     }
1691 
1692     os << "constant_pool = [";
1693     for (size_t i = 0; i < constant_pool_.size(); i++) {
1694         size_t b = constant_pool_[i];
1695         os << "0x" << std::setfill('0') << std::setw(2U) << std::right << std::hex << b << std::dec;
1696         if (i < constant_pool_.size() - 1) {
1697             os << ", ";
1698         }
1699     }
1700     os << "]" << std::endl;
1701 
1702     os << "line_number_program = line_number_program_idx[";
1703     if (program_ != nullptr && program_->HasIndex(this)) {
1704         os << program_->GetIndex(this);
1705     } else {
1706         os << "NO_INDEX";
1707     }
1708     os << "]";
1709 }
1710 
Write(Writer * writer)1711 bool MethodHandleItem::Write(Writer *writer)
1712 {
1713     ASSERT(GetOffset() == writer->GetOffset());
1714 
1715     if (!writer->WriteByte(static_cast<uint8_t>(type_))) {
1716         return false;
1717     }
1718 
1719     return writer->WriteUleb128(entity_->GetOffset());
1720 }
1721 
1722 }  // namespace panda::panda_file
1723