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; + +}