| 441 | |
| 442 | |
| 443 | std::optional<ClassInfo> ItaniumRTTIProcessor::ProcessRTTI(uint64_t objectAddr) |
| 444 | { |
| 445 | // TODO: You cant get sub-object offsets from rtti, its stored above this ptr in vtable. |
| 446 | // Get object as type info then check to see if it's valid. |
| 447 | auto typeInfoVariant = ReadTypeInfoVariant(m_view, objectAddr); |
| 448 | if (!typeInfoVariant.has_value()) |
| 449 | return std::nullopt; |
| 450 | |
| 451 | auto typeInfo = TypeInfo(m_view, objectAddr); |
| 452 | auto className = DemangleNameItanium(m_view, allowMangledClassNames, typeInfo.type_name); |
| 453 | if (!className.has_value() || className->empty()) |
| 454 | return std::nullopt; |
| 455 | auto classInfo = ClassInfo{RTTIProcessorType::Itanium, className.value()}; |
| 456 | |
| 457 | auto nameFromTypeInfoSymbol = [&](uint64_t addr) -> std::optional<std::string> { |
| 458 | auto sym = m_view->GetSymbolByAddress(addr); |
| 459 | if (sym == nullptr || sym->GetType() != ExternalSymbol) |
| 460 | return std::nullopt; |
| 461 | auto symName = sym->GetShortName(); |
| 462 | // Remove type info prefix. |
| 463 | if (symName.rfind("_typeinfo_for_", 0) != 0) |
| 464 | return std::nullopt; |
| 465 | return symName.substr(14); |
| 466 | }; |
| 467 | |
| 468 | if (typeInfoVariant == TIVSIClass) |
| 469 | { |
| 470 | // Read the base class. |
| 471 | auto siClassTypeInfo = SIClassTypeInfo(m_view, objectAddr); |
| 472 | auto subTypeInfoVariant = ReadTypeInfoVariant(m_view, siClassTypeInfo.base_type); |
| 473 | std::string subTypeName; |
| 474 | if (!subTypeInfoVariant.has_value()) |
| 475 | { |
| 476 | // Allow externals to be used in place of a backed subtype. |
| 477 | // TODO: We should probably warn that vtables will likely be inaccurate. |
| 478 | // TODO: Because we wont know what offsets are valid. |
| 479 | auto externTypeName = nameFromTypeInfoSymbol(siClassTypeInfo.base_type); |
| 480 | if (!externTypeName.has_value()) |
| 481 | return std::nullopt; |
| 482 | m_logger->LogDebug("Non-backed external subtype for %llx", objectAddr); |
| 483 | subTypeName = externTypeName.value(); |
| 484 | } |
| 485 | else |
| 486 | { |
| 487 | auto subTypeInfo = TypeInfo(m_view, siClassTypeInfo.base_type); |
| 488 | subTypeName = subTypeInfo.type_name; |
| 489 | } |
| 490 | // Demangle base class name and set |
| 491 | auto baseClassName = DemangleNameItanium(m_view, allowMangledClassNames, subTypeName); |
| 492 | if (!baseClassName.has_value()) |
| 493 | { |
| 494 | m_logger->LogWarn("Skipping base class with mangled name %llx", siClassTypeInfo.base_type); |
| 495 | return std::nullopt; |
| 496 | } |
| 497 | // NOTE: The base class offset is not able to be resolved here. |
| 498 | // NOTE: To resolve the base class offset you must go to the vtable. |
| 499 | uint64_t baseClassOffset = 0; |
| 500 | auto subBaseClassInfo = BaseClassInfo {baseClassName.value(), baseClassOffset}; |
no test coverage detected