/ NSObject.m
NSObject.m
1 // 2 // NSObject.m 3 // CoreFoundation 4 // 5 // Copyright (c) 2014 Apportable. All rights reserved. 6 // 7 8 #import <Foundation/NSObject.h> 9 #import <Foundation/NSString.h> 10 #import <Foundation/NSMethodSignature.h> 11 #import <Foundation/NSInvocation.h> 12 #import <Foundation/NSException.h> 13 #import "CFString.h" 14 #import "NSZombie.h" 15 #import <objc/runtime.h> 16 #import <objc/message.h> 17 #include <stdio.h> 18 #include <malloc/malloc.h> 19 20 //#import <libv/libv.h> 21 #define _GETENV(a,b) 0 22 23 #define SYMBOL_HERE_IN_3(sym, vers, n) \ 24 OBJC_EXPORT const char here_ ##n __asm__("$ld$add$os" #vers "$" #sym); const char here_ ##n = 0 25 #define SYMBOL_HERE_IN_2(sym, vers, n) \ 26 SYMBOL_HERE_IN_3(sym, vers, n) 27 #define SYMBOL_HERE_IN(sym, vers) \ 28 SYMBOL_HERE_IN_2(sym, vers, __COUNTER__) 29 30 #if __OBJC2__ 31 # define NSOBJECT_HERE_IN(vers) \ 32 SYMBOL_HERE_IN(_OBJC_CLASS_$_NSObject, vers); \ 33 SYMBOL_HERE_IN(_OBJC_METACLASS_$_NSObject, vers); \ 34 SYMBOL_HERE_IN(_OBJC_IVAR_$_NSObject.isa, vers) 35 #else 36 # define NSOBJECT_HERE_IN(vers) \ 37 SYMBOL_HERE_IN(.objc_class_name_NSObject, vers) 38 #endif 39 40 #if TARGET_OS_IOS 41 42 NSOBJECT_HERE_IN(2.0); 43 NSOBJECT_HERE_IN(2.1); 44 NSOBJECT_HERE_IN(2.2); 45 NSOBJECT_HERE_IN(3.0); 46 NSOBJECT_HERE_IN(3.1); 47 NSOBJECT_HERE_IN(3.2); 48 NSOBJECT_HERE_IN(4.0); 49 NSOBJECT_HERE_IN(4.1); 50 NSOBJECT_HERE_IN(4.2); 51 NSOBJECT_HERE_IN(4.3); 52 NSOBJECT_HERE_IN(5.0); 53 NSOBJECT_HERE_IN(5.1); 54 55 #elif TARGET_OS_MAC 56 57 NSOBJECT_HERE_IN(10.0); 58 NSOBJECT_HERE_IN(10.1); 59 NSOBJECT_HERE_IN(10.2); 60 NSOBJECT_HERE_IN(10.3); 61 NSOBJECT_HERE_IN(10.4); 62 NSOBJECT_HERE_IN(10.5); 63 NSOBJECT_HERE_IN(10.6); 64 NSOBJECT_HERE_IN(10.7); 65 66 #endif 67 68 void __CFZombifyNSObject(void) { 69 Class cls = objc_lookUpClass("NSObject"); 70 Method dealloc_zombie = class_getInstanceMethod(cls, @selector(__dealloc_zombie)); 71 Method dealloc = class_getInstanceMethod(cls, @selector(dealloc)); 72 method_exchangeImplementations(dealloc_zombie, dealloc); 73 } 74 75 static void NSUnrecognizedForwarding() { __asm__("int3"); } 76 77 @implementation NSObject (NSObject) 78 79 + (void)doesNotRecognizeSelector:(SEL)sel 80 { 81 if (_GETENV(BOOL, "NSUnrecognizedForwardingDisabled")) 82 { 83 RELEASE_LOG("+[%s %s]: unrecognized selector sent to instance %p; set a breakpoint on NSUnrecognizedForwarding to debug", class_getName(self), sel_getName(sel), self); 84 NSUnrecognizedForwarding(); 85 } 86 else 87 { 88 // DONT EVEN THINK ABOUT REMOVING/HACKING AROUND THIS! 89 // EVER! 90 // ... 91 // yes, I mean YOU! 92 [NSException raise:NSInvalidArgumentException format:@"+[%s %s]: unrecognized selector sent to instance %p", class_getName(self), sel_getName(sel), self]; 93 } 94 } 95 96 - (void)doesNotRecognizeSelector:(SEL)sel 97 { 98 if (_GETENV(BOOL, "NSUnrecognizedForwardingDisabled")) 99 { 100 RELEASE_LOG("+[%s %s]: unrecognized selector sent to instance %p; set a breakpoint on NSUnrecognizedForwarding to debug", object_getClassName(self), sel_getName(sel), self); 101 NSUnrecognizedForwarding(); 102 } 103 else 104 { 105 // DONT EVEN THINK ABOUT REMOVING/HACKING AROUND THIS! 106 // EVER! 107 // ... 108 // yes, I mean YOU! 109 [NSException raise:NSInvalidArgumentException format:@"-[%s %s]: unrecognized selector sent to instance %p", object_getClassName(self), sel_getName(sel), self]; 110 } 111 } 112 113 + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)sel 114 { 115 if (sel == NULL) 116 { 117 return nil; 118 } 119 120 Method m = class_getInstanceMethod(self, sel); 121 122 if (m == NULL) 123 { 124 return nil; 125 } 126 127 return [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(m)]; 128 } 129 130 + (NSMethodSignature *)methodSignatureForSelector:(SEL)sel 131 { 132 if (sel == NULL) 133 { 134 return nil; 135 } 136 137 Method m = class_getClassMethod(self, sel); 138 139 if (m == NULL) 140 { 141 return nil; 142 } 143 144 return [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(m)]; 145 } 146 147 148 - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel 149 { 150 if (sel == NULL) 151 { 152 return nil; 153 } 154 155 Method m = class_getInstanceMethod(object_getClass(self), sel); 156 157 if (m == NULL) 158 { 159 return nil; 160 } 161 162 return [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(m)]; 163 } 164 165 + (NSString *)description 166 { 167 CFStringRef description = CFStringCreateWithCString(kCFAllocatorDefault, class_getName(self), kCFStringEncodingUTF8); 168 return [(NSString *)description autorelease]; 169 } 170 171 - (NSString *)description 172 { 173 CFStringRef description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<%s: %p>"), object_getClassName(self), self); 174 return [(NSString *)description autorelease]; 175 } 176 177 + (BOOL)implementsSelector:(SEL)selector 178 { 179 if (selector == NULL) 180 { 181 [NSException raise:NSInvalidArgumentException format:@"selector cannot be NULL"]; 182 return NO; 183 } 184 185 return class_getMethodImplementation(object_getClass(self), selector) != (IMP)&_objc_msgForward; 186 } 187 188 - (BOOL)implementsSelector:(SEL)selector 189 { 190 if (selector == NULL) 191 { 192 [NSException raise:NSInvalidArgumentException format:@"selector cannot be NULL"]; 193 return NO; 194 } 195 196 // sneaky! this calls [self class]!! 197 return class_getMethodImplementation([self class], selector) != (IMP)&_objc_msgForward; 198 } 199 200 + (BOOL)instancesImplementSelector:(SEL)selector 201 { 202 if (selector == NULL) 203 { 204 [NSException raise:NSInvalidArgumentException format:@"selector cannot be NULL"]; 205 return NO; 206 } 207 208 return class_getMethodImplementation(self, selector) != (IMP)&_objc_msgForward; 209 } 210 211 + (void)forwardInvocation:(NSInvocation *)inv 212 { 213 [inv setTarget:self]; 214 [inv invoke]; 215 } 216 217 - (void)forwardInvocation:(NSInvocation *)inv 218 { 219 [inv setTarget:self]; 220 [inv invoke]; 221 } 222 223 - (void)__dealloc_zombie 224 { 225 const char *className = object_getClassName(self); 226 char *zombieClassName = NULL; 227 do { 228 if (asprintf(&zombieClassName, "%s%s", ZOMBIE_PREFIX, className) == -1) 229 { 230 break; 231 } 232 233 Class zombieClass = objc_getClass(zombieClassName); 234 235 if (zombieClass == Nil) 236 { 237 zombieClass = objc_duplicateClass(objc_getClass(ZOMBIE_PREFIX), zombieClassName, 0); 238 } 239 240 if (zombieClass == Nil) 241 { 242 break; 243 } 244 245 objc_destructInstance(self); 246 247 object_setClass(self, zombieClass); 248 249 } while (0); 250 251 if (zombieClassName != NULL) 252 { 253 free(zombieClassName); 254 } 255 } 256 257 @end 258 259 @implementation NSObject (NSCoderMethods) 260 261 - (BOOL)_allowsDirectEncoding 262 { 263 return NO; 264 } 265 266 + (NSInteger)version 267 { 268 return class_getVersion(self); 269 } 270 271 + (void)setVersion:(NSInteger)aVersion 272 { 273 class_setVersion(self, aVersion); 274 } 275 276 - (Class)classForCoder 277 { 278 return [self class]; 279 } 280 281 - (id)replacementObjectForCoder:(NSCoder *)aCoder 282 { 283 return self; 284 } 285 286 - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder 287 { 288 return self; 289 } 290 291 @end 292 293 @implementation NSObject (__NSIsKinds) 294 295 - (BOOL)isNSValue__ 296 { 297 return NO; 298 } 299 300 - (BOOL)isNSTimeZone__ 301 { 302 return NO; 303 } 304 305 - (BOOL)isNSString__ 306 { 307 return NO; 308 } 309 310 - (BOOL)isNSSet__ 311 { 312 return NO; 313 } 314 315 - (BOOL)isNSOrderedSet__ 316 { 317 return NO; 318 } 319 320 - (BOOL)isNSNumber__ 321 { 322 return NO; 323 } 324 325 - (BOOL)isNSDictionary__ 326 { 327 return NO; 328 } 329 330 - (BOOL)isNSDate__ 331 { 332 return NO; 333 } 334 335 - (BOOL)isNSData__ 336 { 337 return NO; 338 } 339 340 - (BOOL)isNSArray__ 341 { 342 return NO; 343 } 344 345 @end