diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp --- a/libcxxabi/src/private_typeinfo.cpp +++ b/libcxxabi/src/private_typeinfo.cpp @@ -61,6 +61,16 @@ return x == y || strcmp(x->name(), y->name()) == 0; } +static inline ptrdiff_t update_offset_to_base(const char* vtable, + ptrdiff_t offset_to_base) { +#if __has_feature(cxx_abi_relative_vtable) + // VTable components are 32 bits in the relative vtables ABI. + return *reinterpret_cast(vtable + offset_to_base); +#else + return *reinterpret_cast(vtable + offset_to_base); +#endif +} + namespace __cxxabiv1 { @@ -297,7 +307,7 @@ if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(adjustedPtr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } } __base_type->has_unambiguous_public_base( @@ -615,10 +625,26 @@ // Possible future optimization: Take advantage of src2dst_offset // Get (dynamic_ptr, dynamic_type) from static_ptr +#if __has_feature(cxx_abi_relative_vtable) + // The vtable address will point to the first virtual function, which is 8 + // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component). + const int32_t* vtable = + *reinterpret_cast(static_ptr); + int32_t offset_to_derived = vtable[-2]; + const void* dynamic_ptr = static_cast(static_ptr) + offset_to_derived; + + // The typeinfo component is now a relative offset to a proxy. + int32_t offset_to_ti_proxy = vtable[-1]; + const uint8_t* ptr_to_ti_proxy = + reinterpret_cast(vtable) + offset_to_ti_proxy; + const __class_type_info* dynamic_type = + *(reinterpret_cast(ptr_to_ti_proxy)); +#else void **vtable = *static_cast(static_ptr); ptrdiff_t offset_to_derived = reinterpret_cast(vtable[-2]); const void* dynamic_ptr = static_cast(static_ptr) + offset_to_derived; const __class_type_info* dynamic_type = static_cast(vtable[-1]); +#endif // Initialize answer to nullptr. This will be changed from the search // results if a non-null answer is found. Regardless, this is what will @@ -1267,7 +1293,7 @@ if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_above_dst(info, dst_ptr, static_cast(current_ptr) + offset_to_base, @@ -1287,7 +1313,7 @@ if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_below_dst(info, static_cast(current_ptr) + offset_to_base,