summaryrefslogtreecommitdiff
path: root/plugins/rtti/itanium.cpp
diff options
context:
space:
mode:
authorMark Rowe <mrowe@bdash.net.nz>2025-05-09 15:09:23 -0700
committerMason Reed <35282038+emesare@users.noreply.github.com>2025-05-09 20:57:25 -0400
commit77171115175039b2aef96f754005fea13d2b4375 (patch)
tree26ed15d88f0d992e1a952bb221fc005b10c041c6 /plugins/rtti/itanium.cpp
parent20945fadfe373d44f916e5e15619e0226459dd98 (diff)
[RTTI] Handle cxxabi vtables being referenced via RELOC_COPY
32-bit ELF binaries that are dynamically linked to the C++ runtime may use a copy relocation for the vtable. The vtable itself will be defined in the `.bss` section, and the copy relocation will cause the dynamic linker to populate it at load time from the C++ runtime library. Detect this by looking for a symbol pointing to the start of the vtable data, two pointers before the vtable address.
Diffstat (limited to 'plugins/rtti/itanium.cpp')
-rw-r--r--plugins/rtti/itanium.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/plugins/rtti/itanium.cpp b/plugins/rtti/itanium.cpp
index a6e85b4d..5e1cf0a8 100644
--- a/plugins/rtti/itanium.cpp
+++ b/plugins/rtti/itanium.cpp
@@ -291,6 +291,32 @@ Ref<Type> VMIClassTypeInfoType(BinaryView *view, uint64_t baseCount)
return TypeBuilder::StructureType(structureBuilder.Finalize()).Finalize();
}
+static Ref<Symbol> DetectPotentialCopyRelocatedVTable(BinaryView* view, uint64_t address)
+{
+ // 32-bit ELF binaries that are dynamically linked to the C++ runtime may use a
+ // copy relocation for the vtable. The vtable itself will be defined in the .bss
+ // section, and the copy relocation will cause the dynamic linker to populate it
+ // at load time from the C++ runtime library.
+ //
+ // Detect this by looking for a symbol pointing to the start of the vtable data,
+ // two pointers before the vtable address.
+
+ int64_t vtableSymbolOffset = -(view->GetAddressSize() * 2);
+ if (!view->IsValidOffset(address) || !view->IsValidOffset(address + vtableSymbolOffset))
+ return nullptr;
+
+ // ELFView does not add a relocation record for RELOC_COPY so we use hueristics here.
+ if (view->IsOffsetBackedByFile(address))
+ return nullptr;
+ if (!view->IsOffsetWritableSemantics(address))
+ return nullptr;
+
+ auto sym = view->GetSymbolByAddress(address + vtableSymbolOffset);
+ if (!sym || sym->GetShortName().find("__cxxabiv1") == std::string::npos)
+ return nullptr;
+
+ return sym;
+}
std::optional<TypeInfoVariant> ReadTypeInfoVariant(BinaryView *view, uint64_t objectAddr)
{
@@ -301,6 +327,9 @@ std::optional<TypeInfoVariant> ReadTypeInfoVariant(BinaryView *view, uint64_t ob
// If there is a symbol at objectAddr pointing to a symbol starting with "vtable for __cxxabiv1"
Ref<Symbol> baseSym = GetRealSymbol(view, objectAddr, typeInfo->base);
+ if (!baseSym)
+ baseSym = DetectPotentialCopyRelocatedVTable(view, typeInfo->base);
+
if (baseSym == nullptr)
{
// Verify first that we can even read a pointer sized value at the base.