[libcxx-commits] [libcxxabi] 61aec69 - [libcxxabi] Add macro for changing functions to support the relative vtables ABI

Leonard Chan via libcxx-commits libcxx-commits at lists.llvm.org
Mon Nov 30 10:50:51 PST 2020


Author: Leonard Chan
Date: 2020-11-30T10:50:05-08:00
New Revision: 61aec69a65dec949f3d2556c4d0efaa87869e1ee

URL: https://github.com/llvm/llvm-project/commit/61aec69a65dec949f3d2556c4d0efaa87869e1ee
DIFF: https://github.com/llvm/llvm-project/commit/61aec69a65dec949f3d2556c4d0efaa87869e1ee.diff

LOG: [libcxxabi] Add macro for changing functions to support the relative vtables ABI

Under the relative vtables ABI, __dynamic_cast will not work since it assumes
the vtable pointer is 2 ptrdiff_ts away from the start of the vtable (8-byte
offset to top + 8-byte pointer to typeinfo) when it is actually 8 bytes away
(4-byte offset to top + 4-byte offset to typeinfo). This adjusts the logic under
__dynamic_cast and other areas vtable calculations are done to support this ABI
when it's used.

Differential Revision: https://reviews.llvm.org/D77606

Added: 
    

Modified: 
    libcxxabi/src/private_typeinfo.cpp

Removed: 
    


################################################################################
diff  --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp
index 3e8bdae32e41..c77ad669c49e 100644
--- a/libcxxabi/src/private_typeinfo.cpp
+++ b/libcxxabi/src/private_typeinfo.cpp
@@ -61,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
     return x == y || strcmp(x->name(), y->name()) == 0;
 }
 
+static inline ptr
diff _t update_offset_to_base(const char* vtable,
+                                              ptr
diff _t offset_to_base) {
+#if __has_feature(cxx_abi_relative_vtable)
+  // VTable components are 32 bits in the relative vtables ABI.
+  return *reinterpret_cast<const int32_t*>(vtable + offset_to_base);
+#else
+  return *reinterpret_cast<const ptr
diff _t*>(vtable + offset_to_base);
+#endif
+}
+
 namespace __cxxabiv1
 {
 
@@ -297,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
         if (__offset_flags & __virtual_mask)
         {
             const char* vtable = *static_cast<const char*const*>(adjustedPtr);
-            offset_to_base = *reinterpret_cast<const ptr
diff _t*>(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 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
     // 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<const int32_t* const*>(static_ptr);
+    int32_t offset_to_derived = vtable[-2];
+    const void* dynamic_ptr = static_cast<const char*>(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<const uint8_t*>(vtable) + offset_to_ti_proxy;
+    const __class_type_info* dynamic_type =
+        *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
+#else
     void **vtable = *static_cast<void ** const *>(static_ptr);
     ptr
diff _t offset_to_derived = reinterpret_cast<ptr
diff _t>(vtable[-2]);
     const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
     const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(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 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info,
     if (__offset_flags & __virtual_mask)
     {
         const char* vtable = *static_cast<const char*const*>(current_ptr);
-        offset_to_base = *reinterpret_cast<const ptr
diff _t*>(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<const char*>(current_ptr) + offset_to_base,
@@ -1287,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
     if (__offset_flags & __virtual_mask)
     {
         const char* vtable = *static_cast<const char*const*>(current_ptr);
-        offset_to_base = *reinterpret_cast<const ptr
diff _t*>(vtable + offset_to_base);
+        offset_to_base = update_offset_to_base(vtable, offset_to_base);
     }
     __base_type->search_below_dst(info,
                                   static_cast<const char*>(current_ptr) + offset_to_base,


        


More information about the libcxx-commits mailing list