3

I need to replace some methods’ implementations of specific Objective-C classes. A set of functions from objc/runtime library is capable of doing that. To simplify the issue I just write a simplest sample code as following:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface MyClass : NSObject
- (void) func;
@end

@implementation MyClass

- (void) func {
    NSLog(@"Hello from MyClass!");
}

@end

//Original implementation of the method
static IMP gOriginalFunc = nil;

//Hook function that will take place of the original method
void HookFunc(id self, SEL _cmd)
{
    NSLog(@"[MyClass func] is hooked!");
    gOriginalFunc(self, _cmd);//EXC_BAD_ACCESS occurs here when ARC is enabled!!
}

int main(int argc, char *argv[])
{
    Class clsMyClass = objc_getClass("MyClass");
    // Restore the original method implementation:
    gOriginalFunc = class_getMethodImplementation(clsMyClass, @selector(func));
    Method mtdFunc = class_getInstanceMethod(clsMyClass, @selector(func));
    // Replace implementaion of the method of my own:
    class_replaceMethod(clsMyClass, @selector(func), IMP(HookFunc), method_getTypeEncoding(mtdFunc));
    objc_registerClassPair(clsMyClass);

    MyClass* obj = [[MyClass alloc] init];
    [obj func];

    return 0;
}

I just replace the original implementation of [MyClass func]. When compiler flag -fno-objc-arc is set, this code works just fine:

2014-12-18 11:59:17.524 Hooker[749:72783] [MyClass func] is hooked!
2014-12-18 11:59:20.361 Hooker[749:72783] Hello from MyClass!

But problem occurs when ARC is enabled(by setting compiler flag as -fobjc-arc). A EXC_BAD_ACCESS signal is thrown while invoking gOriginalFunc(as comments say). I don’t know the reason, could anyone tell?

4

1 回答 1

1

您的函数原型不准确,编译器错误地设置了调用。使用 ARC,这包括引用计数操作。要么是未定义的行为。

要更正程序,请告知编译器实际的函数签名,这样它就不会搞砸调用:

typedef void (*HookFunc_Signature)(id, SEL); // << != IMP's signature
static HookFunc_Signature gOriginalFunc = nil;

...之后:

gOriginalFunc = (HookFunc_Signature)class_getMethodImplementation(clsMyClass, @selector(func));
于 2014-12-18T04:52:51.330 回答