Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -1196,6 +1196,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",
Expand Down
8 changes: 5 additions & 3 deletions include/PowerPC_EABI_Support/Runtime/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)();
Expand Down
88 changes: 4 additions & 84 deletions src/Runtime.PPCEABI.H/Gecko_ExceptionPPC.cp
Original file line number Diff line number Diff line change
Expand Up @@ -690,106 +690,32 @@ 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;
};

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
*/
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();
}

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
Expand Down Expand Up @@ -1141,9 +1067,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 };
42 changes: 5 additions & 37 deletions src/Runtime.PPCEABI.H/New.cp
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,19 @@
namespace std {
class exception {
public:
virtual ~exception();
virtual const char* what() const;
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
*/

inline void operator delete(void* arg0) throw() {
__declspec(weak) 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; }

const char* exception::what() const { return "exception"; }
} // namespace std
Loading