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