diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -171,6 +171,11 @@ option(LIBCXXABI_HERMETIC_STATIC_LIBRARY "Do not export any symbols from the static library." OFF) +option(LIBCXXABI_RELATIVE_VTABLES_ABI_ENABLED + "Use different configurations of libcxxabi functions supported for the \ + Relative VTables ABI, which replaces vtable function pointers with offsets \ + between those virtual functions and the vtable itself." OFF) + #=============================================================================== # Configure System #=============================================================================== @@ -470,6 +475,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBCXXABI_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBCXXABI_C_FLAGS}") +if (LIBCXXABI_RELATIVE_VTABLES_ABI_ENABLED) + add_definitions(-D_LIBCXXABI_RELATIVE_VTABLES_ABI_ENABLED) +endif() + #=============================================================================== # Setup Source Code #=============================================================================== 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 @@ -614,10 +614,26 @@ // Possible future optimization: Take advantage of src2dst_offset // Get (dynamic_ptr, dynamic_type) from static_ptr +#ifdef _LIBCXXABI_RELATIVE_VTABLES_ABI_ENABLED + // The vtable address will point to the first virtual function, which is 12 + // bytes after the start of the vtable (8 for the offset from top + 4 for the typeinfo component). + uint8_t* vtable = *reinterpret_cast(static_ptr); + ptrdiff_t offset_to_derived = *(reinterpret_cast(vtable - 12)); + + 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 = *reinterpret_cast(vtable - 4); + uint8_t* ptr_to_ti_proxy = vtable + offset_to_ti_proxy; + const __class_type_info* dynamic_type = + *(reinterpret_cast<__class_type_info**>(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