/ 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