diff --git a/lib/libcxxabi/include/cxxabi.h b/lib/libcxxabi/include/cxxabi.h index d070118175..8d1b5c9b55 100644 --- a/lib/libcxxabi/include/cxxabi.h +++ b/lib/libcxxabi/include/cxxabi.h @@ -48,13 +48,17 @@ extern _LIBCXXABI_FUNC_VIS void __cxa_free_exception(void *thrown_exception) throw(); // This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt extern _LIBCXXABI_FUNC_VIS __cxa_exception* +#ifdef __wasm__ +// In Wasm, a destructor returns its argument +__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw(); +#else __cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw(); +#endif // 2.4.3 Throwing the Exception Object extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_throw(void *thrown_exception, std::type_info *tinfo, -#ifdef __USING_WASM_EXCEPTIONS__ - // In Wasm, a destructor returns its argument +#ifdef __wasm__ void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)); #else void (_LIBCXXABI_DTOR_FUNC *dest)(void *)); @@ -73,6 +77,11 @@ extern _LIBCXXABI_FUNC_VIS void __cxa_end_cleanup(); #endif extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type(); +// GNU extension +// Calls `terminate` with the current exception being caught. This function is used by GCC when a `noexcept` function +// throws an exception inside a try/catch block and doesn't catch it. +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_call_terminate(void*) throw(); + // 2.5.4 Rethrowing Exceptions extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow(); diff --git a/lib/libcxxabi/src/aix_state_tab_eh.inc b/lib/libcxxabi/src/aix_state_tab_eh.inc index 0cd94834b3..0ed329890a 100644 --- a/lib/libcxxabi/src/aix_state_tab_eh.inc +++ b/lib/libcxxabi/src/aix_state_tab_eh.inc @@ -102,8 +102,6 @@ static bool state_tab_dbg() { namespace __state_table_eh { -using destruct_f = void (*)(void*); - // Definition of flags for the state table entry field 'action flag'. enum FSMEntryCount : intptr_t { beginCatch = -1, endCatch = -2, deleteObject = -3, cleanupLabel = -4, terminate = -5 }; @@ -145,8 +143,10 @@ struct FSMEntry { intptr_t nextStatePtr; }; union { - // Address of the destructor function. - void (*destructor)(void*, size_t); + // Address of the destructor function with 1 argument. + void (*destructor)(void*); + // Address of the destructor function with 2 arguments. + void (*xlCDestructor)(void*, size_t); // The address of the catch block or cleanup code. void* landingPad; }; @@ -191,12 +191,12 @@ static void invoke_destructor(FSMEntry* fsmEntry, void* addr) { try { if (fsmEntry->elementCount == 1) { _LIBCXXABI_TRACE_STATETAB0("calling scalar destructor\n"); - (*fsmEntry->destructor)(addr, dtorArgument); + (*fsmEntry->xlCDestructor)(addr, dtorArgument); _LIBCXXABI_TRACE_STATETAB0("returned from scalar destructor\n"); } else { _LIBCXXABI_TRACE_STATETAB0("calling vector destructor\n"); __cxa_vec_cleanup(addr, reinterpret_cast(fsmEntry->elementCount), fsmEntry->elemSize, - reinterpret_cast(fsmEntry->destructor)); + fsmEntry->destructor); _LIBCXXABI_TRACE_STATETAB0("returned from vector destructor\n"); } } catch (...) { @@ -213,7 +213,7 @@ static void invoke_delete(FSMEntry* fsmEntry, void* addr) { try { _LIBCXXABI_TRACE_STATETAB0("..calling delete()\n"); // 'destructor' holds a function pointer to delete(). - (*fsmEntry->destructor)(objectAddress, fsmEntry->elemSize); + (*fsmEntry->xlCDestructor)(objectAddress, fsmEntry->elemSize); _LIBCXXABI_TRACE_STATETAB0("..returned from delete()\n"); } catch (...) { _LIBCXXABI_TRACE_STATETAB0("Uncaught exception in delete(), terminating\n"); @@ -681,7 +681,7 @@ static uintptr_t* skip_non_cxx_eh_aware_frames(uint32_t* Pc, uintptr_t* Sp) { // xlclang++ compiled code. If __xlc_exception_handle() is called by // non-C++ EH aware functions, their frames are skipped until a C++ EH aware // frame is found. -// Note: make sure __xlc_excpetion_handle() is a non-leaf function. Currently +// Note: make sure __xlc_exception_handle() is a non-leaf function. Currently // it calls skip_non_cxx_eh_aware_frames(), which in turn calls abort(). _LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() { // Get the SP of this function, i.e., __xlc_exception_handle(). diff --git a/lib/libcxxabi/src/cxa_exception.cpp b/lib/libcxxabi/src/cxa_exception.cpp index 65e9f4504d..92901a83bf 100644 --- a/lib/libcxxabi/src/cxa_exception.cpp +++ b/lib/libcxxabi/src/cxa_exception.cpp @@ -207,7 +207,12 @@ void __cxa_free_exception(void *thrown_object) throw() { } __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo, +#ifdef __wasm__ +// In Wasm, a destructor returns its argument + void *(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() { +#else void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() { +#endif __cxa_exception* exception_header = cxa_exception_from_thrown_object(object); exception_header->referenceCount = 0; exception_header->unexpectedHandler = std::get_unexpected(); @@ -267,7 +272,7 @@ will call terminate, assuming that there was no handler for the exception. */ void -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __wasm__ // In Wasm, a destructor returns its argument __cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) { #else @@ -584,6 +589,11 @@ void __cxa_end_catch() { } } +void __cxa_call_terminate(void* unwind_arg) throw() { + __cxa_begin_catch(unwind_arg); + std::terminate(); +} + // Note: exception_header may be masquerading as a __cxa_dependent_exception // and that's ok. exceptionType is there too. // However watch out for foreign exceptions. Return null for them. diff --git a/lib/libcxxabi/src/cxa_exception.h b/lib/libcxxabi/src/cxa_exception.h index 10712f6f47..aba08f2992 100644 --- a/lib/libcxxabi/src/cxa_exception.h +++ b/lib/libcxxabi/src/cxa_exception.h @@ -43,7 +43,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { // Manage the exception object itself. std::type_info *exceptionType; -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __wasm__ // In Wasm, a destructor returns its argument void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); #else diff --git a/lib/libcxxabi/src/cxa_exception_storage.cpp b/lib/libcxxabi/src/cxa_exception_storage.cpp index 3a3233a1b9..c842da195a 100644 --- a/lib/libcxxabi/src/cxa_exception_storage.cpp +++ b/lib/libcxxabi/src/cxa_exception_storage.cpp @@ -12,7 +12,7 @@ #include "cxa_exception.h" -#include <__threading_support> +#include <__thread/support.h> #if defined(_LIBCXXABI_HAS_NO_THREADS) @@ -24,7 +24,7 @@ extern "C" { } // extern "C" } // namespace __cxxabiv1 -#elif defined(HAS_THREAD_LOCAL) +#elif __has_feature(cxx_thread_local) namespace __cxxabiv1 { namespace { diff --git a/lib/libcxxabi/src/cxa_guard_impl.h b/lib/libcxxabi/src/cxa_guard_impl.h index 90d589be4d..320501cb85 100644 --- a/lib/libcxxabi/src/cxa_guard_impl.h +++ b/lib/libcxxabi/src/cxa_guard_impl.h @@ -58,7 +58,7 @@ # endif #endif -#include <__threading_support> +#include <__thread/support.h> #include #include #include diff --git a/lib/libcxxabi/src/cxa_personality.cpp b/lib/libcxxabi/src/cxa_personality.cpp index 4b6c4edbc2..843a18a4cb 100644 --- a/lib/libcxxabi/src/cxa_personality.cpp +++ b/lib/libcxxabi/src/cxa_personality.cpp @@ -70,7 +70,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, +------------------+--+-----+-----+------------------------+--------------------------+ | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table | +---------------------+-----------+---------------------------------------------------+ -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip lies within the | | ... (start, length) range of one of these | @@ -84,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, | +-------------+---------------------------------+------------------------------+ | | ... | +----------------------------------------------------------------------------------+ -#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip is a 1-based index into | | ... this table. Or it is -1 meaning no | @@ -97,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, | +-------------+---------------------------------+------------------------------+ | | ... | +----------------------------------------------------------------------------------+ -#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ +---------------------------------------------------------------------+ | Beginning of Action Table ttypeIndex == 0 : cleanup | | ... ttypeIndex > 0 : catch | @@ -547,7 +547,7 @@ void set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, const scan_results& results) { -#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__) +#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__WASM_EXCEPTIONS__) #define __builtin_eh_return_data_regno(regno) regno #elif defined(__ibmxl__) // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno. @@ -642,7 +642,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); -#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__) +#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__WASM_EXCEPTIONS__) if (ip == uintptr_t(-1)) { // no action @@ -652,9 +652,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, else if (ip == 0) call_terminate(native_exception, unwind_exception); // ip is 1-based index into call site table -#else // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__ +#else // !__USING_SJLJ_EXCEPTIONS__ && !__WASM_EXCEPTIONS__ uintptr_t ipOffset = ip - funcStart; -#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__ +#endif // !__USING_SJLJ_EXCEPTIONS__ && !__WASM_EXCEPTIONS__ const uint8_t* classInfo = NULL; // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission @@ -675,7 +675,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; -#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__) +#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__WASM_EXCEPTIONS__) (void)callSiteEncoding; // When using SjLj/Wasm exceptions, callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast(readULEB128(&lsda)); @@ -686,7 +686,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); @@ -694,15 +694,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) -#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ // ip is 1-based index into this table uintptr_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) -#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ { // Found the call site containing ip. -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) if (landingPad == 0) { // No handler here @@ -710,16 +710,14 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, return; } landingPad = (uintptr_t)lpStart + landingPad; -#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ ++landingPad; -#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__ +#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ results.landingPad = landingPad; if (actionEntry == 0) { // Found a cleanup - results.reason = actions & _UA_SEARCH_PHASE - ? _URC_CONTINUE_UNWIND - : _URC_HANDLER_FOUND; + results.reason = (actions & _UA_SEARCH_PHASE) ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; return; } // Convert 1-based byte offset into @@ -840,7 +838,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, action += actionOffset; } // there is no break out of this loop, only return } -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__WASM_EXCEPTIONS__) else if (ipOffset < start) { // There is no call site for this ip @@ -848,7 +846,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Possible stack corruption. call_terminate(native_exception, unwind_exception); } -#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__ +#endif // !__USING_SJLJ_EXCEPTIONS__ && !__WASM_EXCEPTIONS__ } // there might be some tricky cases which break out of this loop // It is possible that no eh table entry specify how to handle @@ -905,7 +903,7 @@ _UA_CLEANUP_PHASE */ #if !defined(_LIBCXXABI_ARM_EHABI) -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ _Unwind_Reason_Code __gxx_personality_wasm0 #elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) static _Unwind_Reason_Code __gxx_personality_imp @@ -974,7 +972,7 @@ __gxx_personality_v0 exc->languageSpecificData = results.languageSpecificData; exc->catchTemp = reinterpret_cast(results.landingPad); exc->adjustedPtr = results.adjustedPtr; -#ifdef __USING_WASM_EXCEPTIONS__ +#ifdef __WASM_EXCEPTIONS__ // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the // results here. set_registers(unwind_exception, context, results); diff --git a/lib/libcxxabi/src/cxa_thread_atexit.cpp b/lib/libcxxabi/src/cxa_thread_atexit.cpp index 665f9e5569..c6bd0aa323 100644 --- a/lib/libcxxabi/src/cxa_thread_atexit.cpp +++ b/lib/libcxxabi/src/cxa_thread_atexit.cpp @@ -8,7 +8,7 @@ #include "abort_message.h" #include "cxxabi.h" -#include <__threading_support> +#include <__thread/support.h> #ifndef _LIBCXXABI_HAS_NO_THREADS #if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB) #pragma comment(lib, "pthread") diff --git a/lib/libcxxabi/src/demangle/ItaniumDemangle.h b/lib/libcxxabi/src/demangle/ItaniumDemangle.h index 5a53a18bcc..36bf454636 100644 --- a/lib/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/lib/libcxxabi/src/demangle/ItaniumDemangle.h @@ -39,13 +39,12 @@ DEMANGLE_NAMESPACE_BEGIN template class PODSmallVector { - static_assert(std::is_pod::value, - "T is required to be a plain old data type"); - + static_assert(std::is_trivial::value, + "T is required to be a trivial type"); T *First = nullptr; T *Last = nullptr; T *Cap = nullptr; - T Inline[N] = {0}; + T Inline[N] = {}; bool isInline() const { return First == Inline; } @@ -5542,7 +5541,7 @@ Node *AbstractManglingParser::parseFloatingLiteral() { return nullptr; std::string_view Data(First, N); for (char C : Data) - if (!std::isxdigit(C)) + if (!(C >= '0' && C <= '9') && !(C >= 'a' && C <= 'f')) return nullptr; First += N; if (!consumeIf('E')) @@ -5716,6 +5715,7 @@ Node *AbstractManglingParser::parseTemplateParam() { } // ::= Ty # type parameter +// ::= Tk [] # constrained type parameter // ::= Tn # non-type parameter // ::= Tt * E # template parameter // ::= Tp # parameter pack @@ -5847,7 +5847,7 @@ Node *AbstractManglingParser::parseTemplateArg() { } } -// ::= I * E +// ::= I * [Q ] E // extension, the abi says + template Node * diff --git a/lib/libcxxabi/src/fallback_malloc.cpp b/lib/libcxxabi/src/fallback_malloc.cpp index fa802b2d81..76bd2e9bcd 100644 --- a/lib/libcxxabi/src/fallback_malloc.cpp +++ b/lib/libcxxabi/src/fallback_malloc.cpp @@ -9,7 +9,7 @@ #include "fallback_malloc.h" #include "abort_message.h" -#include <__threading_support> +#include <__thread/support.h> #ifndef _LIBCXXABI_HAS_NO_THREADS #if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB) #pragma comment(lib, "pthread") diff --git a/lib/libcxxabi/src/private_typeinfo.cpp b/lib/libcxxabi/src/private_typeinfo.cpp index 857ae25b70..9dba91e198 100644 --- a/lib/libcxxabi/src/private_typeinfo.cpp +++ b/lib/libcxxabi/src/private_typeinfo.cpp @@ -44,13 +44,25 @@ #include #include #include +#include "abort_message.h" #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST -#include "abort_message.h" #include #include #endif +#if __has_feature(ptrauth_calls) +#include +#endif + +template +static inline T* strip_vtable(T* vtable) { +#if __has_feature(ptrauth_calls) + vtable = ptrauth_strip(vtable, ptrauth_key_cxx_vtable_pointer); +#endif + return vtable; +} + static inline bool is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) @@ -102,10 +114,10 @@ void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr reinterpret_cast(vtable) + offset_to_ti_proxy; info->dynamic_type = *(reinterpret_cast(ptr_to_ti_proxy)); #else - void **vtable = *static_cast(static_ptr); - info->offset_to_derived = reinterpret_cast(vtable[-2]); - info->dynamic_ptr = static_cast(static_ptr) + info->offset_to_derived; - info->dynamic_type = static_cast(vtable[-1]); + void** vtable = strip_vtable(*static_cast(static_ptr)); + info->offset_to_derived = reinterpret_cast(vtable[-2]); + info->dynamic_ptr = static_cast(static_ptr) + info->offset_to_derived; + info->dynamic_type = static_cast(vtable[-1]); #endif } @@ -470,7 +482,7 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type, if (thrown_class_type == 0) return false; // bullet 2 - assert(adjustedPtr && "catching a class without an object?"); + _LIBCXXABI_ASSERT(adjustedPtr, "catching a class without an object?"); __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, nullptr}; info.number_of_dst_type = 1; thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path); @@ -560,7 +572,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, find the layout. */ offset_to_base = __offset_flags >> __offset_shift; if (is_virtual) { - const char* vtable = *static_cast(adjustedPtr); + const char* vtable = strip_vtable(*static_cast(adjustedPtr)); offset_to_base = update_offset_to_base(vtable, offset_to_base); } } else if (!is_virtual) { @@ -1500,8 +1512,8 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info, ptrdiff_t offset_to_base = __offset_flags >> __offset_shift; if (__offset_flags & __virtual_mask) { - const char* vtable = *static_cast(current_ptr); - offset_to_base = update_offset_to_base(vtable, offset_to_base); + const char* vtable = strip_vtable(*static_cast(current_ptr)); + 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, @@ -1520,8 +1532,8 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, ptrdiff_t offset_to_base = __offset_flags >> __offset_shift; if (__offset_flags & __virtual_mask) { - const char* vtable = *static_cast(current_ptr); - offset_to_base = update_offset_to_base(vtable, offset_to_base); + const char* vtable = strip_vtable(*static_cast(current_ptr)); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_below_dst(info, static_cast(current_ptr) + offset_to_base,