diff --git a/src/register.cpp b/src/register.cpp index 5e5925e..b5fc7d5 100644 --- a/src/register.cpp +++ b/src/register.cpp @@ -325,6 +325,14 @@ MAKE_HOOK(LivenessState_TraverseObjectInternal, nullptr, bool, Il2CppObject* obj // custom_types::logger.debug("Complete Liveness::FromStatics"); // } +// The value we are reporting on is, by definition, one whose class pointer we +// already suspect. Dereferencing it (or a filter class read out of the liveness +// state) is what turns this diagnostic into a SIGSEGV instead of a log message. +// A real Il2CppClass points its klass field back at itself and has a name. +static inline bool LooksLikeValidClass(const Il2CppClass* klass) { + return klass != nullptr && klass->klass == klass && klass->name != nullptr; +} + static inline bool HasParentUnsafe(const Il2CppClass* klass, const Il2CppClass* parent) { return klass->typeHierarchyDepth >= parent->typeHierarchyDepth && klass->typeHierarchy[parent->typeHierarchyDepth - 1] == parent; } @@ -434,12 +442,19 @@ MAKE_HOOK(LivenessState_TraverseGCDescriptor, nullptr, void, Il2CppObject* obj, custom_types::logAll(GET_CLASS(obj)); } custom_types::logger.critical("KLASS PTR: {}", fmt::ptr(val->klass)); - custom_types::logger.critical("Attempting HasParentUnsafe({}, {})...", fmt::ptr(GET_CLASS(val)), fmt::ptr(filterClass)); - auto ret = HasParentUnsafe(GET_CLASS(val), filterClass); - custom_types::logger.critical("HasParentUnsafe return: {}", ret); - if (GET_CLASS(val)) { + if (LooksLikeValidClass(GET_CLASS(val))) { + if (LooksLikeValidClass(filterClass)) { + custom_types::logger.critical("Attempting HasParentUnsafe({}, {})...", fmt::ptr(GET_CLASS(val)), fmt::ptr(filterClass)); + auto ret = HasParentUnsafe(GET_CLASS(val), filterClass); + custom_types::logger.critical("HasParentUnsafe return: {}", ret); + } else { + custom_types::logger.critical("Filter class {} is not a valid Il2CppClass, skipping HasParentUnsafe", fmt::ptr(filterClass)); + } custom_types::logAll(GET_CLASS(val)); + } else { + custom_types::logger.critical("Class {} of the offending instance is not a valid Il2CppClass, skipping the parent check and class dump", fmt::ptr(GET_CLASS(val))); } + custom_types::logger.critical("Continuing without crashing"); // Things I have learned, just dumping here: // static fields and classes that have a nonzero quantity of static // fields need to be added to: Class::GetStaticFieldData() as for