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 <cstdint> 17 18#include "libpandafile/bytecode_instruction-inl.h" 19#include "libpandafile/line_number_program.h" 20#include "libpandafile/literal_data_accessor-inl.h" 21#include "libpandafile/class_data_accessor-inl.h" 22#include "libpandafile/proto_data_accessor-inl.h" 23#include "libpandafile/code_data_accessor-inl.h" 24#include "libpandafile/debug_data_accessor-inl.h" 25#include "libpandafile/field_data_accessor-inl.h" 26#include "libpandafile/method_data_accessor-inl.h" 27 28#include "file.h" 29 30#include "libpandabase/utils/utf.h" 31 32#include "libpandafile/file_reader.h" 33 34namespace panda::panda_file { 35 36bool FileReader::ReadContainer() 37{ 38 if (!ReadClasses()) { 39 return false; 40 } 41 if (!ReadLiteralArrayItems()) { 42 return false; 43 } 44 if (!ReadIndexHeaders()) { 45 return false; 46 } 47 48 ComputeLayoutAndUpdateIndices(); 49 50 return true; 51} 52 53/* static */ 54bool FileReader::CreateLiteralArrayItem(const LiteralDataAccessor::LiteralValue &lit_value, const LiteralTag &tag, 55 File::EntityId array_id) 56{ 57 auto it = items_done_.find(array_id); 58 if (it != items_done_.end()) { 59 return true; 60 } 61 62 LiteralArrayItem *item = container_.GetOrCreateLiteralArrayItem(std::to_string(array_id.GetOffset())); 63 items_done_.insert({array_id, static_cast<BaseItem *>(item)}); 64 65 File::EntityId id(std::get<uint32_t>(lit_value)); 66 auto sp = file_->GetSpanFromId(id); 67 68 std::vector<panda_file::LiteralItem> literal_array; 69 literal_array.emplace_back(static_cast<uint8_t>(tag)); 70 switch (tag) { 71 case panda_file::LiteralTag::BOOL: { 72 auto v = helpers::Read<sizeof(bool)>(&sp); 73 literal_array.emplace_back(static_cast<uint8_t>(v)); 74 break; 75 } 76 case panda_file::LiteralTag::TAGVALUE: 77 case panda_file::LiteralTag::ACCESSOR: 78 case panda_file::LiteralTag::NULLVALUE: { 79 auto v = helpers::Read<sizeof(uint8_t)>(&sp); 80 literal_array.emplace_back(v); 81 break; 82 } 83 case panda_file::LiteralTag::ARRAY_U1: 84 case panda_file::LiteralTag::ARRAY_I8: 85 case panda_file::LiteralTag::ARRAY_U8: { 86 auto len = helpers::Read<sizeof(uint32_t)>(&sp); 87 literal_array.emplace_back(len); 88 for (size_t i = 0; i < len; i++) { 89 auto v = helpers::Read<sizeof(uint8_t)>(&sp); 90 literal_array.emplace_back(v); 91 } 92 break; 93 } 94 case panda_file::LiteralTag::ARRAY_I16: 95 case panda_file::LiteralTag::ARRAY_U16: { 96 auto len = helpers::Read<sizeof(uint32_t)>(&sp); 97 literal_array.emplace_back(len); 98 for (size_t i = 0; i < len; i++) { 99 auto v = helpers::Read<sizeof(uint16_t)>(&sp); 100 literal_array.emplace_back(v); 101 } 102 break; 103 } 104 case panda_file::LiteralTag::INTEGER: { 105 auto v = helpers::Read<sizeof(uint32_t)>(&sp); 106 literal_array.emplace_back(v); 107 break; 108 } 109 case panda_file::LiteralTag::ARRAY_I32: 110 case panda_file::LiteralTag::ARRAY_U32: 111 case panda_file::LiteralTag::ARRAY_F32: { 112 auto len = helpers::Read<sizeof(uint32_t)>(&sp); 113 literal_array.emplace_back(len); 114 for (size_t i = 0; i < len; i++) { 115 auto v = helpers::Read<sizeof(uint32_t)>(&sp); 116 literal_array.emplace_back(v); 117 } 118 break; 119 } 120 case panda_file::LiteralTag::ARRAY_I64: 121 case panda_file::LiteralTag::ARRAY_U64: 122 case panda_file::LiteralTag::ARRAY_F64: { 123 auto len = helpers::Read<sizeof(uint32_t)>(&sp); 124 literal_array.emplace_back(len); 125 for (size_t i = 0; i < len; i++) { 126 auto v = helpers::Read<sizeof(uint64_t)>(&sp); 127 literal_array.emplace_back(v); 128 } 129 break; 130 } 131 case panda_file::LiteralTag::FLOAT: { 132 auto v = helpers::Read<sizeof(uint32_t)>(&sp); 133 literal_array.emplace_back(v); 134 break; 135 } 136 case panda_file::LiteralTag::DOUBLE: { 137 auto v = panda_file::helpers::Read<sizeof(uint64_t)>(&sp); 138 literal_array.emplace_back(v); 139 break; 140 } 141 case panda_file::LiteralTag::STRING: { 142 File::EntityId str_id(helpers::Read<sizeof(uint32_t)>(&sp)); 143 auto data = file_->GetStringData(str_id); 144 std::string item_str(utf::Mutf8AsCString(data.data)); 145 auto *string_item = container_.GetOrCreateStringItem(item_str); 146 literal_array.emplace_back(string_item); 147 break; 148 } 149 case panda_file::LiteralTag::ARRAY_STRING: { 150 auto len = helpers::Read<sizeof(uint32_t)>(&sp); 151 literal_array.emplace_back(len); 152 for (size_t i = 0; i < len; i++) { 153 File::EntityId str_id(helpers::Read<sizeof(uint32_t)>(&sp)); 154 auto data = file_->GetStringData(str_id); 155 std::string item_str(utf::Mutf8AsCString(data.data)); 156 auto *string_item = container_.GetOrCreateStringItem(item_str); 157 literal_array.emplace_back(string_item); 158 } 159 break; 160 } 161 case panda_file::LiteralTag::METHOD: 162 case panda_file::LiteralTag::GETTER: 163 case panda_file::LiteralTag::SETTER: 164 case panda_file::LiteralTag::GENERATORMETHOD: 165 case panda_file::LiteralTag::ASYNCGENERATORMETHOD: { 166 File::EntityId method_id(helpers::Read<sizeof(uint32_t)>(&sp)); 167 MethodDataAccessor method_acc(*file_, method_id); 168 File::EntityId class_id(method_acc.GetClassId()); 169 auto *class_item = CreateClassItem(class_id); 170 literal_array.emplace_back(CreateMethodItem(class_item, method_id)); 171 break; 172 } 173 default: 174 UNREACHABLE(); 175 } 176 177 item->AddItems(literal_array); 178 179 return true; 180} 181 182// NOLINTNEXTLINE(readability-function-size) 183AnnotationItem *FileReader::CreateAnnotationItem(File::EntityId ann_id) 184{ 185 auto it = items_done_.find(ann_id); 186 if (it != items_done_.end()) { 187 return static_cast<AnnotationItem *>(it->second); 188 } 189 190 AnnotationDataAccessor ann_acc(*file_, ann_id); 191 File::EntityId ann_class_id {ann_acc.GetClassId()}; 192 AnnotationItem *ann_item = nullptr; 193 194 if (!file_->IsExternal(ann_class_id)) { 195 auto *ann_class_item = CreateClassItem(ann_class_id); 196 ann_item = container_.CreateItem<AnnotationItem>(ann_class_item, std::vector<AnnotationItem::Elem>(), 197 std::vector<AnnotationItem::Tag>()); 198 } else { 199 auto *ann_class_item = CreateForeignClassItem(ann_class_id); 200 ann_item = container_.CreateItem<AnnotationItem>(ann_class_item, std::vector<AnnotationItem::Elem>(), 201 std::vector<AnnotationItem::Tag>()); 202 } 203 204 ASSERT(ann_item != nullptr); 205 206 items_done_.insert({ann_id, static_cast<BaseItem *>(ann_item)}); 207 208 std::vector<AnnotationItem::Elem> item_elements; 209 std::vector<AnnotationItem::Tag> tag_elements; 210 211 for (size_t i = 0; i < ann_acc.GetCount(); i++) { 212 AnnotationDataAccessor::Tag ann_tag = ann_acc.GetTag(i); 213 AnnotationDataAccessor::Elem ann_elem = ann_acc.GetElement(i); 214 ValueItem *elem_value_item = nullptr; 215 switch (ann_tag.GetItem()) { 216 case '1': 217 case '2': 218 case '3': { 219 auto scalar = ann_elem.GetScalarValue(); 220 elem_value_item = container_.GetOrCreateIntegerValueItem(scalar.Get<uint8_t>()); 221 break; 222 } 223 case '4': 224 case '5': { 225 auto scalar = ann_elem.GetScalarValue(); 226 elem_value_item = container_.GetOrCreateIntegerValueItem(scalar.Get<uint16_t>()); 227 break; 228 } 229 case '6': 230 case '7': { 231 auto scalar = ann_elem.GetScalarValue(); 232 elem_value_item = container_.GetOrCreateIntegerValueItem(scalar.Get<uint32_t>()); 233 break; 234 } 235 case '8': 236 case '9': { 237 auto scalar = ann_elem.GetScalarValue(); 238 elem_value_item = container_.GetOrCreateLongValueItem(scalar.Get<uint64_t>()); 239 break; 240 } 241 case 'A': { 242 auto scalar = ann_elem.GetScalarValue(); 243 elem_value_item = container_.GetOrCreateFloatValueItem(scalar.Get<float>()); 244 break; 245 } 246 case 'B': { 247 auto scalar = ann_elem.GetScalarValue(); 248 elem_value_item = container_.GetOrCreateDoubleValueItem(scalar.Get<double>()); 249 break; 250 } 251 case 'C': { 252 auto scalar = ann_elem.GetScalarValue(); 253 const File::EntityId str_id(scalar.Get<uint32_t>()); 254 auto data = file_->GetStringData(str_id); 255 std::string item_str(utf::Mutf8AsCString(data.data)); 256 auto *str_item = container_.GetOrCreateStringItem(item_str); 257 elem_value_item = container_.GetOrCreateIdValueItem(str_item); 258 break; 259 } 260 case 'D': { 261 auto scalar = ann_elem.GetScalarValue(); 262 const File::EntityId class_id {scalar.Get<uint32_t>()}; 263 elem_value_item = container_.GetOrCreateIdValueItem(CreateGenericClassItem(class_id)); 264 break; 265 } 266 case 'E': { 267 auto scalar = ann_elem.GetScalarValue(); 268 const File::EntityId method_id {scalar.Get<uint32_t>()}; 269 MethodDataAccessor method_acc(*file_, method_id); 270 auto *cls_item = CreateGenericClassItem(method_acc.GetClassId()); 271 elem_value_item = container_.GetOrCreateIdValueItem(CreateGenericMethodItem(cls_item, method_id)); 272 break; 273 } 274 case 'F': { 275 auto scalar = ann_elem.GetScalarValue(); 276 const File::EntityId field_id {scalar.Get<uint32_t>()}; 277 FieldDataAccessor field_acc(*file_, field_id); 278 auto *cls_item = CreateGenericClassItem(field_acc.GetClassId()); 279 elem_value_item = container_.GetOrCreateIdValueItem(CreateGenericFieldItem(cls_item, field_id)); 280 break; 281 } 282 case 'G': { 283 auto scalar = ann_elem.GetScalarValue(); 284 const File::EntityId ann_item_id {scalar.Get<uint32_t>()}; 285 elem_value_item = container_.GetOrCreateIdValueItem(CreateAnnotationItem(ann_item_id)); 286 break; 287 } 288 case 'J': { 289 LOG(FATAL, PANDAFILE) << "MethodHandle is not supported so far"; 290 break; 291 } 292 case '*': { 293 elem_value_item = container_.GetOrCreateIntegerValueItem(0); 294 break; 295 } 296 case 'K': { 297 auto array = ann_elem.GetArrayValue(); 298 std::vector<ScalarValueItem> items; 299 for (size_t j = 0; j < array.GetCount(); j++) { 300 ScalarValueItem scalar(static_cast<uint32_t>(array.Get<uint8_t>(j))); 301 items.emplace_back(std::move(scalar)); 302 } 303 elem_value_item = static_cast<ValueItem *>( 304 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::U1), std::move(items))); 305 break; 306 } 307 case 'L': { 308 auto array = ann_elem.GetArrayValue(); 309 std::vector<ScalarValueItem> items; 310 for (size_t j = 0; j < array.GetCount(); j++) { 311 ScalarValueItem scalar(static_cast<uint32_t>(array.Get<uint8_t>(j))); 312 items.emplace_back(std::move(scalar)); 313 } 314 elem_value_item = static_cast<ValueItem *>( 315 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::I8), std::move(items))); 316 break; 317 } 318 case 'M': { 319 auto array = ann_elem.GetArrayValue(); 320 std::vector<ScalarValueItem> items; 321 for (size_t j = 0; j < array.GetCount(); j++) { 322 ScalarValueItem scalar(static_cast<uint32_t>(array.Get<uint8_t>(j))); 323 items.emplace_back(std::move(scalar)); 324 } 325 elem_value_item = static_cast<ValueItem *>( 326 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::U8), std::move(items))); 327 break; 328 } 329 case 'N': { 330 auto array = ann_elem.GetArrayValue(); 331 std::vector<ScalarValueItem> items; 332 for (size_t j = 0; j < array.GetCount(); j++) { 333 ScalarValueItem scalar(static_cast<uint32_t>(array.Get<uint16_t>(j))); 334 items.emplace_back(std::move(scalar)); 335 } 336 elem_value_item = static_cast<ValueItem *>( 337 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::I16), std::move(items))); 338 break; 339 } 340 case 'O': { 341 auto array = ann_elem.GetArrayValue(); 342 std::vector<ScalarValueItem> items; 343 for (size_t j = 0; j < array.GetCount(); j++) { 344 ScalarValueItem scalar(static_cast<uint32_t>(array.Get<uint16_t>(j))); 345 items.emplace_back(std::move(scalar)); 346 } 347 elem_value_item = static_cast<ValueItem *>( 348 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::U16), std::move(items))); 349 break; 350 } 351 case 'P': { 352 auto array = ann_elem.GetArrayValue(); 353 std::vector<ScalarValueItem> items; 354 for (size_t j = 0; j < array.GetCount(); j++) { 355 ScalarValueItem scalar(array.Get<uint32_t>(j)); 356 items.emplace_back(std::move(scalar)); 357 } 358 elem_value_item = static_cast<ValueItem *>( 359 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::I32), std::move(items))); 360 break; 361 } 362 case 'Q': { 363 auto array = ann_elem.GetArrayValue(); 364 std::vector<ScalarValueItem> items; 365 for (size_t j = 0; j < array.GetCount(); j++) { 366 ScalarValueItem scalar(array.Get<uint32_t>(j)); 367 items.emplace_back(std::move(scalar)); 368 } 369 elem_value_item = static_cast<ValueItem *>( 370 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::U32), std::move(items))); 371 break; 372 } 373 case 'R': { 374 auto array = ann_elem.GetArrayValue(); 375 std::vector<ScalarValueItem> items; 376 for (size_t j = 0; j < array.GetCount(); j++) { 377 ScalarValueItem scalar(array.Get<uint64_t>(j)); 378 items.emplace_back(std::move(scalar)); 379 } 380 elem_value_item = static_cast<ValueItem *>( 381 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::I64), std::move(items))); 382 break; 383 } 384 case 'S': { 385 auto array = ann_elem.GetArrayValue(); 386 std::vector<ScalarValueItem> items; 387 for (size_t j = 0; j < array.GetCount(); j++) { 388 ScalarValueItem scalar(array.Get<uint64_t>(j)); 389 items.emplace_back(std::move(scalar)); 390 } 391 elem_value_item = static_cast<ValueItem *>( 392 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::U64), std::move(items))); 393 break; 394 } 395 case 'T': { 396 auto array = ann_elem.GetArrayValue(); 397 std::vector<ScalarValueItem> items; 398 for (size_t j = 0; j < array.GetCount(); j++) { 399 ScalarValueItem scalar(array.Get<float>(j)); 400 items.emplace_back(std::move(scalar)); 401 } 402 elem_value_item = static_cast<ValueItem *>( 403 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::F32), std::move(items))); 404 break; 405 } 406 case 'U': { 407 auto array = ann_elem.GetArrayValue(); 408 std::vector<ScalarValueItem> items; 409 for (size_t j = 0; j < array.GetCount(); j++) { 410 ScalarValueItem scalar(array.Get<double>(j)); 411 items.emplace_back(std::move(scalar)); 412 } 413 elem_value_item = static_cast<ValueItem *>( 414 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::F64), std::move(items))); 415 break; 416 } 417 case 'V': { 418 auto array = ann_elem.GetArrayValue(); 419 std::vector<ScalarValueItem> items; 420 for (size_t j = 0; j < array.GetCount(); j++) { 421 const File::EntityId str_id(array.Get<uint32_t>(j)); 422 auto data = file_->GetStringData(str_id); 423 std::string item_str(utf::Mutf8AsCString(data.data)); 424 items.emplace_back(ScalarValueItem(container_.GetOrCreateStringItem(item_str))); 425 } 426 elem_value_item = static_cast<ValueItem *>( 427 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::REFERENCE), std::move(items))); 428 break; 429 } 430 case 'W': { 431 auto array = ann_elem.GetArrayValue(); 432 std::vector<ScalarValueItem> items; 433 for (size_t j = 0; j < array.GetCount(); j++) { 434 const File::EntityId class_id {array.Get<uint32_t>(j)}; 435 BaseClassItem *cls_item = nullptr; 436 if (file_->IsExternal(class_id)) { 437 cls_item = CreateForeignClassItem(class_id); 438 } else { 439 cls_item = CreateClassItem(class_id); 440 } 441 ASSERT(cls_item != nullptr); 442 items.emplace_back(ScalarValueItem(cls_item)); 443 } 444 elem_value_item = static_cast<ValueItem *>( 445 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::REFERENCE), std::move(items))); 446 break; 447 } 448 case 'X': { 449 auto array = ann_elem.GetArrayValue(); 450 std::vector<ScalarValueItem> items; 451 for (size_t j = 0; j < array.GetCount(); j++) { 452 const File::EntityId method_id {array.Get<uint32_t>(j)}; 453 MethodDataAccessor method_acc(*file_, method_id); 454 auto *cls_item = CreateGenericClassItem(method_acc.GetClassId()); 455 items.emplace_back(ScalarValueItem(CreateGenericMethodItem(cls_item, method_id))); 456 } 457 elem_value_item = static_cast<ValueItem *>( 458 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::REFERENCE), std::move(items))); 459 break; 460 } 461 case 'Y': { 462 auto array = ann_elem.GetArrayValue(); 463 std::vector<ScalarValueItem> items; 464 for (size_t j = 0; j < array.GetCount(); j++) { 465 const File::EntityId field_id {array.Get<uint32_t>(j)}; 466 FieldDataAccessor field_acc(*file_, field_id); 467 auto *cls_item = CreateGenericClassItem(field_acc.GetClassId()); 468 items.emplace_back(ScalarValueItem(CreateGenericFieldItem(cls_item, field_id))); 469 } 470 elem_value_item = static_cast<ValueItem *>( 471 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::REFERENCE), std::move(items))); 472 break; 473 } 474 case 'H': { 475 // ARRAY can appear for empty arrays only 476 ASSERT(ann_elem.GetArrayValue().GetCount() == 0); 477 elem_value_item = static_cast<ValueItem *>( 478 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::VOID), std::vector<ScalarValueItem>())); 479 break; 480 } 481 case 'Z': { 482 auto array = ann_elem.GetArrayValue(); 483 std::vector<ScalarValueItem> items; 484 for (size_t j = 0; j < array.GetCount(); j++) { 485 const File::EntityId ann_item_id {array.Get<uint32_t>(j)}; 486 items.emplace_back(CreateAnnotationItem(ann_item_id)); 487 } 488 elem_value_item = static_cast<ValueItem *>( 489 container_.CreateItem<ArrayValueItem>(Type(Type::TypeId::REFERENCE), std::move(items))); 490 break; 491 } 492 case '@': { 493 // TODO(nsizov): support it 494 LOG(FATAL, PANDAFILE) << "MethodHandle is not supported so far"; 495 break; 496 } 497 // array 498 case 'I': 499 // VOID(I) and ARRAY(H) value should not appear 500 default: 501 UNREACHABLE(); 502 } 503 504 ASSERT(elem_value_item != nullptr); 505 506 tag_elements.emplace_back(AnnotationItem::Tag(static_cast<char>(ann_tag.GetItem()))); 507 File::EntityId name_id(ann_elem.GetNameId()); 508 std::string annot_name_str(utf::Mutf8AsCString(file_->GetStringData(name_id).data)); 509 auto elem_name_item = container_.GetOrCreateStringItem(annot_name_str); 510 item_elements.emplace_back(AnnotationItem::Elem(elem_name_item, elem_value_item)); 511 } 512 513 ann_item->SetElements(std::move(item_elements)); 514 ann_item->SetTags(std::move(tag_elements)); 515 516 return ann_item; 517} 518 519TypeItem *FileReader::CreateParamTypeItem(ProtoDataAccessor *proto_acc, size_t param_num, size_t reference_num) 520{ 521 Type param_type = proto_acc->GetArgType(param_num); 522 TypeItem *param_type_item = nullptr; 523 if (param_type.IsPrimitive()) { 524 param_type_item = container_.GetOrCreatePrimitiveTypeItem(param_type); 525 } else { 526 const File::EntityId type_cls_id = proto_acc->GetReferenceType(reference_num); 527 if (file_->IsExternal(type_cls_id)) { 528 param_type_item = CreateForeignClassItem(type_cls_id); 529 } else { 530 param_type_item = CreateClassItem(type_cls_id); 531 } 532 } 533 534 ASSERT(param_type_item != nullptr); 535 536 return param_type_item; 537} 538 539std::vector<MethodParamItem> FileReader::CreateMethodParamItems(ProtoDataAccessor *proto_acc, 540 MethodDataAccessor *method_acc, size_t reference_num) 541{ 542 std::vector<MethodParamItem> param_items; 543 544 for (size_t i = 0; i < proto_acc->GetNumArgs(); i++) { 545 TypeItem *param_type_item = CreateParamTypeItem(proto_acc, i, reference_num); 546 if (param_type_item->GetType().IsReference()) { 547 reference_num++; 548 } 549 param_items.emplace_back(MethodParamItem(param_type_item)); 550 } 551 552 auto param_ann_id = method_acc->GetParamAnnotationId(); 553 if (param_ann_id) { 554 ParamAnnotationsDataAccessor param_acc(*file_, param_ann_id.value()); 555 for (size_t i = 0; i < proto_acc->GetNumArgs(); i++) { 556 ParamAnnotationsDataAccessor::AnnotationArray ann_arr = param_acc.GetAnnotationArray(i); 557 ann_arr.EnumerateAnnotations([&](File::EntityId ann_id) { 558 auto ann_item = CreateAnnotationItem(ann_id); 559 param_items[i].AddAnnotation(ann_item); 560 }); 561 } 562 } 563 564 auto runtime_param_ann_id = method_acc->GetRuntimeParamAnnotationId(); 565 if (runtime_param_ann_id) { 566 ParamAnnotationsDataAccessor param_acc(*file_, runtime_param_ann_id.value()); 567 for (size_t i = 0; i < proto_acc->GetNumArgs(); i++) { 568 ParamAnnotationsDataAccessor::AnnotationArray ann_arr = param_acc.GetAnnotationArray(i); 569 ann_arr.EnumerateAnnotations([&](File::EntityId ann_id) { 570 auto ann_item = CreateAnnotationItem(ann_id); 571 param_items[i].AddRuntimeAnnotation(ann_item); 572 }); 573 } 574 } 575 576 return param_items; 577} 578 579DebugInfoItem *FileReader::CreateDebugInfoItem(File::EntityId debug_info_id) 580{ 581 auto it = items_done_.find(debug_info_id); 582 if (it != items_done_.end()) { 583 return static_cast<DebugInfoItem *>(it->second); 584 } 585 586 auto *lnp_item = container_.CreateLineNumberProgramItem(); 587 auto *debug_info_item = container_.CreateItem<DebugInfoItem>(lnp_item); 588 items_done_.insert({debug_info_id, static_cast<BaseItem *>(debug_info_item)}); 589 590 DebugInfoDataAccessor debug_acc(*file_, debug_info_id); 591 592 debug_info_item->SetLineNumber(debug_acc.GetLineStart()); 593 debug_acc.EnumerateParameters([&](File::EntityId param_id) { 594 auto data = file_->GetStringData(param_id); 595 std::string item_str(utf::Mutf8AsCString(data.data)); 596 auto *string_item = container_.GetOrCreateStringItem(item_str); 597 debug_info_item->AddParameter(string_item); 598 }); 599 600 return debug_info_item; 601} 602 603TypeItem *FileReader::GetReturnTypeItem(Type ret_type, size_t &reference_num) 604{ 605 TypeItem *ret_type_item = nullptr; 606 if (ret_type.IsPrimitive()) { 607 ret_type_item = container_.GetOrCreatePrimitiveTypeItem(ret_type); 608 } else { 609 const File::EntityId type_cls_id = proto_acc.GetReferenceType(reference_num); 610 if (file_->IsExternal(type_cls_id)) { 611 ret_type_item = CreateForeignClassItem(type_cls_id); 612 } else { 613 ret_type_item = CreateClassItem(type_cls_id); 614 } 615 reference_num++; 616 } 617 return ret_type_item; 618} 619 620void FileReader::EnumerateBlocks(MethodDataAccessor method_acc, MethodItem *method_item) 621{ 622 // quick check 623 auto code_id = method_acc.GetCodeId(); 624 if (code_id == std::nullopt) { 625 return; 626 } 627 628 CodeDataAccessor code_acc(*file_, code_id.value()); 629 std::vector<uint8_t> instructions(code_acc.GetCodeSize()); 630 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 631 instructions.assign(code_acc.GetInstructions(), code_acc.GetInstructions() + code_acc.GetCodeSize()); 632 auto *code_item = 633 container_.CreateItem<CodeItem>(code_acc.GetNumVregs(), code_acc.GetNumArgs(), std::move(instructions)); 634 635 code_acc.EnumerateTryBlocks([&](CodeDataAccessor::TryBlock &try_block) { 636 std::vector<CodeItem::CatchBlock> catch_blocks; 637 try_block.EnumerateCatchBlocks([&](CodeDataAccessor::CatchBlock &catch_block) { 638 BaseClassItem *catch_type_item = nullptr; 639 auto type_idx = catch_block.GetTypeIdx(); 640 if (type_idx != panda_file::INVALID_INDEX) { 641 File::EntityId catch_cls_id = file_->ResolveClassIndex(method_id, catch_block.GetTypeIdx()); 642 catch_type_item = (file_->IsExternal(catch_cls_id)) ? CreateForeignClassItem(catch_cls_id) : 643 CreateClassItem(catch_cls_id); 644 method_item->AddIndexDependency(catch_type_item); 645 } 646 // Add new CatchBlock 647 catch_blocks.emplace_back(CodeItem::CatchBlock(method_item, catch_type_item, catch_block.GetHandlerPc(), 648 catch_block.GetCodeSize())); 649 return true; 650 }); 651 code_item->AddTryBlock( 652 CodeItem::TryBlock(try_block.GetStartPc(), try_block.GetLength(), std::move(catch_blocks))); 653 return true; 654 }); 655 656 method_item->SetCode(code_item); 657} 658 659MethodItem *FileReader::CreateMethodItem(ClassItem *cls, File::EntityId method_id) 660{ 661 // Check if we have done this method 662 auto it = items_done_.find(method_id); 663 if (it != items_done_.end()) { 664 return static_cast<MethodItem *>(it->second); 665 } 666 667 MethodDataAccessor method_acc(*file_, method_id); 668 auto data = file_->GetStringData(method_acc.GetNameId()); 669 std::string method_name(utf::Mutf8AsCString(data.data)); 670 auto method_str_item = container_.GetOrCreateStringItem(method_name); 671 672 ProtoDataAccessor proto_acc(*file_, method_acc.GetProtoId()); 673 Type ret_type = proto_acc.GetReturnType(); 674 size_t reference_num = 0; 675 TypeItem *ret_type_item = GetReturnTypeItem(ret_type, reference_num); 676 ASSERT(ret_type_item != nullptr); 677 auto param_items = CreateMethodParamItems(&proto_acc, &method_acc, reference_num); 678 679 // Double check if we have done this method while computing params 680 auto it_check = items_done_.find(method_id); 681 if (it_check != items_done_.end()) { 682 return static_cast<MethodItem *>(it_check->second); 683 } 684 685 auto proto_item = container_.GetOrCreateProtoItem(ret_type_item, param_items); 686 auto method_item = 687 cls->AddMethod(method_str_item, proto_item, method_acc.GetAccessFlags(), std::move(param_items)); 688 if (method_item->HasRuntimeParamAnnotations()) { 689 container_.CreateItem<ParamAnnotationsItem>(method_item, true); 690 } 691 692 if (method_item->HasParamAnnotations()) { 693 container_.CreateItem<ParamAnnotationsItem>(method_item, false); 694 } 695 items_done_.insert({method_id, static_cast<BaseItem *>(method_item)}); 696 697 method_acc.EnumerateAnnotations( 698 [&](File::EntityId ann_id) { method_item->AddAnnotation(CreateAnnotationItem(ann_id)); }); 699 700 method_acc.EnumerateRuntimeAnnotations( 701 [&](File::EntityId ann_id) { method_item->AddRuntimeAnnotation(CreateAnnotationItem(ann_id)); }); 702 703 method_acc.EnumerateTypeAnnotations( 704 [&](File::EntityId ann_id) { method_item->AddTypeAnnotation(CreateAnnotationItem(ann_id)); }); 705 706 method_acc.EnumerateRuntimeTypeAnnotations( 707 [&](File::EntityId ann_id) { method_item->AddRuntimeTypeAnnotation(CreateAnnotationItem(ann_id)); }); 708 709 EnumerateBlocks(method_acc, method_item); 710 711 auto debug_info_id = method_acc.GetDebugInfoId(); 712 if (debug_info_id) { 713 method_item->SetDebugInfo(CreateDebugInfoItem(debug_info_id.value())); 714 } 715 716 auto source_lang = method_acc.GetSourceLang(); 717 if (source_lang) { 718 method_item->SetSourceLang(source_lang.value()); 719 } 720 721 return method_item; 722} 723 724MethodHandleItem *FileReader::CreateMethodHandleItem(File::EntityId mh_id) 725{ 726 (void)mh_id; 727 ASSERT(false); 728 return nullptr; // STUB 729} 730 731FieldItem *FileReader::CreateFieldItem(ClassItem *cls, File::EntityId field_id) 732{ 733 auto it = items_done_.find(field_id); 734 if (it != items_done_.end()) { 735 return static_cast<FieldItem *>(it->second); 736 } 737 738 FieldDataAccessor field_acc(*file_, field_id); 739 740 auto data = file_->GetStringData(field_acc.GetNameId()); 741 std::string string_name(utf::Mutf8AsCString(data.data)); 742 auto *field_name = container_.GetOrCreateStringItem(string_name); 743 Type field_type = Type::GetTypeFromFieldEncoding(field_acc.GetType()); 744 745 TypeItem *field_type_item = nullptr; 746 if (field_type.IsReference()) { 747 File::EntityId type_id(field_acc.GetType()); 748 if (file_->IsExternal(type_id)) { 749 field_type_item = CreateForeignClassItem(type_id); 750 } else { 751 field_type_item = CreateClassItem(type_id); 752 // Double check if we done this field while generated class item 753 auto it_check = items_done_.find(field_id); 754 if (it_check != items_done_.end()) { 755 return static_cast<FieldItem *>(it_check->second); 756 } 757 } 758 } else { 759 field_type_item = container_.GetOrCreatePrimitiveTypeItem(field_type.GetId()); 760 } 761 762 ASSERT(field_type_item != nullptr); 763 764 FieldItem *field_item = cls->AddField(field_name, field_type_item, field_acc.GetAccessFlags()); 765 items_done_.insert({field_id, static_cast<BaseItem *>(field_item)}); 766 767 switch (field_type.GetId()) { 768 case Type::TypeId::U1: 769 case Type::TypeId::I8: 770 case Type::TypeId::U8: 771 SetIntegerFieldValue<uint8_t>(&field_acc, field_item); 772 break; 773 case Type::TypeId::I16: 774 case Type::TypeId::U16: 775 SetIntegerFieldValue<uint16_t>(&field_acc, field_item); 776 break; 777 case Type::TypeId::I32: 778 case Type::TypeId::U32: 779 SetIntegerFieldValue<uint32_t>(&field_acc, field_item); 780 break; 781 case Type::TypeId::I64: 782 case Type::TypeId::U64: 783 SetIntegerFieldValue<uint64_t>(&field_acc, field_item); 784 break; 785 case Type::TypeId::F32: 786 SetFloatFieldValue<float>(&field_acc, field_item); 787 break; 788 case Type::TypeId::F64: 789 SetFloatFieldValue<double>(&field_acc, field_item); 790 break; 791 case Type::TypeId::REFERENCE: 792 SetStringFieldValue(&field_acc, field_item); 793 break; 794 case Type::TypeId::TAGGED: 795 default: 796 UNREACHABLE(); 797 break; 798 } 799 800 field_acc.EnumerateAnnotations( 801 [&](File::EntityId ann_id) { field_item->AddAnnotation(CreateAnnotationItem(ann_id)); }); 802 803 field_acc.EnumerateRuntimeAnnotations( 804 [&](File::EntityId ann_id) { field_item->AddRuntimeAnnotation(CreateAnnotationItem(ann_id)); }); 805 806 field_acc.EnumerateRuntimeTypeAnnotations( 807 [&](File::EntityId ann_id) { field_item->AddRuntimeTypeAnnotation(CreateAnnotationItem(ann_id)); }); 808 809 field_acc.EnumerateTypeAnnotations( 810 [&](File::EntityId ann_id) { field_item->AddTypeAnnotation(CreateAnnotationItem(ann_id)); }); 811 812 return field_item; 813} 814 815ForeignMethodItem *FileReader::CreateForeignMethodItem(BaseClassItem *fcls, File::EntityId method_id) 816{ 817 auto it = items_done_.find(method_id); 818 if (it != items_done_.end()) { 819 return static_cast<ForeignMethodItem *>(it->second); 820 } 821 822 MethodDataAccessor method_acc(*file_, method_id); 823 auto data = file_->GetStringData(method_acc.GetNameId()); 824 std::string method_name(utf::Mutf8AsCString(data.data)); 825 auto *method_str_item = container_.GetOrCreateStringItem(method_name); 826 827 ProtoDataAccessor proto_acc(*file_, method_acc.GetProtoId()); 828 Type ret_type = proto_acc.GetReturnType(); 829 size_t reference_num = 0; 830 TypeItem *ret_type_item = nullptr; 831 if (ret_type.IsPrimitive()) { 832 ret_type_item = container_.GetOrCreatePrimitiveTypeItem(ret_type); 833 } else { 834 const File::EntityId type_cls_id = proto_acc.GetReferenceType(reference_num); 835 if (file_->IsExternal(type_cls_id)) { 836 ret_type_item = CreateForeignClassItem(type_cls_id); 837 } else { 838 ret_type_item = CreateClassItem(type_cls_id); 839 } 840 reference_num++; 841 } 842 ASSERT(ret_type_item != nullptr); 843 auto param_items = CreateMethodParamItems(&proto_acc, &method_acc, reference_num); 844 // Double check if we done this method while computing params 845 auto it_check = items_done_.find(method_id); 846 if (it_check != items_done_.end()) { 847 return static_cast<ForeignMethodItem *>(it_check->second); 848 } 849 auto *proto_item = container_.GetOrCreateProtoItem(ret_type_item, param_items); 850 851 auto *method_item = 852 container_.CreateItem<ForeignMethodItem>(fcls, method_str_item, proto_item, method_acc.GetAccessFlags()); 853 854 items_done_.insert({method_id, static_cast<BaseItem *>(method_item)}); 855 856 return method_item; 857} 858 859ForeignFieldItem *FileReader::CreateForeignFieldItem(BaseClassItem *fcls, File::EntityId field_id) 860{ 861 auto it = items_done_.find(field_id); 862 if (it != items_done_.end()) { 863 return static_cast<ForeignFieldItem *>(it->second); 864 } 865 866 FieldDataAccessor field_acc(*file_, field_id); 867 868 auto data = file_->GetStringData(field_acc.GetNameId()); 869 std::string string_name(utf::Mutf8AsCString(data.data)); 870 auto *field_name = container_.GetOrCreateStringItem(string_name); 871 Type field_type = Type::GetTypeFromFieldEncoding(field_acc.GetType()); 872 TypeItem *field_type_item = nullptr; 873 if (field_type.IsReference()) { 874 File::EntityId type_id(field_acc.GetType()); 875 if (file_->IsExternal(type_id)) { 876 field_type_item = CreateForeignClassItem(type_id); 877 } else { 878 field_type_item = CreateClassItem(type_id); 879 // Double check if we done this field while generated class item 880 auto it_check = items_done_.find(field_id); 881 if (it_check != items_done_.end()) { 882 return static_cast<ForeignFieldItem *>(it_check->second); 883 } 884 } 885 } else { 886 field_type_item = container_.GetOrCreatePrimitiveTypeItem(field_type.GetId()); 887 } 888 889 ASSERT(field_type_item != nullptr); 890 891 auto *field_item = container_.CreateItem<ForeignFieldItem>(fcls, field_name, field_type_item); 892 items_done_.insert({field_id, static_cast<BaseItem *>(field_item)}); 893 894 return field_item; 895} 896 897ForeignClassItem *FileReader::CreateForeignClassItem(File::EntityId class_id) 898{ 899 auto it = items_done_.find(class_id); 900 if (it != items_done_.end()) { 901 return static_cast<ForeignClassItem *>(it->second); 902 } 903 904 std::string class_name(utf::Mutf8AsCString(file_->GetStringData(class_id).data)); 905 auto *class_item = container_.GetOrCreateForeignClassItem(class_name); 906 907 items_done_.insert({class_id, static_cast<BaseItem *>(class_item)}); 908 909 return class_item; 910} 911 912void FileReader::CreateSuperClassItem(ClassDataAccessor& class_acc, 913 ClassItem* class_item, 914 const std::string& class_name) 915{ 916 auto super_class_id = class_acc.GetSuperClassId(); 917 if (super_class_id.GetOffset() != 0) { 918 if (super_class_id.GetOffset() == class_id.GetOffset()) { 919 LOG(FATAL, PANDAFILE) << "Class " << class_name << " has cyclic inheritance"; 920 } 921 922 if (file_->IsExternal(super_class_id)) { 923 auto *super_class_item = CreateForeignClassItem(super_class_id); 924 class_item->SetSuperClass(super_class_item); 925 } else { 926 auto *super_class_item = CreateClassItem(super_class_id); 927 class_item->SetSuperClass(super_class_item); 928 } 929 } 930} 931 932ClassItem *FileReader::CreateClassItem(File::EntityId class_id) 933{ 934 auto it = items_done_.find(class_id); 935 if (it != items_done_.end()) { 936 return static_cast<ClassItem *>(it->second); 937 } 938 ClassDataAccessor class_acc(*file_, class_id); 939 940 std::string class_name(utf::Mutf8AsCString(file_->GetStringData(class_id).data)); 941 auto *class_item = container_.GetOrCreateClassItem(class_name); 942 943 items_done_.insert({class_id, static_cast<BaseItem *>(class_item)}); 944 945 class_item->SetAccessFlags(class_acc.GetAccessFlags()); 946 947 auto source_lang_opt = class_acc.GetSourceLang(); 948 if (source_lang_opt) { 949 class_item->SetSourceLang(source_lang_opt.value()); 950 } 951 952 CreateSuperClassItem(class_acc, class_item, class_name); 953 954 class_acc.EnumerateInterfaces([&](File::EntityId iface_id) { 955 if (file_->IsExternal(iface_id)) { 956 class_item->AddInterface(CreateForeignClassItem(iface_id)); 957 } else { 958 class_item->AddInterface(CreateClassItem(iface_id)); 959 } 960 }); 961 962 class_acc.EnumerateAnnotations( 963 [&](File::EntityId ann_id) { class_item->AddAnnotation(CreateAnnotationItem(ann_id)); }); 964 965 class_acc.EnumerateRuntimeAnnotations( 966 [&](File::EntityId ann_id) { class_item->AddRuntimeAnnotation(CreateAnnotationItem(ann_id)); }); 967 968 class_acc.EnumerateTypeAnnotations( 969 [&](File::EntityId ann_id) { class_item->AddTypeAnnotation(CreateAnnotationItem(ann_id)); }); 970 971 class_acc.EnumerateFields( 972 [&](FieldDataAccessor &field_acc) { CreateFieldItem(class_item, field_acc.GetFieldId()); }); 973 974 class_acc.EnumerateMethods( 975 [&](MethodDataAccessor &method_acc) { CreateMethodItem(class_item, method_acc.GetMethodId()); }); 976 977 auto source_file_id = class_acc.GetSourceFileId(); 978 if (source_file_id) { 979 std::string source_file = utf::Mutf8AsCString(file_->GetStringData(source_file_id.value()).data); 980 class_item->SetSourceFile(container_.GetOrCreateStringItem(source_file)); 981 } 982 983 ASSERT(class_item != nullptr); 984 985 return class_item; 986} 987 988bool FileReader::ReadLiteralArrayItems() 989{ 990 const auto lit_arrays_id = file_->GetLiteralArraysId(); 991 LiteralDataAccessor lit_array_accessor(*file_, lit_arrays_id); 992 size_t num_litarrays = lit_array_accessor.GetLiteralNum(); 993 994 for (size_t i = 0; i < num_litarrays; i++) { 995 auto id = lit_array_accessor.GetLiteralArrayId(i); 996 lit_array_accessor.EnumerateLiteralVals( 997 id, [id, this](const panda_file::LiteralDataAccessor::LiteralValue &value, 998 const panda_file::LiteralTag &tag) { CreateLiteralArrayItem(value, tag, id); }); 999 } 1000 1001 return true; 1002} 1003 1004bool FileReader::ReadIndexHeaders() 1005{ 1006 auto index_headers = file_->GetIndexHeaders(); 1007 for (const auto &header : index_headers) { 1008 auto method_index = file_->GetMethodIndex(&header); 1009 for (auto method_id : method_index) { 1010 MethodDataAccessor method_acc(*file_, method_id); 1011 File::EntityId class_id(method_acc.GetClassId()); 1012 if (file_->IsExternal(class_id)) { 1013 auto *fclass_item = CreateForeignClassItem(class_id); 1014 ASSERT(file_->IsExternal(method_id)); 1015 if (CreateForeignMethodItem(fclass_item, method_id) == nullptr) { 1016 return false; 1017 } 1018 } else { 1019 auto *class_item = CreateClassItem(class_id); 1020 if (file_->IsExternal(method_id)) { 1021 if (CreateForeignMethodItem(class_item, method_id) == nullptr) { 1022 return false; 1023 } 1024 } else if (CreateMethodItem(class_item, method_id) == nullptr) { 1025 return false; 1026 } 1027 } 1028 } 1029 auto field_index = file_->GetFieldIndex(&header); 1030 for (auto field_id : field_index) { 1031 FieldDataAccessor field_acc(*file_, field_id); 1032 File::EntityId class_id(field_acc.GetClassId()); 1033 if (file_->IsExternal(class_id)) { 1034 ASSERT(file_->IsExternal(field_id)); 1035 auto *fclass_item = CreateForeignClassItem(field_acc.GetClassId()); 1036 if (CreateForeignFieldItem(fclass_item, field_id) == nullptr) { 1037 return false; 1038 } 1039 } else { 1040 auto *class_item = CreateClassItem(field_acc.GetClassId()); 1041 if (file_->IsExternal(field_id)) { 1042 if (CreateForeignFieldItem(class_item, field_id) == nullptr) { 1043 return false; 1044 } 1045 } else if (CreateFieldItem(class_item, field_id) == nullptr) { 1046 return false; 1047 } 1048 } 1049 } 1050 } 1051 return true; 1052} 1053 1054bool FileReader::ReadClasses() 1055{ 1056 const auto class_idx = file_->GetClasses(); 1057 1058 for (unsigned int id : class_idx) { 1059 File::EntityId eid(id); 1060 if (file_->IsExternal(eid)) { 1061 CreateForeignClassItem(eid); 1062 } else { 1063 CreateClassItem(eid); 1064 } 1065 } 1066 1067 return true; 1068} 1069 1070void FileReader::UpdateDebugInfoDependecies(File::EntityId debug_info_id) 1071{ 1072 DebugInfoDataAccessor debug_acc(*file_, debug_info_id); 1073 const uint8_t *program = debug_acc.GetLineNumberProgram(); 1074 auto size = file_->GetSpanFromId(file_->GetIdFromPointer(program)).size(); 1075 auto opcode_sp = Span(program, size); 1076 1077 size_t i = 0; 1078 LineNumberProgramItem::Opcode opcode; 1079 panda_file::LineProgramState state(*file_, File::EntityId(0), debug_acc.GetLineStart(), 1080 debug_acc.GetConstantPool()); 1081 while ((opcode = LineNumberProgramItem::Opcode(opcode_sp[i++])) != LineNumberProgramItem::Opcode::END_SEQUENCE) { 1082 switch (opcode) { 1083 case LineNumberProgramItem::Opcode::ADVANCE_PC: 1084 case LineNumberProgramItem::Opcode::ADVANCE_LINE: 1085 case LineNumberProgramItem::Opcode::SET_PROLOGUE_END: 1086 case LineNumberProgramItem::Opcode::SET_EPILOGUE_BEGIN: { 1087 break; 1088 } 1089 case LineNumberProgramItem::Opcode::START_LOCAL: { 1090 [[maybe_unused]] int32_t reg_number; 1091 size_t n; 1092 bool is_full; 1093 std::tie(reg_number, n, is_full) = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1094 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1095 i += n; 1096 1097 auto name_id = File::EntityId(state.ReadULeb128()); 1098 std::string name = utf::Mutf8AsCString(file_->GetStringData(name_id).data); 1099 container_.GetOrCreateStringItem(name); 1100 1101 auto type_id = File::EntityId(state.ReadULeb128()); 1102 std::string type_name = utf::Mutf8AsCString(file_->GetStringData(type_id).data); 1103 if (file_->IsExternal(type_id)) { 1104 container_.GetOrCreateForeignClassItem(type_name); 1105 } else { 1106 container_.GetOrCreateClassItem(type_name); 1107 } 1108 break; 1109 } 1110 case LineNumberProgramItem::Opcode::START_LOCAL_EXTENDED: { 1111 [[maybe_unused]] int32_t reg_number; 1112 size_t n; 1113 bool is_full; 1114 std::tie(reg_number, n, is_full) = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1115 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1116 i += n; 1117 1118 auto name_id = File::EntityId(state.ReadULeb128()); 1119 std::string name = utf::Mutf8AsCString(file_->GetStringData(name_id).data); 1120 container_.GetOrCreateStringItem(name); 1121 1122 auto type_id = File::EntityId(state.ReadULeb128()); 1123 std::string type_name = utf::Mutf8AsCString(file_->GetStringData(type_id).data); 1124 if (file_->IsExternal(type_id)) { 1125 container_.GetOrCreateForeignClassItem(type_name); 1126 } else { 1127 container_.GetOrCreateClassItem(type_name); 1128 } 1129 1130 auto type_signature_id = File::EntityId(state.ReadULeb128()); 1131 std::string type_signature = utf::Mutf8AsCString(file_->GetStringData(type_signature_id).data); 1132 container_.GetOrCreateStringItem(type_signature); 1133 break; 1134 } 1135 case LineNumberProgramItem::Opcode::END_LOCAL: 1136 case LineNumberProgramItem::Opcode::RESTART_LOCAL: { 1137 [[maybe_unused]] int32_t reg_number; 1138 size_t n; 1139 bool is_full; 1140 std::tie(reg_number, n, is_full) = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1141 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1142 i += n; 1143 break; 1144 } 1145 case LineNumberProgramItem::Opcode::SET_FILE: { 1146 auto source_file_id = File::EntityId(state.ReadULeb128()); 1147 std::string source_file = utf::Mutf8AsCString(file_->GetStringData(source_file_id).data); 1148 container_.GetOrCreateStringItem(source_file); 1149 break; 1150 } 1151 case LineNumberProgramItem::Opcode::SET_SOURCE_CODE: { 1152 auto source_code_id = File::EntityId(state.ReadULeb128()); 1153 std::string source_code = utf::Mutf8AsCString(file_->GetStringData(source_code_id).data); 1154 container_.GetOrCreateStringItem(source_code); 1155 break; 1156 } 1157 default: { 1158 break; 1159 } 1160 } 1161 } 1162} 1163 1164void FileReader::UpdateDebugInfo(DebugInfoItem *debug_info_item, File::EntityId debug_info_id) 1165{ 1166 auto *lnp_item = debug_info_item->GetLineNumberProgram(); 1167 DebugInfoDataAccessor debug_acc(*file_, debug_info_id); 1168 const uint8_t *program = debug_acc.GetLineNumberProgram(); 1169 auto size = file_->GetSpanFromId(file_->GetIdFromPointer(program)).size(); 1170 auto opcode_sp = Span(program, size); 1171 1172 size_t i = 0; 1173 LineNumberProgramItem::Opcode opcode; 1174 panda_file::LineProgramState state(*file_, File::EntityId(0), debug_acc.GetLineStart(), 1175 debug_acc.GetConstantPool()); 1176 while ((opcode = LineNumberProgramItem::Opcode(opcode_sp[i++])) != LineNumberProgramItem::Opcode::END_SEQUENCE) { 1177 switch (opcode) { 1178 case LineNumberProgramItem::Opcode::ADVANCE_PC: { 1179 lnp_item->EmitAdvancePc(debug_info_item->GetConstantPool(), state.ReadULeb128()); 1180 break; 1181 } 1182 case LineNumberProgramItem::Opcode::ADVANCE_LINE: { 1183 lnp_item->EmitAdvanceLine(debug_info_item->GetConstantPool(), state.ReadSLeb128()); 1184 break; 1185 } 1186 case LineNumberProgramItem::Opcode::START_LOCAL: { 1187 auto [reg_number, n, is_full] = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1188 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1189 i += n; 1190 1191 auto name_id = File::EntityId(state.ReadULeb128()); 1192 std::string name = utf::Mutf8AsCString(file_->GetStringData(name_id).data); 1193 auto *name_item = container_.GetOrCreateStringItem(name); 1194 1195 auto type_id = File::EntityId(state.ReadULeb128()); 1196 std::string type_name = utf::Mutf8AsCString(file_->GetStringData(type_id).data); 1197 auto *type_item = file_->IsExternal(type_id) 1198 ? static_cast<BaseClassItem *>(container_.GetOrCreateForeignClassItem(type_name)) 1199 : static_cast<BaseClassItem *>(container_.GetOrCreateClassItem(type_name)); 1200 1201 lnp_item->EmitStartLocal(debug_info_item->GetConstantPool(), reg_number, name_item, 1202 type_item->GetNameItem()); 1203 break; 1204 } 1205 case LineNumberProgramItem::Opcode::START_LOCAL_EXTENDED: { 1206 auto [reg_number, n, is_full] = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1207 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1208 i += n; 1209 1210 auto name_id = File::EntityId(state.ReadULeb128()); 1211 std::string name = utf::Mutf8AsCString(file_->GetStringData(name_id).data); 1212 auto *name_item = container_.GetOrCreateStringItem(name); 1213 1214 auto type_id = File::EntityId(state.ReadULeb128()); 1215 std::string type_name = utf::Mutf8AsCString(file_->GetStringData(type_id).data); 1216 auto *type_item = file_->IsExternal(type_id) 1217 ? static_cast<BaseClassItem *>(container_.GetOrCreateForeignClassItem(type_name)) 1218 : static_cast<BaseClassItem *>(container_.GetOrCreateClassItem(type_name)); 1219 1220 auto type_signature_id = File::EntityId(state.ReadULeb128()); 1221 std::string type_signature = utf::Mutf8AsCString(file_->GetStringData(type_signature_id).data); 1222 auto *type_signature_item = container_.GetOrCreateStringItem(type_signature); 1223 1224 lnp_item->EmitStartLocalExtended(debug_info_item->GetConstantPool(), reg_number, name_item, 1225 type_item->GetNameItem(), type_signature_item); 1226 break; 1227 } 1228 case LineNumberProgramItem::Opcode::END_LOCAL: { 1229 auto [reg_number, n, is_full] = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1230 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1231 i += n; 1232 1233 lnp_item->EmitEndLocal(reg_number); 1234 break; 1235 } 1236 case LineNumberProgramItem::Opcode::RESTART_LOCAL: { 1237 auto [reg_number, n, is_full] = leb128::DecodeSigned<int32_t>(&opcode_sp[i]); 1238 LOG_IF(!is_full, FATAL, COMMON) << "Cannot read a register number"; 1239 i += n; 1240 1241 lnp_item->EmitRestartLocal(reg_number); 1242 break; 1243 } 1244 case LineNumberProgramItem::Opcode::SET_PROLOGUE_END: { 1245 lnp_item->EmitPrologEnd(); 1246 break; 1247 } 1248 case LineNumberProgramItem::Opcode::SET_EPILOGUE_BEGIN: { 1249 lnp_item->EmitEpilogBegin(); 1250 break; 1251 } 1252 case LineNumberProgramItem::Opcode::SET_FILE: { 1253 auto source_file_id = File::EntityId(state.ReadULeb128()); 1254 std::string source_file = utf::Mutf8AsCString(file_->GetStringData(source_file_id).data); 1255 auto *source_file_item = container_.GetOrCreateStringItem(source_file); 1256 lnp_item->EmitSetFile(debug_info_item->GetConstantPool(), source_file_item); 1257 break; 1258 } 1259 case LineNumberProgramItem::Opcode::SET_SOURCE_CODE: { 1260 auto source_code_id = File::EntityId(state.ReadULeb128()); 1261 std::string source_code = utf::Mutf8AsCString(file_->GetStringData(source_code_id).data); 1262 auto *source_code_item = container_.GetOrCreateStringItem(source_code); 1263 lnp_item->EmitSetFile(debug_info_item->GetConstantPool(), source_code_item); 1264 break; 1265 } 1266 default: { 1267 auto opcode_value = static_cast<uint8_t>(opcode); 1268 auto adjust_opcode = opcode_value - LineNumberProgramItem::OPCODE_BASE; 1269 uint32_t pc_diff = adjust_opcode / LineNumberProgramItem::LINE_RANGE; 1270 int32_t line_diff = 1271 adjust_opcode % LineNumberProgramItem::LINE_RANGE + LineNumberProgramItem::LINE_BASE; 1272 lnp_item->EmitSpecialOpcode(pc_diff, line_diff); 1273 break; 1274 } 1275 } 1276 } 1277 lnp_item->EmitEnd(); 1278} 1279 1280void AddIndexDependencyInstFlag(CodeItem *code_item, MethodItem *method_item, 1281 const std::unordered_map<File::EntityId, File::EntityId> &reverse_done) 1282{ 1283 using Flags = panda::BytecodeInst<panda::BytecodeInstMode::FAST>::Flags; 1284 1285 size_t offset = 0; 1286 BytecodeInstruction inst(code_item->GetInstructions()->data()); 1287 while (offset < code_item->GetCodeSize()) { 1288 if (inst.HasFlag(Flags::TYPE_ID)) { 1289 BytecodeId b_id = inst.GetId(); 1290 File::Index idx = b_id.AsIndex(); 1291 File::EntityId method_id = reverse_done.find(method_item)->second; 1292 File::EntityId old_id = file_->ResolveClassIndex(method_id, idx); 1293 ASSERT(items_done_.find(old_id) != items_done_.end()); 1294 auto *idx_item = static_cast<IndexedItem *>(items_done_.find(old_id)->second); 1295 method_item->AddIndexDependency(idx_item); 1296 } else if (inst.HasFlag(Flags::METHOD_ID)) { 1297 BytecodeId b_id = inst.GetId(); 1298 File::Index idx = b_id.AsIndex(); 1299 File::EntityId method_id = reverse_done.find(method_item)->second; 1300 File::EntityId old_id = file_->ResolveMethodIndex(method_id, idx); 1301 ASSERT(items_done_.find(old_id) != items_done_.end()); 1302 auto *idx_item = static_cast<IndexedItem *>(items_done_.find(old_id)->second); 1303 method_item->AddIndexDependency(idx_item); 1304 } else if (inst.HasFlag(Flags::FIELD_ID)) { 1305 BytecodeId b_id = inst.GetId(); 1306 File::Index idx = b_id.AsIndex(); 1307 File::EntityId method_id = reverse_done.find(method_item)->second; 1308 File::EntityId old_id = file_->ResolveFieldIndex(method_id, idx); 1309 ASSERT(items_done_.find(old_id) != items_done_.end()); 1310 auto *idx_item = static_cast<IndexedItem *>(items_done_.find(old_id)->second); 1311 method_item->AddIndexDependency(idx_item); 1312 } else if (inst.HasFlag(Flags::STRING_ID)) { 1313 BytecodeId b_id = inst.GetId(); 1314 File::EntityId old_id = b_id.AsFileId(); 1315 auto data = file_->GetStringData(old_id); 1316 std::string item_str(utf::Mutf8AsCString(data.data)); 1317 container_.GetOrCreateStringItem(item_str); 1318 } 1319 offset += inst.GetSize(); 1320 inst = inst.GetNext(); 1321 } 1322} 1323 1324void FileReader::UpdateCodeAndDebugInfoDependencies(const std::map<BaseItem *, File::EntityId> &reverse_done) 1325{ 1326 auto *class_map = container_.GetClassMap(); 1327 1328 // First pass, add dependencies bytecode -> new items 1329 for (const auto &it : *class_map) { 1330 auto *base_class_item = it.second; 1331 if (base_class_item->IsForeign()) { 1332 continue; 1333 } 1334 auto *class_item = static_cast<ClassItem *>(base_class_item); 1335 class_item->VisitMethods([this, &reverse_done](BaseItem *param_item) { 1336 auto *method_item = static_cast<MethodItem *>(param_item); 1337 auto *code_item = method_item->GetCode(); 1338 if (code_item == nullptr) { 1339 return true; 1340 } 1341 1342 auto *debug_info_item = method_item->GetDebugInfo(); 1343 if (debug_info_item != nullptr) { 1344 UpdateDebugInfoDependecies(reverse_done.find(debug_info_item)->second); 1345 } 1346 1347 AddIndexDependencyInstFlag(inst, method_item, reverse_done); 1348 1349 return true; 1350 }); 1351 } 1352} 1353 1354void UpdateIdInstFlag(CodeItem *code_item, MethodItem *method_item, 1355 const std::unordered_map<File::EntityId, File::EntityId> &reverse_done) 1356{ 1357 using Flags = panda::BytecodeInst<panda::BytecodeInstMode::FAST>::Flags; 1358 1359 size_t offset = 0; 1360 BytecodeInstruction inst(code_item->GetInstructions()->data()); 1361 while (offset < code_item->GetCodeSize()) { 1362 if (inst.HasFlag(Flags::TYPE_ID)) { 1363 BytecodeId b_id = inst.GetId(); 1364 File::Index idx = b_id.AsIndex(); 1365 File::EntityId method_id = reverse_done.find(method_item)->second; 1366 File::EntityId old_id = file_->ResolveClassIndex(method_id, idx); 1367 ASSERT(items_done_.find(old_id) != items_done_.end()); 1368 auto *idx_item = static_cast<IndexedItem *>(items_done_.find(old_id)->second); 1369 uint32_t index = idx_item->GetIndex(method_item); 1370 inst.UpdateId(BytecodeId(index)); 1371 } else if (inst.HasFlag(Flags::METHOD_ID)) { 1372 BytecodeId b_id = inst.GetId(); 1373 File::Index idx = b_id.AsIndex(); 1374 File::EntityId method_id = reverse_done.find(method_item)->second; 1375 File::EntityId old_id = file_->ResolveMethodIndex(method_id, idx); 1376 ASSERT(items_done_.find(old_id) != items_done_.end()); 1377 auto *idx_item = static_cast<IndexedItem *>(items_done_.find(old_id)->second); 1378 uint32_t index = idx_item->GetIndex(method_item); 1379 inst.UpdateId(BytecodeId(index)); 1380 } else if (inst.HasFlag(Flags::FIELD_ID)) { 1381 BytecodeId b_id = inst.GetId(); 1382 File::Index idx = b_id.AsIndex(); 1383 File::EntityId method_id = reverse_done.find(method_item)->second; 1384 File::EntityId old_id = file_->ResolveFieldIndex(method_id, idx); 1385 ASSERT(items_done_.find(old_id) != items_done_.end()); 1386 auto *idx_item = static_cast<IndexedItem *>(items_done_.find(old_id)->second); 1387 uint32_t index = idx_item->GetIndex(method_item); 1388 inst.UpdateId(BytecodeId(index)); 1389 } else if (inst.HasFlag(Flags::STRING_ID)) { 1390 BytecodeId b_id = inst.GetId(); 1391 File::EntityId old_id = b_id.AsFileId(); 1392 auto data = file_->GetStringData(old_id); 1393 std::string item_str(utf::Mutf8AsCString(data.data)); 1394 auto *string_item = container_.GetOrCreateStringItem(item_str); 1395 inst.UpdateId(BytecodeId(string_item->GetFileId().GetOffset())); 1396 } else if (inst.HasFlag(Flags::LITERALARRAY_ID)) { 1397 BytecodeId b_id = inst.GetId(); 1398 File::EntityId old_id = b_id.AsFileId(); 1399 ASSERT(items_done_.find(old_id) != items_done_.end()); 1400 auto *array_item = items_done_.find(old_id)->second; 1401 inst.UpdateId(BytecodeId(array_item->GetFileId().GetOffset())); 1402 } 1403 offset += inst.GetSize(); 1404 inst = inst.GetNext(); 1405 } 1406} 1407 1408void FileReader::ComputeLayoutAndUpdateIndices() 1409{ 1410 std::map<BaseItem *, File::EntityId> reverse_done; 1411 for (const auto &it : items_done_) { 1412 reverse_done.insert({it.second, it.first}); 1413 } 1414 1415 auto *class_map = container_.GetClassMap(); 1416 1417 UpdateCodeAndDebugInfoDependencies(reverse_done); 1418 1419 container_.ComputeLayout(); 1420 1421 // Second pass, update debug info 1422 for (const auto &it : *class_map) { 1423 auto *base_class_item = it.second; 1424 if (base_class_item->IsForeign()) { 1425 continue; 1426 } 1427 auto *class_item = static_cast<ClassItem *>(base_class_item); 1428 class_item->VisitMethods([this, &reverse_done](BaseItem *param_item) { 1429 auto *method_item = static_cast<MethodItem *>(param_item); 1430 auto *code_item = method_item->GetCode(); 1431 if (code_item == nullptr) { 1432 return true; 1433 } 1434 1435 auto *debug_info_item = method_item->GetDebugInfo(); 1436 if (debug_info_item != nullptr) { 1437 UpdateDebugInfo(debug_info_item, reverse_done.find(debug_info_item)->second); 1438 } 1439 1440 return true; 1441 }); 1442 } 1443 1444 container_.DeduplicateItems(false); 1445 container_.ComputeLayout(); 1446 1447 // Third pass, update bytecode indices 1448 for (const auto &it : *class_map) { 1449 auto *base_class_item = it.second; 1450 if (base_class_item->IsForeign()) { 1451 continue; 1452 } 1453 auto *class_item = static_cast<ClassItem *>(base_class_item); 1454 class_item->VisitMethods([this, &reverse_done](BaseItem *param_item) { 1455 auto *method_item = static_cast<MethodItem *>(param_item); 1456 auto *code_item = method_item->GetCode(); 1457 if (code_item == nullptr) { 1458 return true; 1459 } 1460 1461 UpdateIdInstFlag(code_item, method_item, reverse_done); 1462 1463 return true; 1464 }); 1465 } 1466} 1467 1468} // namespace panda::panda_file 1469