Skip to content

Instantly share code, notes, and snippets.

@landonf
Forked from 0xced/Makefile
Created April 23, 2011 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save landonf/938633 to your computer and use it in GitHub Desktop.
Save landonf/938633 to your computer and use it in GitHub Desktop.
objc_msgSend gotchas
/*
$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ clang --version
Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
Target: x86_64-apple-darwin10
Thread model: posix
gcc -arch x86_64 banana.m -framework Foundation && ./a.out => pear
gcc -arch i386 banana.m -framework Foundation && ./a.out => banana
clang -arch x86_64 banana.m -framework Foundation && ./a.out => banana
clang -arch i386 banana.m -framework Foundation && ./a.out => banana
*/
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
static int magic()
{
return 36; // (0x0000000100000ca3 - 0x0000000100000c13) / 4
}
static id pear()
{
__asm__("nop");
return @"pear";
}
// The method isn't variadic itself, so the IMP also shouldn't be
static id banana(id self, SEL _cmd)
{
return @"banana";
}
@interface Fruit : NSObject
@end
@implementation Fruit
- (id) apple
{
return @"apple";
}
@end
int main (int argc, char const *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Method apple = class_getInstanceMethod([Fruit class], @selector(apple));
method_setImplementation(apple, (IMP)banana);
Fruit *fruit = [[[Fruit alloc] init] autorelease];
int n = magic();
// The following will emit identical code
printf("%s\n", [[fruit apple] UTF8String]);
printf("%s\n", [(*(NSString *(*)(id, SEL))objc_msgSend)(fruit, @selector(apple)) UTF8String]);
// This will not emit correct code
objc_msgSend(fruit, @selector(apple));
[pool drain];
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment