Shamsiddin Saidov
Shamsiddin Saidov

Reputation: 2281

method_getImplementation crashes on 64-bit iphone 5s

I have a piece of code in my project

- (NSData *)getIvars:(unsigned int *)count from:(id)class_name NS_RETURNS_RETAINED {
    @synchronized(self) {
        SEL selector = @selector(copyIvarList:from:);
        Method grannyMethod = class_getInstanceMethod([class_name class], selector);
        IMP grannyImp = method_getImplementation(grannyMethod);
        return grannyImp([class_name class], selector, count, [class_name class]);
    }
}

- (NSData *)copyIvarList:(unsigned int *)count from:(id)class_name NS_RETURNS_RETAINED {
    @synchronized(self) {
        Ivar *ret_val_c = class_copyIvarList([class_name class], count);
        NSData *ret_val = [[NSData alloc] initWithBytes:ret_val_c length:sizeof(Ivar) * *count];
        free(ret_val_c);
        return ret_val;
    }
}

Here's the call of first method:

Class class_to_anylize = [self superclass]; // some class inherieted from NSObject
unsigned int ivar_count = 0;
NSData *new_var_list = [self getIvars:&ivar_count from:class_to_anylize];

But it crashes at (showing no log):

return grannyImp([class_name class], selector, count, [class_name class]);

PS: It crashes when I include arm64 architecture to the project's Valid Architectures section. But when I leave this section without arm64 it runs without problem.

Is there any problematic code I done?

enter image description here

Upvotes: 0

Views: 564

Answers (1)

Cy-4AH
Cy-4AH

Reputation: 4585

There is problem with the keyword IMP.
Actually IMP defines a function with the prototype:id (*)(id, SEL, ...).

Under Arm64 passing arguments to a function with a variable argument count is different than how it is under Arm6 and 7

instead of IMP you should use exact prototype of your function.
Use this type:
typedef NSData* (*getIvarsFunction)(id, SEL, unsigned int*, Class);

And your code will be:

- (NSData *)getIvars:(unsigned int *)count from:(id)class_name NS_RETURNS_RETAINED {
    @synchronized(self) {
        SEL selector = @selector(copyIvarList:from:);
        Method grannyMethod = class_getInstanceMethod([class_name class], selector);
        getIvarsFunction grannyImp = (getIvarsFunction)method_getImplementation(grannyMethod);
        return grannyImp([class_name class], selector, count, [class_name class]);
    }
}

This code will work on arm6,7,64.

Upvotes: 6

Related Questions