From 019ca3522b78c21d610735097440e7b227c87d52 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 25 Apr 2026 15:35:25 -0700 Subject: [PATCH 1/4] Revert hacks --- configure.py | 2 + .../PowerPC_EABI_Support/Runtime/exception.h | 8 ++-- src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp | 47 ------------------- src/Runtime.PPCEABI.H/New.cp | 47 +------------------ 4 files changed, 8 insertions(+), 96 deletions(-) diff --git a/configure.py b/configure.py index efeb13bc6a..506f56f115 100755 --- a/configure.py +++ b/configure.py @@ -167,6 +167,7 @@ config.binutils_tag = "2.42-1" config.compilers_tag = "20250812" config.dtk_tag = "v1.8.3" +config.objdiff_path = Path("build/tools/objdiff-cli.exe") config.objdiff_tag = "v3.6.1" config.sjiswrap_tag = "v1.2.2" config.wibo_tag = "1.0.0-beta.5" @@ -1196,6 +1197,7 @@ def link_order_callback(module_id: int, objects: List[str]) -> List[str]: config.progress_each_module = args.verbose # Optional extra arguments to `objdiff-cli report generate` config.progress_report_args = [ + "--deduplicate", # Marks relocations as mismatching if the target value is different # Default is "functionRelocDiffs=none", which is most lenient "--config", "functionRelocDiffs=none", diff --git a/include/PowerPC_EABI_Support/Runtime/exception.h b/include/PowerPC_EABI_Support/Runtime/exception.h index f6f28e71a4..dad23d18fa 100644 --- a/include/PowerPC_EABI_Support/Runtime/exception.h +++ b/include/PowerPC_EABI_Support/Runtime/exception.h @@ -7,14 +7,16 @@ namespace std { class exception { public: + exception() {} virtual ~exception() {} - virtual const char* what() const; + virtual const char* what() const { return "exception"; } }; class bad_exception : public exception { public: - virtual ~bad_exception(); - virtual const char* what() const; + bad_exception() {} + virtual ~bad_exception() {} + virtual const char* what() const { return "bad_exception"; } }; typedef void (*unexpected_handler)(); diff --git a/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp b/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp index 151d89a917..9ed3745d7f 100644 --- a/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp +++ b/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp @@ -694,13 +694,6 @@ void ExPPC_ThrowHandler(ThrowContext* context) * @note Address: N/A * @note Size: 0x144 */ -extern "C" const char s_std_bad_exception[]; -extern "C" const char s_std_exception[]; -extern "C" const char s_bad_exception[0x20]; - -extern "C" void* __RTTI__Q23std9exception_gecko[]; -extern "C" void* s_bad_exception_rtti[]; -extern "C" void* __RTTI__Q23std13bad_exception[]; struct BadExceptionStorage { void* vtable; }; @@ -709,31 +702,6 @@ extern "C" void __dt__Q23std13bad_exceptionFv(std::bad_exception*, s16); extern "C" void* __vt__Q23std9exception[]; extern "C" void* __vt__Q23std13bad_exception[]; -/* - * TODO: Remove this note block once linkage has been resolved. - * - * Current blocker in this unit: - * - Gecko_ExceptionPPC.cp now rebuilds at 100% code/data on latest main, but - * flipping the unit to `Matching` still fails final main.dol checksum - * - that means this unit is now a pure hidden-link / object-metadata blocker; - * the remaining miss is no longer in visible source code shape - * - * Most useful result so far: - * - current latest-main source does now match __unexpected at 100% again: the - * keepable fix was to seed `stdExceptionBadExceptionType` from - * `unexpectedTypes`, then derive `badExceptionType` back from that pointer - * instead of initializing `badExceptionType` directly from the array base - * - that source shape changes only the one live instruction seam at the second - * ExPPC_IsInSpecification compare, turning source `addi r3, r30, 0` into the - * target `mr r3, r30` - * - a fresh Matching flip on this fixed source still fails final main.dol - * checksum, so the remaining blocker is no longer C code shape inside - * `__unexpected`; it is hidden object/linkage metadata elsewhere in the unit - * - older flat probes are still worth remembering: a dedicated - * `compareBadExceptionType` local and fully collapsed direct-offset pointer - * initializers both stayed flat before the winning pointer-derivation shape - */ - /** * @note Address: N/A * @note Size: 0x1B4 @@ -781,15 +749,6 @@ extern void __unexpected(CatchInfo* catchinfo) terminate(); } -namespace std { -bad_exception::~bad_exception() {} -const char* bad_exception::what() const; -} // namespace std - -extern "C" const char s_std_bad_exception[] = "std::bad_exception"; -extern "C" const char s_std_exception[] = "std::exception"; -extern "C" const char s_bad_exception[0x20] = "bad_exception\0\0\0exception"; - /** * @note Address: N/A * @note Size: 0x50C @@ -1141,9 +1100,3 @@ int __register_fragment(struct __eti_init_info* info, char* TOC) return -1; } - -const char* std::bad_exception::what() const { return s_bad_exception; } - -extern "C" void* __RTTI__Q23std9exception_gecko[] = { (void*)s_std_exception, 0 }; -extern "C" void* s_bad_exception_rtti[] = { __RTTI__Q23std9exception_gecko, 0, 0 }; -extern "C" void* __RTTI__Q23std13bad_exception[] = { (void*)s_std_bad_exception, s_bad_exception_rtti }; diff --git a/src/Runtime.PPCEABI.H/New.cp b/src/Runtime.PPCEABI.H/New.cp index 325b4d01c5..4e5a9ac6a7 100644 --- a/src/Runtime.PPCEABI.H/New.cp +++ b/src/Runtime.PPCEABI.H/New.cp @@ -1,54 +1,9 @@ #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/alloc.h" #include "PowerPC_EABI_Support/Runtime/New.h" - -namespace std { -class exception { -public: - virtual ~exception(); - virtual const char* what() const; -}; -} // namespace std - -/* - * TODO: Remove this note block once linkage has been resolved. - * - * Current blocker in this unit: - * - baseline source already matches the target destructor / what() code shape - * - final linkage is still blocked by constant / RTTI object-source shape, not control flow - * - live MWCC output materializes an extra private std::exception RTTI/string blob - * alongside the authored _new symbols the target object wants - * - * Most useful probe so far: - * - keep named s_std_exception_new / s_exception plus an out-of-line - * exception::~exception() in this file - * - compile this unit with -RTTI off - * - that drops the extra private RTTI blob while preserving the target code shape - * - a fresh follow-up naming the two string literals directly in namespace std - * is not keepable: MWCC duplicates `"std::exception"` into a second local - * rodata blob and grows `.rodata` from `0x1A` to `0x2B` instead of matching - * the target's padded `0x20` layout - * - * Why this is not keepable yet: - * - promoting that probe to Matching still failed final main.dol checksum - * - promoting New.cp together with Gecko_ExceptionPPC.cp on latest main still - * fails only at the final checksum, so this is not just one unresolved - * exception-runtime cluster seam between those two units - * - so there is still at least one remaining object-shape / linkage detail beyond - * the obvious duplicate RTTI emission - */ +#include "PowerPC_EABI_Support/Runtime/exception.h" inline void operator delete(void* arg0) throw() { if (arg0 != 0) { free(arg0); } } - -extern "C" const char s_std_exception_new[] = "std::exception"; -extern "C" const char s_exception[] = "exception"; -extern "C" void* __RTTI__Q23std9exception[] = { (void*)s_std_exception_new, 0 }; - -namespace std { -exception::~exception() {} -const char* exception::what() const { return s_exception; } - -} // namespace std From 8273edaff30a9ac299bd33c2925010b9a6e265f6 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 25 Apr 2026 16:15:40 -0700 Subject: [PATCH 2/4] Avoid fakematch on MSL --- .../PowerPC_EABI_Support/Runtime/exception.h | 2 +- src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp | 26 ++++++++++--------- src/Runtime.PPCEABI.H/New.cp | 17 ++++++++++-- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/include/PowerPC_EABI_Support/Runtime/exception.h b/include/PowerPC_EABI_Support/Runtime/exception.h index dad23d18fa..c19d4f4522 100644 --- a/include/PowerPC_EABI_Support/Runtime/exception.h +++ b/include/PowerPC_EABI_Support/Runtime/exception.h @@ -16,7 +16,7 @@ class bad_exception : public exception { public: bad_exception() {} virtual ~bad_exception() {} - virtual const char* what() const { return "bad_exception"; } + virtual const char* what() const { return "bad_exception\0\0"; } }; typedef void (*unexpected_handler)(); diff --git a/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp b/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp index 9ed3745d7f..9a5fd59621 100644 --- a/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp +++ b/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp @@ -304,6 +304,14 @@ static inline int ExPPC_IsInSpecification(char* extype, ex_specification* spec) char* ExPPC_PopStackFrame(ThrowContext* context, MWExceptionInfo* info); void ExPPC_FindExceptionRecord(char* returnaddr, MWExceptionInfo* info); void ExPPC_ThrowHandler(ThrowContext* context); +extern "C" void __dt__Q23std13bad_exceptionFv(std::bad_exception*, s16); + +struct BadExceptionStorage { + void* vtable; +}; + +extern "C" void* __vt__Q23std9exception[]; +extern "C" void* __vt__Q23std13bad_exception[]; /** * @note Address: N/A @@ -690,18 +698,6 @@ void ExPPC_ThrowHandler(ThrowContext* context) } } -/** - * @note Address: N/A - * @note Size: 0x144 - */ -struct BadExceptionStorage { - void* vtable; -}; - -extern "C" void __dt__Q23std13bad_exceptionFv(std::bad_exception*, s16); -extern "C" void* __vt__Q23std9exception[]; -extern "C" void* __vt__Q23std13bad_exception[]; - /** * @note Address: N/A * @note Size: 0x1B4 @@ -749,6 +745,12 @@ extern void __unexpected(CatchInfo* catchinfo) terminate(); } +static void ExPPC_EmitBadException() +{ + std::bad_exception badException; + badException.what(); +} + /** * @note Address: N/A * @note Size: 0x50C diff --git a/src/Runtime.PPCEABI.H/New.cp b/src/Runtime.PPCEABI.H/New.cp index 4e5a9ac6a7..2778097f86 100644 --- a/src/Runtime.PPCEABI.H/New.cp +++ b/src/Runtime.PPCEABI.H/New.cp @@ -1,9 +1,22 @@ #include "PowerPC_EABI_Support/Msl/MSL_C/MSL_Common/alloc.h" #include "PowerPC_EABI_Support/Runtime/New.h" -#include "PowerPC_EABI_Support/Runtime/exception.h" -inline void operator delete(void* arg0) throw() { +namespace std { +class exception { +public: + virtual ~exception(); + virtual const char* what() const; +}; +} // namespace std + +__declspec(weak) void operator delete(void* arg0) throw() +{ if (arg0 != 0) { free(arg0); } } + +namespace std { +exception::~exception() {} +const char* exception::what() const { return "exception"; } +} // namespace std From 8811f3cf9fa34e8e420bbb822df9e1487e0a4fcc Mon Sep 17 00:00:00 2001 From: Zachary Canann Date: Sat, 25 Apr 2026 16:16:54 -0700 Subject: [PATCH 3/4] Update configure.py --- configure.py | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.py b/configure.py index 506f56f115..a2256c142e 100755 --- a/configure.py +++ b/configure.py @@ -167,7 +167,6 @@ config.binutils_tag = "2.42-1" config.compilers_tag = "20250812" config.dtk_tag = "v1.8.3" -config.objdiff_path = Path("build/tools/objdiff-cli.exe") config.objdiff_tag = "v3.6.1" config.sjiswrap_tag = "v1.2.2" config.wibo_tag = "1.0.0-beta.5" From b89c161604e6e7ab32d7efae24cf2c4574630e81 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 25 Apr 2026 17:05:39 -0700 Subject: [PATCH 4/4] Fix manual vtable hacks --- configure.py | 4 +- .../PowerPC_EABI_Support/Runtime/exception.h | 2 +- src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp | 43 ++----------------- 3 files changed, 7 insertions(+), 42 deletions(-) diff --git a/configure.py b/configure.py index a2256c142e..03a7f52a00 100755 --- a/configure.py +++ b/configure.py @@ -945,8 +945,8 @@ def MatchingFor(*versions): Object( Matching, "Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp", - mw_version="GC/2.7", - extra_cflags=["-char signed", "-RTTI on"], + mw_version="GC/2.6", + extra_cflags=["-char signed", "-RTTI on", "-str reuse,nopool,readonly"], extab_padding=[0x02, 0x55], ), Object( diff --git a/include/PowerPC_EABI_Support/Runtime/exception.h b/include/PowerPC_EABI_Support/Runtime/exception.h index c19d4f4522..dad23d18fa 100644 --- a/include/PowerPC_EABI_Support/Runtime/exception.h +++ b/include/PowerPC_EABI_Support/Runtime/exception.h @@ -16,7 +16,7 @@ class bad_exception : public exception { public: bad_exception() {} virtual ~bad_exception() {} - virtual const char* what() const { return "bad_exception\0\0"; } + virtual const char* what() const { return "bad_exception"; } }; typedef void (*unexpected_handler)(); diff --git a/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp b/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp index 9a5fd59621..b51cbed489 100644 --- a/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp +++ b/src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp @@ -304,14 +304,6 @@ static inline int ExPPC_IsInSpecification(char* extype, ex_specification* spec) char* ExPPC_PopStackFrame(ThrowContext* context, MWExceptionInfo* info); void ExPPC_FindExceptionRecord(char* returnaddr, MWExceptionInfo* info); void ExPPC_ThrowHandler(ThrowContext* context); -extern "C" void __dt__Q23std13bad_exceptionFv(std::bad_exception*, s16); - -struct BadExceptionStorage { - void* vtable; -}; - -extern "C" void* __vt__Q23std9exception[]; -extern "C" void* __vt__Q23std13bad_exception[]; /** * @note Address: N/A @@ -704,53 +696,26 @@ void ExPPC_ThrowHandler(ThrowContext* context) */ extern void __unexpected(CatchInfo* catchinfo) { - static const char unexpectedTypes[0x54] = "!bad_exception!!\0\0\0\0" - "!std::exception!!std::bad_exception!!\0\0\0" - "!std::bad_exception!!\0\0"; - char* badExceptionType; - char* stdExceptionBadExceptionType; - char* stdBadExceptionType; ex_specification* unexp = (ex_specification*)catchinfo->stacktop; - stdExceptionBadExceptionType = (char*)unexpectedTypes; - stdExceptionBadExceptionType += sizeof("!bad_exception!!\0\0\0"); - badExceptionType = stdExceptionBadExceptionType; - badExceptionType -= sizeof("!bad_exception!!\0\0\0"); - stdBadExceptionType = stdExceptionBadExceptionType; - stdBadExceptionType += sizeof("!std::exception!!std::bad_exception!!\0\0"); - #pragma exception_magic // allow access to __exception_magic in try/catch blocks try { unexpected(); } catch (...) { - BadExceptionStorage badException; - if (ExPPC_IsInSpecification((char*)((CatchInfo*)&__exception_magic)->typeinfo, unexp)) { throw; } - if (ExPPC_IsInSpecification(badExceptionType, unexp)) { - badException.vtable = __vt__Q23std9exception; - badException.vtable = __vt__Q23std13bad_exception; - __throw((char*)stdExceptionBadExceptionType, &badException, __dt__Q23std13bad_exceptionFv); + if (ExPPC_IsInSpecification("!bad_exception!!", unexp)) { + throw bad_exception(); } - if (ExPPC_IsInSpecification(stdBadExceptionType, unexp)) { - BadExceptionStorage stdBadException; - - stdBadException.vtable = __vt__Q23std9exception; - stdBadException.vtable = __vt__Q23std13bad_exception; - __throw((char*)stdExceptionBadExceptionType, &stdBadException, __dt__Q23std13bad_exceptionFv); + if (ExPPC_IsInSpecification("!std::bad_exception!!", unexp)) { + throw bad_exception(); } } terminate(); } -static void ExPPC_EmitBadException() -{ - std::bad_exception badException; - badException.what(); -} - /** * @note Address: N/A * @note Size: 0x50C