Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -612,11 +612,41 @@ } IMP class_getMethodImplementation(Class cls, SEL sel) { - return objc_sparsearray_get(cls->dtable, (uint32_t)sel->uid); + /* + * We use a dummy object here so that the normal lookup is used, even + * though we don't have an object. Doing so is safe, as objc_msg_lookup + * does not access the object, but only its class. + * + * Just looking it up in the dispatch table could result in returning + * NULL instead of the forwarding handler, it would also mean + * +[resolveClassMethod:] / +[resolveInstanceMethod:] would not be + * called. + */ + + struct { + Class isa; + } dummy = { cls }; + + return objc_msg_lookup((id)&dummy, sel); +} + +IMP +class_getMethodImplementation_stret(Class cls, SEL sel) +{ + /* + * Same as above, but use objc_msg_lookup_stret instead, so that the + * correct forwarding handler is returned. + */ + + struct { + Class isa; + } dummy = { cls }; + + return objc_msg_lookup_stret((id)&dummy, sel); } const char* class_getMethodTypeEncoding(Class cls, SEL sel) { Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -27,10 +27,15 @@ static void *forward_handler_stret = NULL; static IMP common_method_not_found(id obj, SEL sel, IMP (*lookup)(id, SEL), void *forward) { + /* + * obj might be a dummy object (see class_getMethodImplementation), so + * don't access obj directly unless it's a class! + */ + bool is_class = object_getClass(obj)->info & OBJC_CLASS_INFO_METACLASS; if (!(object_getClass(obj)->info & OBJC_CLASS_INFO_INITIALIZED)) { Class cls = (is_class ? (Class)obj : object_getClass(obj)); Index: src/runtime/runtime.h ================================================================== --- src/runtime/runtime.h +++ src/runtime/runtime.h @@ -195,10 +195,11 @@ extern bool class_isKindOfClass(Class, Class); extern unsigned long class_getInstanceSize(Class); extern bool class_respondsToSelector(Class, SEL); extern bool class_conformsToProtocol(Class, Protocol*); extern IMP class_getMethodImplementation(Class, SEL); +extern IMP class_getMethodImplementation_stret(Class, SEL); extern const char* class_getMethodTypeEncoding(Class, SEL); extern IMP class_replaceMethod(Class, SEL, IMP, const char*); extern Class object_getClass(id); extern Class object_setClass(id, Class); extern const char* object_getClassName(id);