From a961ad35e5f6ffdb01278f2e3bf3e277069e5be8 Mon Sep 17 00:00:00 2001 From: Prophet069 <291514246+Prophet069@users.noreply.github.com> Date: Thu, 8 Oct 2026 22:56:11 +0200 Subject: [PATCH 1/2] fix(libc): bridge guest message exception destructors Guest message throws registered native Windows callbacks even though Release invokes guest callbacks using System V. Register an APS5_VABI adapter in the standard and regex message throw paths and retain the native DestroyMessage helper and legacy callback storage type. Add MinGW CTest regressions with distinct or zero RCX, shared and final-release messages, typed guest catches, rethrow and normal Release. All ten new cases plus Windows exception and thread callback regressions pass three repetitions. Linux execution remains unvalidated; guest vtables and host exception paths are unchanged. --- core/libs/prx/libc/CMakeLists.txt | 15 ++ .../libc/src/exception/StandardExceptions.cpp | 9 +- core/libs/tests/GuestMessageDestructorAbi.S | 191 ++++++++++++++++++ core/libs/tests/GuestMessageDestructorAbi.cpp | 121 +++++++++++ 4 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 core/libs/tests/GuestMessageDestructorAbi.S create mode 100644 core/libs/tests/GuestMessageDestructorAbi.cpp diff --git a/core/libs/prx/libc/CMakeLists.txt b/core/libs/prx/libc/CMakeLists.txt index 30aaf71ba88..1677e99f434 100644 --- a/core/libs/prx/libc/CMakeLists.txt +++ b/core/libs/prx/libc/CMakeLists.txt @@ -373,6 +373,21 @@ if(BUILD_TESTING) endif() if(MINGW) + if(BUILD_TESTING) + enable_language(ASM) + add_test_executable(guest_message_destructor_abi_tests + ${LIBS_INCLUDE_DIR}/tests/GuestMessageDestructorAbi.cpp + ${LIBS_INCLUDE_DIR}/tests/GuestMessageDestructorAbi.S) + target_include_directories(guest_message_destructor_abi_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_message_destructor_abi_tests PRIVATE libc) + configure_windows_unwind(guest_message_destructor_abi_tests) + foreach(mode IN ITEMS control decoy zero release regex-decoy regex-zero + unshared-decoy unshared-zero regex-unshared-decoy regex-unshared-zero) + add_test(NAME guest_message_destructor_${mode} COMMAND guest_message_destructor_abi_tests ${mode}) + set_tests_properties(guest_message_destructor_${mode} PROPERTIES TIMEOUT 10 + ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") + endforeach() + endif() foreach(runtimeLinkFlag IN ITEMS -static-libgcc -static-libstdc++ -static) string(REPLACE "${runtimeLinkFlag}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") endforeach() diff --git a/core/libs/prx/libc/src/exception/StandardExceptions.cpp b/core/libs/prx/libc/src/exception/StandardExceptions.cpp index b8bf43028f1..f6b2bd2cb66 100644 --- a/core/libs/prx/libc/src/exception/StandardExceptions.cpp +++ b/core/libs/prx/libc/src/exception/StandardExceptions.cpp @@ -71,6 +71,9 @@ void ReleaseMessage(const char* message) { void DestroyPlain(ExceptionObject*) {} void DeletePlain(ExceptionObject* object) { std::free(object); } void DestroyMessage(ExceptionObject* object) { ReleaseMessage(object->message); object->message = nullptr; } +static void APS5_VABI DestroyGuestMessage_nid_no_patch(void* object) { + DestroyMessage(static_cast(object)); +} void DeleteMessage(ExceptionObject* object) { DestroyMessage(object); std::free(object); } const char* PlainWhat(const ExceptionObject* object) { auto* table = static_cast(object->vtable); @@ -102,7 +105,8 @@ ExceptionObject* Assign(ExceptionObject* object, const ExceptionObject* source) [[noreturn]] void ThrowMessage(const ExceptionVtable& table, const char* message) { auto* object = static_cast(__cxa_allocate_exception_nid_postfix(sizeof(ExceptionObject))); Construct(object, table, message); - __cxa_throw_nid_postfix(object, reinterpret_cast(const_cast(table.type)), [](void* p) { DestroyMessage(static_cast(p)); }); + __cxa_throw_nid_postfix(object, reinterpret_cast(const_cast(table.type)), + reinterpret_cast(DestroyGuestMessage_nid_no_patch)); } [[noreturn]] void ThrowPlain(const ExceptionVtable& table) { auto* object = static_cast(__cxa_allocate_exception_nid_postfix(sizeof(void*))); @@ -304,6 +308,7 @@ const char* APS5_VABI _ZNKSt8ios_base7failure4whatEv_nid_postfix(const LibcExcep auto* object = static_cast(__cxa_allocate_exception_nid_postfix(sizeof(RegexObject))); LibcException::Construct(&object->base, _ZTVSt11regex_error_nid_postfix, "regular expression error"); object->code = code; - __cxa_throw_nid_postfix(object, reinterpret_cast(&_ZTISt11regex_error_nid_postfix), [](void* p) { LibcException::DestroyMessage(static_cast(p)); }); + __cxa_throw_nid_postfix(object, reinterpret_cast(&_ZTISt11regex_error_nid_postfix), + reinterpret_cast(LibcException::DestroyGuestMessage_nid_no_patch)); } } diff --git a/core/libs/tests/GuestMessageDestructorAbi.S b/core/libs/tests/GuestMessageDestructorAbi.S new file mode 100644 index 00000000000..580843d1710 --- /dev/null +++ b/core/libs/tests/GuestMessageDestructorAbi.S @@ -0,0 +1,191 @@ +.cfi_sections .eh_frame +.text +.macro PROLOGUE + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $16, %rsp +.endm +.macro WHAT + movq %rax, %rdi + movq (%rax), %r11 + call *16(%r11) + movq %rax, %rdi + call FixtureCheckWhat +.endm +.globl GuestThrow +GuestThrow: + .cfi_startproc + PROLOGUE + movl $16, %edi + call __cxa_allocate_exception_nid_postfix + movq %rax, FixtureLastObject(%rip) + leaq FixtureVtable+16(%rip), %rdx + movq %rdx, (%rax) + leaq FixtureMessage(%rip), %rdx + movq %rdx, 8(%rax) + movq %rax, %rdi + leaq FixtureErrorType(%rip), %rsi + leaq FixtureDestroy(%rip), %rdx + call __cxa_throw_nid_postfix + ud2 + .cfi_endproc + +.globl GuestInner +GuestInner: + .cfi_startproc + .cfi_personality 0x00, __gxx_personality_v0_nid_postfix + .cfi_lsda 0x00, .Linner_lsda + PROLOGUE +.Linner_call: + call GuestThrow +.Linner_call_end: + ud2 +.Linner_catch: + cmpq $1, %rdx + jne .Linner_bad + movq %rax, %rdi + call __cxa_begin_catch_nid_postfix + incl FixtureCaught(%rip) + WHAT +.Linner_rethrow: + call __cxa_rethrow_nid_postfix +.Linner_rethrow_end: + ud2 +.Linner_cleanup: + movq %rax, -8(%rbp) + call __cxa_end_catch_nid_postfix + incl FixtureGuardDestroyed(%rip) + movq -8(%rbp), %rdi + call _Unwind_Resume_nid_postfix + ud2 +.Linner_bad: + movl $31, %edi + call FixtureFail + ud2 + .cfi_endproc + +.globl GuestOuter +GuestOuter: + .cfi_startproc + .cfi_personality 0x00, __gxx_personality_v0_nid_postfix + .cfi_lsda 0x00, .Louter_lsda + PROLOGUE +.Louter_call: + call GuestInner +.Louter_call_end: + ud2 +.Louter_catch: + cmpq $2, %rdx + jne .Louter_bad + movq %rax, %rdi + call __cxa_begin_catch_nid_postfix + cmpq FixtureLastObject(%rip), %rax + jne .Louter_bad + incl FixtureCaught(%rip) + WHAT + call __cxa_end_catch_nid_postfix + xorl %eax, %eax + leave + .cfi_def_cfa %rsp, 8 + ret +.Louter_bad: + movl $32, %edi + call FixtureFail + ud2 + .cfi_endproc + +.globl GuestStdCapture +GuestStdCapture: + .cfi_startproc + .cfi_personality 0x00, __gxx_personality_v0_nid_postfix + .cfi_lsda 0x00, .Lstd_lsda + PROLOGUE + movq FixtureArgument(%rip), %rdi +.Lstd_call: + call *FixtureThrow(%rip) +.Lstd_call_end: + ud2 +.Lstd_catch: + cmpq $1, %rdx + jne .Lstd_bad + movq %rax, %rdi + call __cxa_begin_catch_nid_postfix + movq %rax, %rdi + call FixtureInspect + call __cxa_end_catch_nid_postfix + leave + .cfi_def_cfa %rsp, 8 + ret +.Lstd_bad: + movl $33, %edi + call FixtureFail + ud2 + .cfi_endproc + +.globl ProbeDestroy +ProbeDestroy: + .cfi_startproc + PROLOGUE + subq $32, %rsp + movq %rdi, %r11 + movq %rsi, %rdi + movq %rdx, %rcx + call *%r11 + leave + .cfi_def_cfa %rsp, 8 + ret + .cfi_endproc +.section .rdata,"dr" +.Linner_lsda: + .byte 0xff, 0x00 + .uleb128 .Linner_types_end-.Linner_types_offset +.Linner_types_offset: + .byte 0x01 + .uleb128 .Linner_calls_end-.Linner_calls +.Linner_calls: + .uleb128 .Linner_call-GuestInner + .uleb128 .Linner_call_end-.Linner_call + .uleb128 .Linner_catch-GuestInner + .uleb128 1 + .uleb128 .Linner_rethrow-GuestInner + .uleb128 .Linner_rethrow_end-.Linner_rethrow + .uleb128 .Linner_cleanup-GuestInner + .uleb128 0 +.Linner_calls_end: + .byte 1, 0 + .quad FixtureErrorType +.Linner_types_end: +.Louter_lsda: + .byte 0xff, 0x00 + .uleb128 .Louter_types_end-.Louter_types_offset +.Louter_types_offset: + .byte 0x01 + .uleb128 .Louter_calls_end-.Louter_calls +.Louter_calls: + .uleb128 .Louter_call-GuestOuter + .uleb128 .Louter_call_end-.Louter_call + .uleb128 .Louter_catch-GuestOuter + .uleb128 1 +.Louter_calls_end: + .byte 1, 1, 2, 0 + .quad FixtureBaseType + .quad FixtureOtherType +.Louter_types_end: +.Lstd_lsda: + .byte 0xff, 0x80 + .uleb128 .Lstd_types_end-.Lstd_types_offset +.Lstd_types_offset: + .byte 0x01 + .uleb128 .Lstd_calls_end-.Lstd_calls +.Lstd_calls: + .uleb128 .Lstd_call-GuestStdCapture + .uleb128 .Lstd_call_end-.Lstd_call + .uleb128 .Lstd_catch-GuestStdCapture + .uleb128 1 +.Lstd_calls_end: + .byte 1, 0 + .quad FixtureStdOutType +.Lstd_types_end: diff --git a/core/libs/tests/GuestMessageDestructorAbi.cpp b/core/libs/tests/GuestMessageDestructorAbi.cpp new file mode 100644 index 00000000000..103ec23e358 --- /dev/null +++ b/core/libs/tests/GuestMessageDestructorAbi.cpp @@ -0,0 +1,121 @@ +#include "prx/libc/include/exceptions/Runtime.hpp" +#include +#include +#include +#include + +using GuestWhat = const char* (APS5_VABI *)(const void*); +using GuestDestroy = void (APS5_VABI *)(void*); +using HostDestroy = void (*)(void*); +using GuestThrowFunction = void (APS5_VABI *)(std::uintptr_t); +struct TypeRecord { const void* vtable; const char* name; const TypeRecord* base; }; +struct Object { const void* vtable; const char* message; }; +struct Table { std::ptrdiff_t offset; const TypeRecord* type; GuestDestroy destroy; GuestDestroy deleteObject; GuestWhat what; }; +struct Message { std::size_t length; std::size_t capacity; std::atomic references; }; +static_assert(sizeof(Object) == 16); + +extern "C" { +extern const unsigned char _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix[]; +extern const unsigned char _ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix[]; +extern const unsigned char _ZTISt12out_of_range_nid_postfix[]; +extern const unsigned char _ZTISt11regex_error_nid_postfix[]; +void APS5_VABI _ZNSt12out_of_rangeC1EPKc_nid_postfix(Object*, const char*); +void APS5_VABI _ZNSt12out_of_rangeC1ERKS__nid_postfix(Object*, const Object*); +void APS5_VABI _ZNSt12out_of_rangeD1Ev_nid_postfix(Object*); +[[noreturn]] void APS5_VABI _ZSt14_Xout_of_rangePKc_nid_postfix(const char*); +[[noreturn]] void APS5_VABI _ZSt13_Xregex_errorNSt15regex_constants10error_typeE_nid_postfix(std::regex_constants::error_type); +int APS5_VABI GuestOuter(); +void APS5_VABI GuestStdCapture(); +void APS5_VABI ProbeDestroy(GuestDestroy, void*, void*); + +TypeRecord FixtureBaseType{_ZTVN10__cxxabiv117__class_type_infoE_nid_postfix + 16, "11FixtureBase", nullptr}; +TypeRecord FixtureErrorType{_ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix + 16, "12FixtureError", &FixtureBaseType}; +TypeRecord FixtureOtherType{_ZTVN10__cxxabiv117__class_type_infoE_nid_postfix + 16, "12FixtureOther", nullptr}; +const void* FixtureStdOutType = _ZTISt12out_of_range_nid_postfix; +GuestThrowFunction FixtureThrow = reinterpret_cast(_ZSt14_Xout_of_rangePKc_nid_postfix); +std::uintptr_t FixtureArgument; +extern const char FixtureMessage[] = "own System-V guest message"; +void* FixtureLastObject = nullptr; +unsigned FixtureDestroyed = 0; +unsigned FixtureGuardDestroyed = 0; +unsigned FixtureCaught = 0; +unsigned FixtureWhatChecked = 0; + +[[noreturn]] void APS5_VABI FixtureFail(unsigned code) { + std::fprintf(stderr, "guest exception failure %u\n", code); + ExitProcess(code); +} +const char* APS5_VABI FixtureWhat(const void* object) { return static_cast(object)->message; } +void APS5_VABI FixtureDestroy(void* object) { + if (object != FixtureLastObject) FixtureFail(11); + ++FixtureDestroyed; +} +Table FixtureVtable{0, &FixtureErrorType, FixtureDestroy, FixtureDestroy, FixtureWhat}; +void APS5_VABI FixtureCheckWhat(const char* message) { + if (!message || std::strcmp(message, FixtureMessage)) FixtureFail(12); + ++FixtureWhatChecked; +} +} + +static Object decoy{}, retained{}; +static GuestDestroy registeredDestructor; +static void* expectedObject; +static void* poison; +static unsigned callbacks; +static bool regularRelease; +static bool keepMessage; + +static Message* MessageHeader(const Object& object) { + return reinterpret_cast(const_cast(object.message)) - 1; +} + +extern "C" void APS5_VABI ObserveDestroy(void* pointer) { + if (pointer != expectedObject || ++callbacks != 1) FixtureFail(40); + ProbeDestroy(registeredDestructor, pointer, poison); + if (static_cast(pointer)->message != nullptr || + !decoy.message || std::strcmp(decoy.message, "unrelated message") || + (keepMessage && MessageHeader(retained)->references.load() != 0)) FixtureFail(41); +} + +extern "C" void APS5_VABI FixtureInspect(void* pointer) { + auto* header = LibcException::FromObject(pointer); + if (header->_pad != 0 || !header->destructor) FixtureFail(42); + expectedObject = pointer; + if (keepMessage) { + _ZNSt12out_of_rangeC1ERKS__nid_postfix(&retained, static_cast(pointer)); + if (MessageHeader(retained)->references.load() != 1) FixtureFail(43); + } + registeredDestructor = reinterpret_cast(header->destructor); + if (!regularRelease) header->destructor = reinterpret_cast(ObserveDestroy); +} + +int main(int argc, char** argv) { + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + if (argc != 2) return 2; + if (std::strcmp(argv[1], "control") == 0) { + if (GuestOuter() != 0 || FixtureDestroyed != 1 || FixtureGuardDestroyed != 1 || + FixtureCaught != 2 || FixtureWhatChecked != 2) return 10; + return 0; + } + const bool regex = std::strstr(argv[1], "regex") != nullptr; + regularRelease = std::strcmp(argv[1], "release") == 0; + keepMessage = std::strstr(argv[1], "unshared") == nullptr; + FixtureArgument = reinterpret_cast(FixtureMessage); + if (regex) { + FixtureStdOutType = _ZTISt11regex_error_nid_postfix; + FixtureThrow = reinterpret_cast(_ZSt13_Xregex_errorNSt15regex_constants10error_typeE_nid_postfix); + FixtureArgument = static_cast(std::regex_constants::error_collate); + } + _ZNSt12out_of_rangeC1EPKc_nid_postfix(&decoy, "unrelated message"); + poison = std::strstr(argv[1], "zero") ? nullptr : &decoy; + GuestStdCapture(); + if (callbacks != (regularRelease ? 0u : 1u) || + (keepMessage && (MessageHeader(retained)->references.load() != 0 || + std::strcmp(retained.message, regex ? "regular expression error" : FixtureMessage))) || + !decoy.message || std::strcmp(decoy.message, "unrelated message")) return 44; + _ZNSt12out_of_rangeD1Ev_nid_postfix(&retained); + _ZNSt12out_of_rangeD1Ev_nid_postfix(&decoy); + if (retained.message || decoy.message) return 45; + std::puts("guest message callback, retained ownership and release: PASS"); + return 0; +} From 05e1cf9d670e9c1b9f284041d81c4409aad3f87f Mon Sep 17 00:00:00 2001 From: Prophet069 <291514246+Prophet069@users.noreply.github.com> Date: Thu, 8 Oct 2026 23:04:06 +0200 Subject: [PATCH 2/2] fix(libc): bridge guest exception vtable callbacks Give guest exception what, non-deleting destructor and deleting destructor slots explicit APS5_VABI types and register guest adapters. Preserve native helpers, object layouts, native exception routing and existing malloc/free ownership. Add mismatched and cleared RCX regressions for plain and message vtables, observing actual libc free calls to reject foreign or duplicate frees. Retain typed guest catch/rethrow and native exception coverage. All 27 targeted CTests pass three repetitions on Windows Release; Linux execution remains unvalidated. --- core/libs/prx/libc/CMakeLists.txt | 10 ++ .../libc/src/exception/StandardExceptions.cpp | 46 ++++---- core/libs/tests/GuestMessageDestructorAbi.S | 3 + core/libs/tests/GuestMessageDestructorAbi.cpp | 109 ++++++++++++++++++ 4 files changed, 148 insertions(+), 20 deletions(-) diff --git a/core/libs/prx/libc/CMakeLists.txt b/core/libs/prx/libc/CMakeLists.txt index 1677e99f434..551ebd176dc 100644 --- a/core/libs/prx/libc/CMakeLists.txt +++ b/core/libs/prx/libc/CMakeLists.txt @@ -387,6 +387,16 @@ if(MINGW) set_tests_properties(guest_message_destructor_${mode} PROPERTIES TIMEOUT 10 ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endforeach() + foreach(kind IN ITEMS message plain) + foreach(operation IN ITEMS what destroy delete) + foreach(register IN ITEMS decoy zero) + set(mode "vtable-${kind}-${operation}-${register}") + add_test(NAME guest_exception_${mode} COMMAND guest_message_destructor_abi_tests ${mode}) + set_tests_properties(guest_exception_${mode} PROPERTIES TIMEOUT 10 + ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") + endforeach() + endforeach() + endforeach() endif() foreach(runtimeLinkFlag IN ITEMS -static-libgcc -static-libstdc++ -static) string(REPLACE "${runtimeLinkFlag}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") diff --git a/core/libs/prx/libc/src/exception/StandardExceptions.cpp b/core/libs/prx/libc/src/exception/StandardExceptions.cpp index f6b2bd2cb66..cef6c4e566d 100644 --- a/core/libs/prx/libc/src/exception/StandardExceptions.cpp +++ b/core/libs/prx/libc/src/exception/StandardExceptions.cpp @@ -9,9 +9,9 @@ struct ExceptionObject { const void* vtable; const char* message; }; struct ExceptionVtable { std::ptrdiff_t offset; const TypeRecord* type; - void (*destroy)(ExceptionObject*); - void (*deleteObject)(ExceptionObject*); - const char* (*what)(const ExceptionObject*); + void (APS5_VABI *destroy)(ExceptionObject*); + void (APS5_VABI *deleteObject)(ExceptionObject*); + const char* (APS5_VABI *what)(const ExceptionObject*); }; struct Message { std::size_t length; @@ -89,6 +89,12 @@ const char* PlainWhat(const ExceptionObject* object) { return name; } const char* MessageWhat(const ExceptionObject* object) { return object->message ? object->message : ""; } +static void APS5_VABI GuestDestroyPlain_nid_no_patch(ExceptionObject* object) { DestroyPlain(object); } +static void APS5_VABI GuestDeletePlain_nid_no_patch(ExceptionObject* object) { DeletePlain(object); } +static const char* APS5_VABI GuestPlainWhat_nid_no_patch(const ExceptionObject* object) { return PlainWhat(object); } +static void APS5_VABI GuestDestroyMessage_nid_no_patch(ExceptionObject* object) { DestroyMessage(object); } +static void APS5_VABI GuestDeleteMessage_nid_no_patch(ExceptionObject* object) { DeleteMessage(object); } +static const char* APS5_VABI GuestMessageWhat_nid_no_patch(const ExceptionObject* object) { return MessageWhat(object); } void Construct(ExceptionObject* object, const ExceptionVtable& table, const char* message) { object->vtable = &table.destroy; object->message = CopyMessage(message); @@ -118,7 +124,7 @@ ExceptionObject* Assign(ExceptionObject* object, const ExceptionObject* source) extern "C" { LibcException::TypeRecord _ZTISt8ios_base_nid_postfix {LibcException::ClassTypeVtable + 2, "St8ios_base", nullptr}; LibcException::TypeRecord _ZTISt9exception_nid_postfix {LibcException::ClassTypeVtable + 2, "St9exception", nullptr}; -LibcException::ExceptionVtable _ZTVSt9exception_nid_postfix {0, &_ZTISt9exception_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt9exception_nid_postfix {0, &_ZTISt9exception_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt9exceptionD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt9exceptionD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt9exceptionD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } @@ -136,7 +142,7 @@ void APS5_VABI _ZNSt9exceptionC1Ev_nid_postfix(LibcException::ExceptionObject* s void APS5_VABI _ZNSt9exceptionC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt9exception_nid_postfix.destroy; } LibcException::TypeRecord _ZTISt8bad_cast_nid_postfix {LibcException::SingleTypeVtable + 2, "St8bad_cast", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt8bad_cast_nid_postfix {0, &_ZTISt8bad_cast_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt8bad_cast_nid_postfix {0, &_ZTISt8bad_cast_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt8bad_castD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt8bad_castD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt8bad_castD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } @@ -145,7 +151,7 @@ void APS5_VABI _ZNSt8bad_castC1Ev_nid_postfix(LibcException::ExceptionObject* se void APS5_VABI _ZNSt8bad_castC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt8bad_cast_nid_postfix.destroy; } LibcException::TypeRecord _ZTISt10bad_typeid_nid_postfix {LibcException::SingleTypeVtable + 2, "St10bad_typeid", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt10bad_typeid_nid_postfix {0, &_ZTISt10bad_typeid_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt10bad_typeid_nid_postfix {0, &_ZTISt10bad_typeid_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt10bad_typeidD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt10bad_typeidD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt10bad_typeidD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } @@ -154,7 +160,7 @@ void APS5_VABI _ZNSt10bad_typeidC1Ev_nid_postfix(LibcException::ExceptionObject* void APS5_VABI _ZNSt10bad_typeidC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt10bad_typeid_nid_postfix.destroy; } LibcException::TypeRecord _ZTISt9bad_alloc_nid_postfix {LibcException::SingleTypeVtable + 2, "St9bad_alloc", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt9bad_alloc_nid_postfix {0, &_ZTISt9bad_alloc_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt9bad_alloc_nid_postfix {0, &_ZTISt9bad_alloc_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt9bad_allocD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt9bad_allocD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt9bad_allocD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } @@ -163,7 +169,7 @@ void APS5_VABI _ZNSt9bad_allocC1Ev_nid_postfix(LibcException::ExceptionObject* s void APS5_VABI _ZNSt9bad_allocC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt9bad_alloc_nid_postfix.destroy; } LibcException::TypeRecord _ZTISt20bad_array_new_length_nid_postfix {LibcException::SingleTypeVtable + 2, "St20bad_array_new_length", &_ZTISt9bad_alloc_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt20bad_array_new_length_nid_postfix {0, &_ZTISt20bad_array_new_length_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt20bad_array_new_length_nid_postfix {0, &_ZTISt20bad_array_new_length_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt20bad_array_new_lengthD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt20bad_array_new_lengthD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt20bad_array_new_lengthD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } @@ -172,7 +178,7 @@ void APS5_VABI _ZNSt20bad_array_new_lengthC1Ev_nid_postfix(LibcException::Except void APS5_VABI _ZNSt20bad_array_new_lengthC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt20bad_array_new_length_nid_postfix.destroy; } LibcException::TypeRecord _ZTISt17bad_function_call_nid_postfix {LibcException::SingleTypeVtable + 2, "St17bad_function_call", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt17bad_function_call_nid_postfix {0, &_ZTISt17bad_function_call_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt17bad_function_call_nid_postfix {0, &_ZTISt17bad_function_call_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt17bad_function_callD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt17bad_function_callD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt17bad_function_callD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } @@ -181,14 +187,14 @@ void APS5_VABI _ZNSt17bad_function_callC1Ev_nid_postfix(LibcException::Exception void APS5_VABI _ZNSt17bad_function_callC2Ev_nid_postfix(LibcException::ExceptionObject* self) { self->vtable = &_ZTVSt17bad_function_call_nid_postfix.destroy; } LibcException::TypeRecord _ZTISt12bad_weak_ptr_nid_postfix {LibcException::SingleTypeVtable + 2, "St12bad_weak_ptr", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt12bad_weak_ptr_nid_postfix {0, &_ZTISt12bad_weak_ptr_nid_postfix, LibcException::DestroyPlain, LibcException::DeletePlain, LibcException::PlainWhat}; +LibcException::ExceptionVtable _ZTVSt12bad_weak_ptr_nid_postfix {0, &_ZTISt12bad_weak_ptr_nid_postfix, LibcException::GuestDestroyPlain_nid_no_patch, LibcException::GuestDeletePlain_nid_no_patch, LibcException::GuestPlainWhat_nid_no_patch}; void APS5_VABI _ZNSt12bad_weak_ptrD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt12bad_weak_ptrD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyPlain(self); } void APS5_VABI _ZNSt12bad_weak_ptrD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeletePlain(self); } const char* APS5_VABI _ZNKSt12bad_weak_ptr4whatEv_nid_postfix(const LibcException::ExceptionObject* self) { return LibcException::PlainWhat(self); } LibcException::TypeRecord _ZTISt11logic_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St11logic_error", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt11logic_error_nid_postfix {0, &_ZTISt11logic_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt11logic_error_nid_postfix {0, &_ZTISt11logic_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt11logic_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11logic_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11logic_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -200,7 +206,7 @@ void APS5_VABI _ZNSt11logic_errorC2ERKS__nid_postfix(LibcException::ExceptionObj LibcException::ExceptionObject* APS5_VABI _ZNSt11logic_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt13runtime_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St13runtime_error", &_ZTISt9exception_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt13runtime_error_nid_postfix {0, &_ZTISt13runtime_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt13runtime_error_nid_postfix {0, &_ZTISt13runtime_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt13runtime_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt13runtime_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt13runtime_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -212,7 +218,7 @@ void APS5_VABI _ZNSt13runtime_errorC2ERKS__nid_postfix(LibcException::ExceptionO LibcException::ExceptionObject* APS5_VABI _ZNSt13runtime_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt16invalid_argument_nid_postfix {LibcException::SingleTypeVtable + 2, "St16invalid_argument", &_ZTISt11logic_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt16invalid_argument_nid_postfix {0, &_ZTISt16invalid_argument_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt16invalid_argument_nid_postfix {0, &_ZTISt16invalid_argument_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt16invalid_argumentD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt16invalid_argumentD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt16invalid_argumentD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -224,7 +230,7 @@ void APS5_VABI _ZNSt16invalid_argumentC2ERKS__nid_postfix(LibcException::Excepti LibcException::ExceptionObject* APS5_VABI _ZNSt16invalid_argumentaSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt12out_of_range_nid_postfix {LibcException::SingleTypeVtable + 2, "St12out_of_range", &_ZTISt11logic_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt12out_of_range_nid_postfix {0, &_ZTISt12out_of_range_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt12out_of_range_nid_postfix {0, &_ZTISt12out_of_range_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt12out_of_rangeD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12out_of_rangeD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12out_of_rangeD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -236,7 +242,7 @@ void APS5_VABI _ZNSt12out_of_rangeC2ERKS__nid_postfix(LibcException::ExceptionOb LibcException::ExceptionObject* APS5_VABI _ZNSt12out_of_rangeaSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt12domain_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St12domain_error", &_ZTISt11logic_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt12domain_error_nid_postfix {0, &_ZTISt12domain_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt12domain_error_nid_postfix {0, &_ZTISt12domain_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt12domain_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12domain_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12domain_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -248,7 +254,7 @@ void APS5_VABI _ZNSt12domain_errorC2ERKS__nid_postfix(LibcException::ExceptionOb LibcException::ExceptionObject* APS5_VABI _ZNSt12domain_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt12length_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St12length_error", &_ZTISt11logic_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt12length_error_nid_postfix {0, &_ZTISt12length_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt12length_error_nid_postfix {0, &_ZTISt12length_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt12length_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12length_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12length_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -260,7 +266,7 @@ void APS5_VABI _ZNSt12length_errorC2ERKS__nid_postfix(LibcException::ExceptionOb LibcException::ExceptionObject* APS5_VABI _ZNSt12length_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt12system_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St12system_error", &_ZTISt13runtime_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt12system_error_nid_postfix {0, &_ZTISt12system_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt12system_error_nid_postfix {0, &_ZTISt12system_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt12system_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12system_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt12system_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -270,7 +276,7 @@ void APS5_VABI _ZNSt12system_errorC2ERKS__nid_postfix(LibcException::ExceptionOb LibcException::ExceptionObject* APS5_VABI _ZNSt12system_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt11regex_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St11regex_error", &_ZTISt13runtime_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt11regex_error_nid_postfix {0, &_ZTISt11regex_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt11regex_error_nid_postfix {0, &_ZTISt11regex_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt11regex_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11regex_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11regex_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } @@ -280,13 +286,13 @@ void APS5_VABI _ZNSt11regex_errorC2ERKS__nid_postfix(LibcException::ExceptionObj LibcException::ExceptionObject* APS5_VABI _ZNSt11regex_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source) { return LibcException::Assign(self, source); } LibcException::TypeRecord _ZTISt11range_error_nid_postfix {LibcException::SingleTypeVtable + 2, "St11range_error", &_ZTISt13runtime_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVSt11range_error_nid_postfix {0, &_ZTISt11range_error_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVSt11range_error_nid_postfix {0, &_ZTISt11range_error_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt11range_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11range_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt11range_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } LibcException::TypeRecord _ZTINSt8ios_base7failureE_nid_postfix {LibcException::SingleTypeVtable + 2, "NSt8ios_base7failureE", &_ZTISt12system_error_nid_postfix}; -LibcException::ExceptionVtable _ZTVNSt8ios_base7failureE_nid_postfix {0, &_ZTINSt8ios_base7failureE_nid_postfix, LibcException::DestroyMessage, LibcException::DeleteMessage, LibcException::MessageWhat}; +LibcException::ExceptionVtable _ZTVNSt8ios_base7failureE_nid_postfix {0, &_ZTINSt8ios_base7failureE_nid_postfix, LibcException::GuestDestroyMessage_nid_no_patch, LibcException::GuestDeleteMessage_nid_no_patch, LibcException::GuestMessageWhat_nid_no_patch}; void APS5_VABI _ZNSt8ios_base7failureD1Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt8ios_base7failureD2Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DestroyMessage(self); } void APS5_VABI _ZNSt8ios_base7failureD0Ev_nid_postfix(LibcException::ExceptionObject* self) { LibcException::DeleteMessage(self); } diff --git a/core/libs/tests/GuestMessageDestructorAbi.S b/core/libs/tests/GuestMessageDestructorAbi.S index 580843d1710..57ac11e8277 100644 --- a/core/libs/tests/GuestMessageDestructorAbi.S +++ b/core/libs/tests/GuestMessageDestructorAbi.S @@ -11,6 +11,7 @@ .macro WHAT movq %rax, %rdi movq (%rax), %r11 + xorl %ecx, %ecx call *16(%r11) movq %rax, %rdi call FixtureCheckWhat @@ -125,6 +126,8 @@ GuestStdCapture: ud2 .cfi_endproc +.globl ProbeWhat +ProbeWhat: .globl ProbeDestroy ProbeDestroy: .cfi_startproc diff --git a/core/libs/tests/GuestMessageDestructorAbi.cpp b/core/libs/tests/GuestMessageDestructorAbi.cpp index 103ec23e358..edf1e8cd417 100644 --- a/core/libs/tests/GuestMessageDestructorAbi.cpp +++ b/core/libs/tests/GuestMessageDestructorAbi.cpp @@ -1,6 +1,7 @@ #include "prx/libc/include/exceptions/Runtime.hpp" #include #include +#include #include #include @@ -27,6 +28,9 @@ void APS5_VABI _ZNSt12out_of_rangeD1Ev_nid_postfix(Object*); int APS5_VABI GuestOuter(); void APS5_VABI GuestStdCapture(); void APS5_VABI ProbeDestroy(GuestDestroy, void*, void*); +const char* APS5_VABI ProbeWhat(GuestWhat, const void*, const void*); +void APS5_VABI _ZNSt8bad_castC1Ev_nid_postfix(Object*); +void APS5_VABI _ZNSt9bad_allocC1Ev_nid_postfix(Object*); TypeRecord FixtureBaseType{_ZTVN10__cxxabiv117__class_type_infoE_nid_postfix + 16, "11FixtureBase", nullptr}; TypeRecord FixtureErrorType{_ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix + 16, "12FixtureError", &FixtureBaseType}; @@ -64,6 +68,104 @@ static void* poison; static unsigned callbacks; static bool regularRelease; static bool keepMessage; +static const char* expectedMessage = FixtureMessage; + +using NativeFree = void (*)(void*); +static NativeFree originalFree; +static std::uintptr_t* freeSlot; +static void* watchedObject; +static void* watchedMessage; +static void* foreignObject; +static void* foreignMessage; +static unsigned objectFrees, messageFrees; + +static void TrackedFree(void* pointer) { + if (pointer && (pointer == foreignObject || pointer == foreignMessage)) FixtureFail(50); + if (pointer && pointer == watchedObject && ++objectFrees != 1) FixtureFail(51); + if (pointer && pointer == watchedMessage && ++messageFrees != 1) FixtureFail(52); + originalFree(pointer); +} + +static void ReplaceFree(std::uintptr_t address) { + DWORD protection; + if (!VirtualProtect(freeSlot, sizeof(*freeSlot), PAGE_READWRITE, &protection)) FixtureFail(53); + *freeSlot = address; + DWORD ignored; + if (!VirtualProtect(freeSlot, sizeof(*freeSlot), protection, &ignored)) FixtureFail(54); +} + +static void TrackFree() { + auto* image = reinterpret_cast(GetModuleHandleW(L"libc.prx")); + if (!image) FixtureFail(55); + auto* dos = reinterpret_cast(image); + auto* nt = reinterpret_cast(image + dos->e_lfanew); + auto* imports = reinterpret_cast(image + + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + for (; imports->Name; ++imports) { + if (!imports->OriginalFirstThunk) continue; + auto* names = reinterpret_cast(image + imports->OriginalFirstThunk); + auto* slots = reinterpret_cast(image + imports->FirstThunk); + for (; names->u1.AddressOfData; ++names, ++slots) { + if (IMAGE_SNAP_BY_ORDINAL64(names->u1.Ordinal)) continue; + auto* name = reinterpret_cast(image + names->u1.AddressOfData); + if (std::strcmp(name->Name, "free")) continue; + freeSlot = reinterpret_cast(&slots->u1.Function); + originalFree = reinterpret_cast(*freeSlot); + ReplaceFree(reinterpret_cast(TrackedFree)); + return; + } + } + FixtureFail(56); +} + +static int TestVtable(const char* mode) { + const bool plain = std::strstr(mode, "plain") != nullptr; + const bool deleting = std::strstr(mode, "delete") != nullptr; + const bool destroying = deleting || std::strstr(mode, "destroy") != nullptr; + auto* actual = static_cast(std::malloc(sizeof(Object))); + auto* other = static_cast(std::malloc(sizeof(Object))); + if (!actual || !other) FixtureFail(57); + actual->message = other->message = nullptr; + if (plain) { + _ZNSt9bad_allocC1Ev_nid_postfix(actual); + _ZNSt8bad_castC1Ev_nid_postfix(other); + } else { + _ZNSt12out_of_rangeC1EPKc_nid_postfix(actual, "actual virtual message"); + _ZNSt12out_of_rangeC1EPKc_nid_postfix(other, "unrelated virtual message"); + } + const Object originalOther = *other; + watchedObject = actual; + watchedMessage = plain ? nullptr : reinterpret_cast(const_cast(actual->message)) - 1; + foreignObject = other; + foreignMessage = plain ? nullptr : reinterpret_cast(const_cast(other->message)) - 1; + TrackFree(); + auto* unused = std::strstr(mode, "zero") ? nullptr : other; + GuestDestroy destroy, deleteObject; + GuestWhat what; + auto* slots = static_cast(actual->vtable); + std::memcpy(&destroy, slots, sizeof(destroy)); + std::memcpy(&deleteObject, slots + sizeof(void*), sizeof(deleteObject)); + std::memcpy(&what, slots + 2 * sizeof(void*), sizeof(what)); + if (destroying) { + ProbeDestroy(deleting ? deleteObject : destroy, actual, unused); + if (objectFrees != (deleting ? 1u : 0u) || messageFrees != (plain ? 0u : 1u)) FixtureFail(58); + if (!deleting && actual->message) FixtureFail(59); + } else { + const char* result = ProbeWhat(what, actual, unused); + if (!result || std::strcmp(result, plain ? "std::bad_alloc" : "actual virtual message") || + objectFrees || messageFrees) FixtureFail(60); + } + if (other->vtable != originalOther.vtable || other->message != originalOther.message || + (!plain && std::strcmp(other->message, "unrelated virtual message"))) FixtureFail(61); + ReplaceFree(reinterpret_cast(originalFree)); + if (!plain) { + if (!deleting) _ZNSt12out_of_rangeD1Ev_nid_postfix(actual); + _ZNSt12out_of_rangeD1Ev_nid_postfix(other); + } + if (!deleting) std::free(actual); + std::free(other); + return 0; +} static Message* MessageHeader(const Object& object) { return reinterpret_cast(const_cast(object.message)) - 1; @@ -81,6 +183,11 @@ extern "C" void APS5_VABI FixtureInspect(void* pointer) { auto* header = LibcException::FromObject(pointer); if (header->_pad != 0 || !header->destructor) FixtureFail(42); expectedObject = pointer; + GuestWhat what; + std::memcpy(&what, static_cast(static_cast(pointer)->vtable) + + 2 * sizeof(void*), sizeof(what)); + const char* message = ProbeWhat(what, pointer, poison); + if (!message || std::strcmp(message, expectedMessage)) FixtureFail(62); if (keepMessage) { _ZNSt12out_of_rangeC1ERKS__nid_postfix(&retained, static_cast(pointer)); if (MessageHeader(retained)->references.load() != 1) FixtureFail(43); @@ -92,6 +199,7 @@ extern "C" void APS5_VABI FixtureInspect(void* pointer) { int main(int argc, char** argv) { SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); if (argc != 2) return 2; + if (std::strncmp(argv[1], "vtable-", 7) == 0) return TestVtable(argv[1]); if (std::strcmp(argv[1], "control") == 0) { if (GuestOuter() != 0 || FixtureDestroyed != 1 || FixtureGuardDestroyed != 1 || FixtureCaught != 2 || FixtureWhatChecked != 2) return 10; @@ -102,6 +210,7 @@ int main(int argc, char** argv) { keepMessage = std::strstr(argv[1], "unshared") == nullptr; FixtureArgument = reinterpret_cast(FixtureMessage); if (regex) { + expectedMessage = "regular expression error"; FixtureStdOutType = _ZTISt11regex_error_nid_postfix; FixtureThrow = reinterpret_cast(_ZSt13_Xregex_errorNSt15regex_constants10error_typeE_nid_postfix); FixtureArgument = static_cast(std::regex_constants::error_collate);