From 3e34f0493f9e7f766cd1eeb691d684eabd76bb29 Mon Sep 17 00:00:00 2001 From: vagnertxr Date: Tue, 8 Sep 2026 17:11:30 -0300 Subject: [PATCH] Decompile __init_cpp_exceptions.cpp Matches and links the last unwritten Runtime unit, taking the DOL to 508 linked files. Three things the unit needs beyond the obvious translation: - cflags_runtime carries no OpenRVL include paths, so ExtabIndexInfo and the __register_fragment/__unregister_fragment prototypes are declared locally rather than pulled from . - __register_fragment takes the TOC in r2. An `asm` helper function is never inlined by mwcc and would emit its own symbol, so the value is read with an inline `asm` block into a `register` local, which lowers to the single `mr r4, r2` the target has. - The unit owns 8 bytes of .sdata, and a lone `int` leaves the section 4 bytes short, shifting everything after it. Pairing the id with its trailing word reproduces the section byte-for-byte. The .ctors$10 and .dtors$15 entries are referenced only as data, so the linker discards them unless they are kept alive; both are added to force_active for the DOL. Verified: `ninja` reports 127 files OK. Co-Authored-By: Claude Opus 5 --- config/RSBE01_02/config.yml | 6 +++ configure.py | 2 +- .../__init_cpp_exceptions.cpp | 53 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp diff --git a/config/RSBE01_02/config.yml b/config/RSBE01_02/config.yml index 8fb15308c..19149db1c 100644 --- a/config/RSBE01_02/config.yml +++ b/config/RSBE01_02/config.yml @@ -6,6 +6,12 @@ symbols: config/RSBE01_02/symbols.txt mw_comment_version: 14 # GC 3.0a5.2 linker quick_analysis: true # Faster reruns after full analysis +# The .ctors$10/.dtors$15 entries that reference these are data-only, so the +# linker drops them unless the symbols are kept alive explicitly. +force_active: +- __init_cpp_exceptions_reference +- __fini_cpp_exceptions_reference + extract: - symbol: HomeBtnIcon binary: HomeBtnIcon.bin diff --git a/configure.py b/configure.py index d44984a5b..1edfd4844 100755 --- a/configure.py +++ b/configure.py @@ -277,7 +277,7 @@ def MatchingFor(*versions): "host": False, "objects": [ Object(NonMatching, "Runtime.PPCEABI.H/global_destructor_chain.c"), - Object(NonMatching, "Runtime.PPCEABI.H/__init_cpp_exceptions.cpp"), + Object(Matching, "Runtime.PPCEABI.H/__init_cpp_exceptions.cpp"), ], }, # The DOL diff --git a/src/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp b/src/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp new file mode 100644 index 000000000..74ae60a24 --- /dev/null +++ b/src/Runtime.PPCEABI.H/__init_cpp_exceptions.cpp @@ -0,0 +1,53 @@ +extern "C" { + +typedef struct ExtabIndexInfo { + unsigned long size; + struct ExtabIndexInfo* extab; + unsigned long extabend; +} ExtabIndexInfo; + +extern const ExtabIndexInfo _eti_init_info[]; + +int __register_fragment(const ExtabIndexInfo* info, char* toc); +void __unregister_fragment(int fragmentID); +void __destroy_global_chain(void); + +// The unit owns 8 bytes of .sdata but only the first word is ever read, and a +// lone int leaves the section 4 bytes short of the split. Pairing the id with +// its trailing word reproduces the section exactly. +static struct { + int id; + int pad; +} fragment = { -2, 0 }; + +void __init_cpp_exceptions(void) +{ + // __register_fragment takes the TOC in r2, which has no C spelling. + register char* toc; + if (fragment.id == -2) { + asm { mr toc, r2 } + fragment.id = __register_fragment(_eti_init_info, toc); + } +} + +void __fini_cpp_exceptions(void) +{ + if (fragment.id != -2) { + __unregister_fragment(fragment.id); + fragment.id = -2; + } +} + +#pragma section ".ctors$10" +__declspec(section ".ctors$10") + extern void* const __init_cpp_exceptions_reference = (void*) __init_cpp_exceptions; + +#pragma section ".dtors$10" +__declspec(section ".dtors$10") __declspec(weak) + extern void* const __destroy_global_chain_reference = (void*) __destroy_global_chain; + +#pragma section ".dtors$15" +__declspec(section ".dtors$15") + extern void* const __fini_cpp_exceptions_reference = (void*) __fini_cpp_exceptions; + +}