]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-runtime.m
objc4-274.tar.gz
[apple/objc4.git] / runtime / objc-runtime.m
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /***********************************************************************
26 * objc-runtime.m
27 * Copyright 1988-1996, NeXT Software, Inc.
28 * Author: s. naroff
29 *
30 **********************************************************************/
31
32 /***********************************************************************
33 * Class loading and connecting (GrP 2004-2-11)
34 *
35 * When images are loaded (during program startup or otherwise), the
36 * runtime needs to load classes and categories from the images, connect
37 * classes to superclasses and categories to parent classes, and call
38 * +load methods.
39 *
40 * The Objective-C runtime can cope with classes arriving in any order.
41 * That is, a class may be discovered by the runtime before some
42 * superclass is known. To handle out-of-order class loads, the
43 * runtime uses a "pending class" system.
44 *
45 * (Historical note)
46 * Panther and earlier: many classes arrived out-of-order because of
47 * the poorly-ordered callback from dyld. However, the runtime's
48 * pending mechanism only handled "missing superclass" and not
49 * "present superclass but missing higher class". See Radar #3225652.
50 * Tiger: The runtime's pending mechanism was augmented to handle
51 * arbitrary missing classes. In addition, dyld was rewritten and
52 * now sends the callbacks in strictly bottom-up link order.
53 * The pending mechanism may now be needed only for rare and
54 * hard to construct programs.
55 * (End historical note)
56 *
57 * A class when first seen in an image is considered "unconnected".
58 * It is stored in `unconnected_class_hash`. If all of the class's
59 * superclasses exist and are already "connected", then the new class
60 * can be connected to its superclasses and moved to `class_hash` for
61 * normal use. Otherwise, the class waits in `unconnected_class_hash`
62 * until the superclasses finish connecting.
63 *
64 * A "connected" class is
65 * (1) in `class_hash`,
66 * (2) connected to its superclasses,
67 * (3) has no unconnected superclasses,
68 * (4) is otherwise initialized and ready for use, and
69 * (5) is eligible for +load if +load has not already been called.
70 *
71 * An "unconnected" class is
72 * (1) in `unconnected_class_hash`,
73 * (2) not connected to its superclasses,
74 * (3) has an immediate superclass which is either missing or unconnected,
75 * (4) is not ready for use, and
76 * (5) is not yet eligible for +load.
77 *
78 * Image mapping is NOT CURRENTLY THREAD-SAFE with respect to just about
79 * * * anything. Image mapping IS RE-ENTRANT in several places: superclass
80 * lookup may cause ZeroLink to load another image, and +load calls may
81 * cause dyld to load another image.
82 *
83 * Image mapping sequence:
84 *
85 * Read all classes in all new images.
86 * Add them all to unconnected_class_hash.
87 * Note any +load implementations before categories are attached.
88 * Fix up any pended classrefs referring to them.
89 * Attach any pending categories.
90 * Read all categories in all new images.
91 * Attach categories whose parent class exists (connected or not),
92 * and pend the rest.
93 * Mark them all eligible for +load (if implemented), even if the
94 * parent class is missing.
95 * Try to connect all classes in all new images.
96 * If the superclass is missing, pend the class
97 * If the superclass is unconnected, try to recursively connect it
98 * If the superclass is connected:
99 * connect the class
100 * mark the class eligible for +load, if implemented
101 * connect any pended subclasses of the class
102 * Resolve selector refs and class refs in all new images.
103 * Class refs whose classes still do not exist are pended.
104 * Fix up protocol objects in all new images.
105 * Call +load for classes and categories.
106 * May include classes or categories that are not in these images,
107 * but are newly eligible because of these image.
108 * Class +loads will be called superclass-first because of the
109 * superclass-first nature of the connecting process.
110 * Category +load needs to be deferred until the parent class is
111 * connected and has had its +load called.
112 *
113 * Performance: all classes are read before any categories are read.
114 * Fewer categories need be pended for lack of a parent class.
115 *
116 * Performance: all categories are attempted to be attached before
117 * any classes are connected. Fewer class caches need be flushed.
118 * (Unconnected classes and their respective subclasses are guaranteed
119 * to be un-messageable, so their caches will be empty.)
120 *
121 * Performance: all classes are read before any classes are connected.
122 * Fewer classes need be pended for lack of a superclass.
123 *
124 * Correctness: all selector and class refs are fixed before any
125 * protocol fixups or +load methods. libobjc itself contains selector
126 * and class refs which are used in protocol fixup and +load.
127 *
128 * Correctness: +load methods are scheduled in bottom-up link order.
129 * This constraint is in addition to superclass order. Some +load
130 * implementations expect to use another class in a linked-to library,
131 * even if the two classes don't share a direct superclass relationship.
132 *
133 * Correctness: all classes are scanned for +load before any categories
134 * are attached. Otherwise, if a category implements +load and its class
135 * has no class methods, the class's +load scan would find the category's
136 * +load method, which would then be called twice.
137 *
138 **********************************************************************/
139
140
141 /***********************************************************************
142 * Imports.
143 **********************************************************************/
144
145 #include <mach-o/ldsyms.h>
146 #include <mach-o/dyld.h>
147 #include <mach-o/dyld_gdb.h>
148 #include <mach/mach.h>
149 #include <mach/mach_error.h>
150
151 // project headers first, otherwise we get the installed ones
152 #import "objc-class.h"
153 #import <objc/objc-runtime.h>
154 #import <objc/hashtable2.h>
155 #import "maptable.h"
156 #import "objc-private.h"
157 #import <objc/Object.h>
158 #import <objc/Protocol.h>
159 #import "objc-rtp.h"
160 #import "objc-auto.h"
161
162 #include <sys/time.h>
163 #include <sys/resource.h>
164 #include <sys/types.h>
165 #include <sys/stat.h>
166 #include <fcntl.h>
167
168 /* NXHashTable SPI */
169 OBJC_EXPORT unsigned _NXHashCapacity(NXHashTable *table);
170 OBJC_EXPORT void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity);
171
172
173 OBJC_EXPORT Class _objc_getNonexistentClass(void);
174
175
176 OBJC_EXPORT Class getOriginalClassForPosingClass(Class);
177
178
179 /***********************************************************************
180 * Constants and macros internal to this module.
181 **********************************************************************/
182
183 /* Turn on support for literal string objects. */
184 #define LITERAL_STRING_OBJECTS
185
186 /***********************************************************************
187 * Types internal to this module.
188 **********************************************************************/
189
190 typedef struct _objc_unresolved_category
191 {
192 struct _objc_unresolved_category * next;
193 struct objc_category * cat; // may be NULL
194 long version;
195 } _objc_unresolved_category;
196
197 typedef struct _PendingSubclass
198 {
199 struct objc_class *subclass; // subclass to finish connecting; may be NULL
200 struct _PendingSubclass *next;
201 } PendingSubclass;
202
203 typedef struct _PendingClassRef
204 {
205 struct objc_class **ref; // class reference to fix up; may be NULL
206 struct _PendingClassRef *next;
207 } PendingClassRef;
208
209 struct loadable_class {
210 struct objc_class *cls; // may be NULL
211 IMP method;
212 };
213
214 struct loadable_category {
215 struct objc_category *cat; // may be NULL
216 IMP method;
217 };
218
219
220 /***********************************************************************
221 * Exports.
222 **********************************************************************/
223
224 // Function called after class has been fixed up (MACH only)
225 void (*callbackFunction)(Class, const char *) = 0;
226
227 // Lock for class hashtable
228 OBJC_DECLARE_LOCK (classLock);
229
230 // Settings from environment variables
231 __private_extern__ int PrintImages = -1; // env OBJC_PRINT_IMAGES
232 __private_extern__ int PrintLoading = -1; // env OBJC_PRINT_LOAD_METHODS
233 __private_extern__ int PrintConnecting = -1; // env OBJC_PRINT_CONNECTION
234 __private_extern__ int PrintRTP = -1; // env OBJC_PRINT_RTP
235 __private_extern__ int PrintGC = -1; // env OBJC_PRINT_GC
236 __private_extern__ int PrintSharing = -1; // env OBJC_PRINT_SHARING
237 __private_extern__ int PrintCxxCtors = -1; // env OBJC_PRINT_CXX_CTORS
238
239 __private_extern__ int UseInternalZone = -1; // env OBJC_USE_INTERNAL_ZONE
240 __private_extern__ int AllowInterposing = -1;// env OBJC_ALLOW_INTERPOSING
241
242 __private_extern__ int DebugUnload = -1; // env OBJC_DEBUG_UNLOAD
243 __private_extern__ int DebugFragileSuperclasses = -1; // env OBJC_DEBUG_FRAGILE_SUPERCLASSES
244
245 __private_extern__ int ForceGC = -1; // env OBJC_FORCE_GC
246 __private_extern__ int ForceNoGC = -1; // env OBJC_FORCE_NO_GC
247 __private_extern__ int CheckFinalizers = -1; // env OBJC_CHECK_FINALIZERS
248
249 // objc's key for pthread_getspecific
250 __private_extern__ pthread_key_t _objc_pthread_key = 0;
251
252 // List of classes that need +load called (pending superclass +load)
253 // This list always has superclasses first because of the way it is constructed
254 static struct loadable_class *loadable_classes NOBSS = NULL;
255 static int loadable_classes_used NOBSS = 0;
256 static int loadable_classes_allocated NOBSS = 0;
257
258 // List of categories that need +load called (pending parent class +load)
259 static struct loadable_category *loadable_categories NOBSS = NULL;
260 static int loadable_categories_used NOBSS = 0;
261 static int loadable_categories_allocated NOBSS = 0;
262
263 // Selectors for which @selector() doesn't work
264 __private_extern__ SEL cxx_construct_sel = NULL;
265 __private_extern__ SEL cxx_destruct_sel = NULL;
266 __private_extern__ const char *cxx_construct_name = ".cxx_construct";
267 __private_extern__ const char *cxx_destruct_name = ".cxx_destruct";
268
269
270 /***********************************************************************
271 * Function prototypes internal to this module.
272 **********************************************************************/
273
274 static unsigned classHash (void * info, struct objc_class * data);
275 static int classIsEqual (void * info, struct objc_class * name, struct objc_class * cls);
276 static int _objc_defaultClassHandler (const char * clsName);
277 static void _objcTweakMethodListPointerForClass (struct objc_class * cls);
278 static void _objc_add_category_flush_caches(struct objc_class * cls, struct objc_category * category, int version);
279 static void _objc_add_category(struct objc_class * cls, struct objc_category * category, int version);
280 static void _objc_register_category (struct objc_category * cat, long version);
281 static void _objc_read_categories_from_image (header_info * hi);
282 static const header_info * _headerForClass (struct objc_class * cls);
283 static NXMapTable * pendingClassRefsMapTable (void);
284 static NXMapTable * pendingSubclassesMapTable (void);
285 static void _objc_read_classes_from_image (header_info * hi);
286 static void _objc_map_class_refs_for_image (header_info * hi);
287 static void _objc_fixup_protocol_objects_for_image (header_info * hi);
288 static void _objc_fixup_selector_refs (const header_info * hi);
289 static void _objc_unmap_image(const headerType *mh);
290 static BOOL connect_class(struct objc_class *cls);
291 static void add_category_to_loadable_list(struct objc_category *cat);
292
293
294 /***********************************************************************
295 * Static data internal to this module.
296 **********************************************************************/
297
298 // we keep a linked list of header_info's describing each image as told to us by dyld
299 static header_info *FirstHeader NOBSS = 0; // NULL means empty list
300 static header_info *LastHeader NOBSS = 0; // NULL means invalid; recompute it
301
302 // Hash table of classes
303 static NXHashTable * class_hash NOBSS = 0;
304 static NXHashTablePrototype classHashPrototype =
305 {
306 (unsigned (*) (const void *, const void *)) classHash,
307 (int (*)(const void *, const void *, const void *)) classIsEqual,
308 NXNoEffectFree, 0
309 };
310
311 // Hash table of unconnected classes
312 static NXHashTable *unconnected_class_hash NOBSS = NULL;
313
314 // Exported copy of class_hash variable (hook for debugging tools)
315 NXHashTable *_objc_debug_class_hash = NULL;
316
317 // Function pointer objc_getClass calls through when class is not found
318 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
319
320 // Function pointer called by objc_getClass and objc_lookupClass when
321 // class is not found. _objc_classLoader is called before objc_classHandler.
322 static BOOL (*_objc_classLoader)(const char *) = NULL;
323
324 // Category and class registries
325 // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
326 // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
327 static NXMapTable * category_hash = NULL;
328
329 // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
330 // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
331 static NXMapTable * pendingClassRefsMap = NULL;
332 static NXMapTable * pendingSubclassesMap = NULL;
333
334 /***********************************************************************
335 * objc_dump_class_hash. Log names of all known classes.
336 **********************************************************************/
337 void objc_dump_class_hash (void)
338 {
339 NXHashTable * table;
340 unsigned count;
341 struct objc_class * data;
342 NXHashState state;
343
344 table = class_hash;
345 count = 0;
346 state = NXInitHashState (table);
347 while (NXNextHashState (table, &state, (void **) &data))
348 printf ("class %d: %s\n", ++count, data->name);
349 }
350
351 /***********************************************************************
352 * classHash.
353 **********************************************************************/
354 static unsigned classHash (void * info,
355 struct objc_class * data)
356 {
357 // Nil classes hash to zero
358 if (!data)
359 return 0;
360
361 // Call through to real hash function
362 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
363 }
364
365 /***********************************************************************
366 * classIsEqual. Returns whether the class names match. If we ever
367 * check more than the name, routines like objc_lookUpClass have to
368 * change as well.
369 **********************************************************************/
370 static int classIsEqual (void * info,
371 struct objc_class * name,
372 struct objc_class * cls)
373 {
374 // Standard string comparison
375 // Our local inlined version is significantly shorter on PPC and avoids the
376 // mflr/mtlr and dyld_stub overhead when calling strcmp.
377 return _objc_strcmp(name->name, cls->name) == 0;
378 }
379
380
381 /***********************************************************************
382 * NXMapKeyCopyingInsert
383 * Like NXMapInsert, but strdups the key if necessary.
384 * Used to prevent stale pointers when bundles are unloaded.
385 **********************************************************************/
386 static void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value)
387 {
388 void *realKey;
389 void *realValue = NULL;
390
391 if ((realKey = NXMapMember(table, key, &realValue)) != NX_MAPNOTAKEY) {
392 // key DOES exist in table - use table's key for insertion
393 } else {
394 // key DOES NOT exist in table - copy the new key before insertion
395 realKey = _strdup_internal(key);
396 }
397 return NXMapInsert(table, realKey, value);
398 }
399
400
401 /***********************************************************************
402 * NXMapKeyFreeingRemove
403 * Like NXMapRemove, but frees the existing key if necessary.
404 * Used to prevent stale pointers when bundles are unloaded.
405 **********************************************************************/
406 static void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key)
407 {
408 void *realKey;
409 void *realValue = NULL;
410
411 if ((realKey = NXMapMember(table, key, &realValue)) != NX_MAPNOTAKEY) {
412 // key DOES exist in table - remove pair and free key
413 realValue = NXMapRemove(table, realKey);
414 _free_internal(realKey); // the key from the table, not necessarily the one given
415 return realValue;
416 } else {
417 // key DOES NOT exist in table - nothing to do
418 return NULL;
419 }
420 }
421
422
423 /***********************************************************************
424 * _objc_init_class_hash. Return the class lookup table, create it if
425 * necessary.
426 **********************************************************************/
427 void _objc_init_class_hash (void)
428 {
429 // Do nothing if class hash table already exists
430 if (class_hash)
431 return;
432
433 // class_hash starts small, with only enough capacity for libobjc itself.
434 // If a second library is found by map_images(), class_hash is immediately
435 // resized to capacity 1024 to cut down on rehashes.
436 // Old numbers: A smallish Foundation+AppKit program will have
437 // about 520 classes. Larger apps (like IB or WOB) have more like
438 // 800 classes. Some customers have massive quantities of classes.
439 // Foundation-only programs aren't likely to notice the ~6K loss.
440 class_hash = NXCreateHashTableFromZone (classHashPrototype,
441 16,
442 nil,
443 _objc_internal_zone ());
444 _objc_debug_class_hash = class_hash;
445 }
446
447 /***********************************************************************
448 * objc_getClassList. Return the known classes.
449 **********************************************************************/
450 int objc_getClassList(Class *buffer, int bufferLen) {
451 NXHashState state;
452 struct objc_class * class;
453 int cnt, num;
454
455 OBJC_LOCK(&classLock);
456 num = NXCountHashTable(class_hash);
457 if (NULL == buffer) {
458 OBJC_UNLOCK(&classLock);
459 return num;
460 }
461 cnt = 0;
462 state = NXInitHashState(class_hash);
463 while (cnt < bufferLen &&
464 NXNextHashState(class_hash, &state, (void **)&class))
465 {
466 buffer[cnt++] = class;
467 }
468 OBJC_UNLOCK(&classLock);
469 return num;
470 }
471
472 /***********************************************************************
473 * objc_getClasses. Return class lookup table.
474 *
475 * NOTE: This function is very dangerous, since you cannot safely use
476 * the hashtable without locking it, and the lock is private!
477 **********************************************************************/
478 void * objc_getClasses (void)
479 {
480 // Return the class lookup hash table
481 return class_hash;
482 }
483
484 /***********************************************************************
485 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
486 **********************************************************************/
487 static int _objc_defaultClassHandler (const char * clsName)
488 {
489 // Return zero so objc_getClass doesn't bother re-searching
490 return 0;
491 }
492
493 /***********************************************************************
494 * objc_setClassHandler. Set objc_classHandler to the specified value.
495 *
496 * NOTE: This should probably deal with userSuppliedHandler being NULL,
497 * because the objc_classHandler caller does not check... it would bus
498 * error. It would make sense to handle NULL by restoring the default
499 * handler. Is anyone hacking with this, though?
500 **********************************************************************/
501 void objc_setClassHandler (int (*userSuppliedHandler) (const char *))
502 {
503 objc_classHandler = userSuppliedHandler;
504 }
505
506
507 /***********************************************************************
508 * look_up_class
509 * Map a class name to a class using various methods.
510 * This is the common implementation of objc_lookUpClass and objc_getClass,
511 * and is also used internally to get additional search options.
512 * Sequence:
513 * 1. class_hash
514 * 2. unconnected_class_hash (optional)
515 * 3. classLoader callback
516 * 4. classHandler callback (optional)
517 **********************************************************************/
518 static id look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler)
519 {
520 BOOL includeClassLoader = YES; // class loader cannot be skipped
521 id result = nil;
522 struct objc_class query;
523
524 query.name = aClassName;
525
526 retry:
527
528 if (!result && class_hash) {
529 // Check ordinary classes
530 OBJC_LOCK (&classLock);
531 result = (id)NXHashGet(class_hash, &query);
532 OBJC_UNLOCK (&classLock);
533 }
534
535 if (!result && includeUnconnected && unconnected_class_hash) {
536 // Check not-yet-connected classes
537 OBJC_LOCK(&classLock);
538 result = (id)NXHashGet(unconnected_class_hash, &query);
539 OBJC_UNLOCK(&classLock);
540 }
541
542 if (!result && includeClassLoader && _objc_classLoader) {
543 // Try class loader callback
544 if ((*_objc_classLoader)(aClassName)) {
545 // Re-try lookup without class loader
546 includeClassLoader = NO;
547 goto retry;
548 }
549 }
550
551 if (!result && includeClassHandler && objc_classHandler) {
552 // Try class handler callback
553 if ((*objc_classHandler)(aClassName)) {
554 // Re-try lookup without class handler or class loader
555 includeClassLoader = NO;
556 includeClassHandler = NO;
557 goto retry;
558 }
559 }
560
561 return result;
562 }
563
564
565 /***********************************************************************
566 * objc_getClass. Return the id of the named class. If the class does
567 * not exist, call _objc_classLoader and then objc_classHandler, either of
568 * which may create a new class.
569 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
570 **********************************************************************/
571 id objc_getClass (const char * aClassName)
572 {
573 // NO unconnected, YES class handler
574 return look_up_class(aClassName, NO, YES);
575 }
576
577
578 /***********************************************************************
579 * objc_getRequiredClass.
580 * Same as objc_getClass, but kills the process if the class is not found.
581 * This is used by ZeroLink, where failing to find a class would be a
582 * compile-time link error without ZeroLink.
583 **********************************************************************/
584 id objc_getRequiredClass(const char *aClassName)
585 {
586 id cls = objc_getClass(aClassName);
587 if (!cls) _objc_fatal("link error: class '%s' not found.", aClassName);
588 return cls;
589 }
590
591
592 /***********************************************************************
593 * objc_lookUpClass. Return the id of the named class.
594 * If the class does not exist, call _objc_classLoader, which may create
595 * a new class.
596 *
597 * Formerly objc_getClassWithoutWarning ()
598 **********************************************************************/
599 id objc_lookUpClass (const char * aClassName)
600 {
601 // NO unconnected, NO class handler
602 return look_up_class(aClassName, NO, NO);
603 }
604
605 /***********************************************************************
606 * objc_getMetaClass. Return the id of the meta class the named class.
607 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
608 **********************************************************************/
609 id objc_getMetaClass (const char * aClassName)
610 {
611 struct objc_class * cls;
612
613 cls = objc_getClass (aClassName);
614 if (!cls)
615 {
616 _objc_inform ("class `%s' not linked into application", aClassName);
617 return Nil;
618 }
619
620 return cls->isa;
621 }
622
623 /***********************************************************************
624 * objc_addClass. Add the specified class to the table of known classes,
625 * after doing a little verification and fixup.
626 **********************************************************************/
627 void objc_addClass (struct objc_class *cls)
628 {
629 // Synchronize access to hash table
630 OBJC_LOCK (&classLock);
631
632 // Make sure both the class and the metaclass have caches!
633 // Clear all bits of the info fields except CLS_CLASS and CLS_META.
634 // Normally these bits are already clear but if someone tries to cons
635 // up their own class on the fly they might need to be cleared.
636 if (cls->cache == NULL) {
637 cls->cache = (Cache) &emptyCache;
638 cls->info = CLS_CLASS;
639 }
640
641 if (cls->isa->cache == NULL) {
642 cls->isa->cache = (Cache) &emptyCache;
643 cls->isa->info = CLS_META;
644 }
645
646 // methodLists should be:
647 // 1. NULL (Tiger and later only)
648 // 2. A -1 terminated method list array
649 // In either case, CLS_NO_METHOD_ARRAY remains clear.
650 // If the user manipulates the method list directly,
651 // they must use the magic private format.
652
653 // Add the class to the table
654 (void) NXHashInsert (class_hash, cls);
655
656 // Desynchronize
657 OBJC_UNLOCK (&classLock);
658 }
659
660 /***********************************************************************
661 * _objcTweakMethodListPointerForClass.
662 * Change the class's method list pointer to a method list array.
663 * Does nothing if the method list pointer is already a method list array.
664 * If the class is currently in use, methodListLock must be held by the caller.
665 **********************************************************************/
666 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
667 {
668 struct objc_method_list * originalList;
669 const int initialEntries = 4;
670 int mallocSize;
671 struct objc_method_list ** ptr;
672
673 // Do nothing if methodLists is already an array.
674 if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) return;
675
676 // Remember existing list
677 originalList = (struct objc_method_list *) cls->methodLists;
678
679 // Allocate and zero a method list array
680 mallocSize = sizeof(struct objc_method_list *) * initialEntries;
681 ptr = (struct objc_method_list **) _calloc_internal(1, mallocSize);
682
683 // Insert the existing list into the array
684 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
685 ptr[0] = originalList;
686
687 // Replace existing list with array
688 cls->methodLists = ptr;
689 _class_clearInfo(cls, CLS_NO_METHOD_ARRAY);
690 }
691
692
693 /***********************************************************************
694 * _objc_insertMethods.
695 * Adds methods to a class.
696 * Does not flush any method caches.
697 * Does not take any locks.
698 * If the class is already in use, use class_addMethods() instead.
699 **********************************************************************/
700 void _objc_insertMethods(struct objc_class *cls,
701 struct objc_method_list *mlist)
702 {
703 struct objc_method_list ***list;
704 struct objc_method_list **ptr;
705 int endIndex;
706 int oldSize;
707 int newSize;
708
709 if (!cls->methodLists) {
710 // cls has no methods - simply use this method list
711 cls->methodLists = (struct objc_method_list **)mlist;
712 _class_setInfo(cls, CLS_NO_METHOD_ARRAY);
713 return;
714 }
715
716 // Create method list array if necessary
717 _objcTweakMethodListPointerForClass(cls);
718
719 list = &cls->methodLists;
720
721 // Locate unused entry for insertion point
722 ptr = *list;
723 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
724 ptr += 1;
725
726 // If array is full, add to it
727 if (*ptr == END_OF_METHODS_LIST)
728 {
729 // Calculate old and new dimensions
730 endIndex = ptr - *list;
731 oldSize = (endIndex + 1) * sizeof(void *);
732 newSize = oldSize + sizeof(struct objc_method_list *); // only increase by 1
733
734 // Grow the method list array by one.
735 // This block may be from user code; don't use _realloc_internal
736 *list = (struct objc_method_list **)realloc(*list, newSize);
737
738 // Zero out addition part of new array
739 bzero (&((*list)[endIndex]), newSize - oldSize);
740
741 // Place new end marker
742 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
743
744 // Insertion point corresponds to old array end
745 ptr = &((*list)[endIndex]);
746 }
747
748 // Right shift existing entries by one
749 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
750
751 // Insert at method list at beginning of array
752 **list = mlist;
753 }
754
755 /***********************************************************************
756 * _objc_removeMethods.
757 * Remove methods from a class.
758 * Does not take any locks.
759 * Does not flush any method caches.
760 * If the class is currently in use, use class_removeMethods() instead.
761 **********************************************************************/
762 void _objc_removeMethods(struct objc_class *cls,
763 struct objc_method_list *mlist)
764 {
765 struct objc_method_list ***list;
766 struct objc_method_list **ptr;
767
768 if (cls->methodLists == NULL) {
769 // cls has no methods
770 return;
771 }
772 if (cls->methodLists == (struct objc_method_list **)mlist) {
773 // mlist is the class's only method list - erase it
774 cls->methodLists = NULL;
775 return;
776 }
777 if (cls->info & CLS_NO_METHOD_ARRAY) {
778 // cls has only one method list, and this isn't it - do nothing
779 return;
780 }
781
782 // cls has a method list array - search it
783
784 list = &cls->methodLists;
785
786 // Locate list in the array
787 ptr = *list;
788 while (*ptr != mlist) {
789 // fix for radar # 2538790
790 if ( *ptr == END_OF_METHODS_LIST ) return;
791 ptr += 1;
792 }
793
794 // Remove this entry
795 *ptr = 0;
796
797 // Left shift the following entries
798 while (*(++ptr) != END_OF_METHODS_LIST)
799 *(ptr-1) = *ptr;
800 *(ptr-1) = 0;
801 }
802
803 /***********************************************************************
804 * _objc_add_category. Install the specified category's methods and
805 * protocols into the class it augments.
806 * The class is assumed not to be in use yet: no locks are taken and
807 * no method caches are flushed.
808 **********************************************************************/
809 static inline void _objc_add_category(struct objc_class *cls, struct objc_category *category, int version)
810 {
811 if (PrintConnecting) {
812 _objc_inform("CONNECT: attaching category '%s (%s)'", cls->name, category->category_name);
813 }
814
815 // Augment instance methods
816 if (category->instance_methods)
817 _objc_insertMethods (cls, category->instance_methods);
818
819 // Augment class methods
820 if (category->class_methods)
821 _objc_insertMethods (cls->isa, category->class_methods);
822
823 // Augment protocols
824 if ((version >= 5) && category->protocols)
825 {
826 if (cls->isa->version >= 5)
827 {
828 category->protocols->next = cls->protocols;
829 cls->protocols = category->protocols;
830 cls->isa->protocols = category->protocols;
831 }
832 else
833 {
834 _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
835 _objc_inform ("class `%s' must be recompiled\n", category->class_name);
836 }
837 }
838 }
839
840 /***********************************************************************
841 * _objc_add_category_flush_caches. Install the specified category's
842 * methods into the class it augments, and flush the class' method cache.
843 **********************************************************************/
844 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
845 {
846 // Install the category's methods into its intended class
847 OBJC_LOCK(&methodListLock);
848 _objc_add_category (cls, category, version);
849 OBJC_UNLOCK(&methodListLock);
850
851 // Flush caches so category's methods can get called
852 _objc_flush_caches (cls);
853 }
854
855
856 /***********************************************************************
857 * reverse_cat
858 * Reverse the given linked list of pending categories.
859 * The pending category list is built backwards, and needs to be
860 * reversed before actually attaching the categories to a class.
861 * Returns the head of the new linked list.
862 **********************************************************************/
863 static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat)
864 {
865 if (!cat) return NULL;
866
867 _objc_unresolved_category *prev = NULL;
868 _objc_unresolved_category *cur = cat;
869 _objc_unresolved_category *ahead = cat->next;
870
871 while (cur) {
872 ahead = cur->next;
873 cur->next = prev;
874 prev = cur;
875 cur = ahead;
876 }
877
878 return prev;
879 }
880
881
882 /***********************************************************************
883 * resolve_categories_for_class.
884 * Install all existing categories intended for the specified class.
885 * cls must be a true class and not a metaclass.
886 **********************************************************************/
887 static void resolve_categories_for_class(struct objc_class *cls)
888 {
889 _objc_unresolved_category * pending;
890 _objc_unresolved_category * next;
891
892 // Nothing to do if there are no categories at all
893 if (!category_hash) return;
894
895 // Locate and remove first element in category list
896 // associated with this class
897 pending = NXMapKeyFreeingRemove (category_hash, cls->name);
898
899 // Traverse the list of categories, if any, registered for this class
900
901 // The pending list is built backwards. Reverse it and walk forwards.
902 pending = reverse_cat(pending);
903
904 while (pending) {
905 if (pending->cat) {
906 // Install the category
907 // use the non-flush-cache version since we are only
908 // called from the class intialization code
909 _objc_add_category(cls, pending->cat, pending->version);
910 }
911
912 // Delink and reclaim this registration
913 next = pending->next;
914 _free_internal(pending);
915 pending = next;
916 }
917 }
918
919
920 /***********************************************************************
921 * _objc_resolve_categories_for_class.
922 * Public version of resolve_categories_for_class. This was
923 * exported pre-10.4 for Omni et al. to workaround a problem
924 * with too-lazy category attachment.
925 * cls should be a class, but this function can also cope with metaclasses.
926 **********************************************************************/
927 void _objc_resolve_categories_for_class(struct objc_class *cls)
928 {
929
930 // If cls is a metaclass, get the class.
931 // resolve_categories_for_class() requires a real class to work correctly.
932 if (ISMETA(cls)) {
933 if (strncmp(cls->name, "_%", 2) == 0) {
934 // Posee's meta's name is smashed and isn't in the class_hash,
935 // so objc_getClass doesn't work.
936 char *baseName = strchr(cls->name, '%'); // get posee's real name
937 cls = objc_getClass(baseName);
938 } else {
939 cls = objc_getClass(cls->name);
940 }
941 }
942
943 resolve_categories_for_class(cls);
944 }
945
946
947 /***********************************************************************
948 * _objc_register_category.
949 * Process a category read from an image.
950 * If the category's class exists, attach the category immediately.
951 * If the category's class does not exist yet, pend the category for
952 * later attachment. Pending categories are attached in the order
953 * they were discovered.
954 **********************************************************************/
955 static void _objc_register_category(struct objc_category *cat, long version)
956 {
957 _objc_unresolved_category * new_cat;
958 _objc_unresolved_category * old;
959 struct objc_class *theClass;
960
961 // If the category's class exists, attach the category.
962 if ((theClass = objc_lookUpClass(cat->class_name))) {
963 _objc_add_category_flush_caches(theClass, cat, version);
964 return;
965 }
966
967 // If the category's class exists but is unconnected,
968 // then attach the category to the class but don't bother
969 // flushing any method caches (because they must be empty).
970 // YES unconnected, NO class_handler
971 if ((theClass = look_up_class(cat->class_name, YES, NO))) {
972 _objc_add_category(theClass, cat, version);
973 return;
974 }
975
976
977 // Category's class does not exist yet.
978 // Save the category for later attachment.
979
980 if (PrintConnecting) {
981 _objc_inform("CONNECT: pending category '%s (%s)'", cat->class_name, cat->category_name);
982 }
983
984 // Create category lookup table if needed
985 if (!category_hash)
986 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
987 128,
988 _objc_internal_zone ());
989
990 // Locate an existing list of categories, if any, for the class.
991 old = NXMapGet (category_hash, cat->class_name);
992
993 // Register the category to be fixed up later.
994 // The category list is built backwards, and is reversed again
995 // by resolve_categories_for_class().
996 new_cat = _malloc_internal(sizeof(_objc_unresolved_category));
997 new_cat->next = old;
998 new_cat->cat = cat;
999 new_cat->version = version;
1000 (void) NXMapKeyCopyingInsert (category_hash, cat->class_name, new_cat);
1001 }
1002
1003
1004 /***********************************************************************
1005 * _objc_read_categories_from_image.
1006 * Read all categories from the given image.
1007 * Install them on their parent classes, or register them for later
1008 * installation.
1009 * Register them for later +load, if implemented.
1010 **********************************************************************/
1011 static void _objc_read_categories_from_image (header_info * hi)
1012 {
1013 Module mods;
1014 unsigned int midx;
1015
1016 if (_objcHeaderIsReplacement(hi)) {
1017 // Ignore any categories in this image
1018 return;
1019 }
1020
1021
1022 // Major loop - process all modules in the header
1023 mods = hi->mod_ptr;
1024
1025 // NOTE: The module and category lists are traversed backwards
1026 // to preserve the pre-10.4 processing order. Changing the order
1027 // would have a small chance of introducing binary compatibility bugs.
1028 midx = hi->mod_count;
1029 while (midx-- > 0) {
1030 unsigned int index;
1031 unsigned int total;
1032
1033 // Nothing to do for a module without a symbol table
1034 if (mods[midx].symtab == NULL)
1035 continue;
1036
1037 // Total entries in symbol table (class entries followed
1038 // by category entries)
1039 total = mods[midx].symtab->cls_def_cnt +
1040 mods[midx].symtab->cat_def_cnt;
1041
1042 // Minor loop - register all categories from given module
1043 index = total;
1044 while (index-- > mods[midx].symtab->cls_def_cnt) {
1045 struct objc_category *cat = mods[midx].symtab->defs[index];
1046 _objc_register_category(cat, mods[midx].version);
1047 add_category_to_loadable_list(cat);
1048 }
1049 }
1050 }
1051
1052
1053 /***********************************************************************
1054 * _headerForAddress.
1055 * addr can be a class or a category
1056 **********************************************************************/
1057 static const header_info *_headerForAddress(void *addr)
1058 {
1059 unsigned long size;
1060 unsigned long seg;
1061 header_info * hInfo;
1062
1063 // Check all headers in the vector
1064 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1065 {
1066 // Locate header data, if any
1067 if (!hInfo->objcSegmentHeader) continue;
1068 seg = hInfo->objcSegmentHeader->vmaddr + hInfo->image_slide;
1069 size = hInfo->objcSegmentHeader->filesize;
1070
1071 // Is the class in this header?
1072 if ((seg <= (unsigned long) addr) &&
1073 ((unsigned long) addr < (seg + size)))
1074 return hInfo;
1075 }
1076
1077 // Not found
1078 return 0;
1079 }
1080
1081
1082 /***********************************************************************
1083 * _headerForClass
1084 * Return the image header containing this class, or NULL.
1085 * Returns NULL on runtime-constructed classes, and the NSCF classes.
1086 **********************************************************************/
1087 static const header_info *_headerForClass(struct objc_class *cls)
1088 {
1089 return _headerForAddress(cls);
1090 }
1091
1092
1093 /***********************************************************************
1094 * _nameForHeader.
1095 **********************************************************************/
1096 const char * _nameForHeader (const headerType * header)
1097 {
1098 return _getObjcHeaderName ((headerType *) header);
1099 }
1100
1101
1102 /***********************************************************************
1103 * class_is_connected.
1104 * Returns TRUE if class cls is connected.
1105 * A connected class has either a connected superclass or a NULL superclass,
1106 * and is present in class_hash.
1107 **********************************************************************/
1108 static BOOL class_is_connected(struct objc_class *cls)
1109 {
1110 BOOL result;
1111 OBJC_LOCK(&classLock);
1112 result = NXHashMember(class_hash, cls);
1113 OBJC_UNLOCK(&classLock);
1114 return result;
1115 }
1116
1117
1118 /***********************************************************************
1119 * pendingClassRefsMapTable. Return a pointer to the lookup table for
1120 * pending class refs.
1121 **********************************************************************/
1122 static inline NXMapTable *pendingClassRefsMapTable(void)
1123 {
1124 // Allocate table if needed
1125 if (!pendingClassRefsMap) {
1126 pendingClassRefsMap =
1127 NXCreateMapTableFromZone(NXStrValueMapPrototype,
1128 10, _objc_internal_zone ());
1129 }
1130
1131 // Return table pointer
1132 return pendingClassRefsMap;
1133 }
1134
1135
1136 /***********************************************************************
1137 * pendingSubclassesMapTable. Return a pointer to the lookup table for
1138 * pending subclasses.
1139 **********************************************************************/
1140 static inline NXMapTable *pendingSubclassesMapTable(void)
1141 {
1142 // Allocate table if needed
1143 if (!pendingSubclassesMap) {
1144 pendingSubclassesMap =
1145 NXCreateMapTableFromZone(NXStrValueMapPrototype,
1146 10, _objc_internal_zone ());
1147 }
1148
1149 // Return table pointer
1150 return pendingSubclassesMap;
1151 }
1152
1153
1154 /***********************************************************************
1155 * pendClassInstallation
1156 * Finish connecting class cls when its superclass becomes connected.
1157 * Check for multiple pends of the same class because connect_class does not.
1158 **********************************************************************/
1159 static void pendClassInstallation(struct objc_class *cls,
1160 const char *superName)
1161 {
1162 NXMapTable *table;
1163 PendingSubclass *pending;
1164 PendingSubclass *oldList;
1165 PendingSubclass *l;
1166
1167 // Create and/or locate pending class lookup table
1168 table = pendingSubclassesMapTable ();
1169
1170 // Make sure this class isn't already in the pending list.
1171 oldList = NXMapGet (table, superName);
1172 for (l = oldList; l != NULL; l = l->next) {
1173 if (l->subclass == cls) return; // already here, nothing to do
1174 }
1175
1176 // Create entry referring to this class
1177 pending = _malloc_internal(sizeof(PendingSubclass));
1178 pending->subclass = cls;
1179
1180 // Link new entry into head of list of entries for this class
1181 pending->next = oldList;
1182
1183 // (Re)place entry list in the table
1184 (void) NXMapKeyCopyingInsert (table, superName, pending);
1185 }
1186
1187
1188 /***********************************************************************
1189 * pendClassReference
1190 * Fix up a class ref when the class with the given name becomes connected.
1191 **********************************************************************/
1192 static void pendClassReference(struct objc_class **ref,
1193 const char *className)
1194 {
1195 NXMapTable *table;
1196 PendingClassRef *pending;
1197
1198 // Create and/or locate pending class lookup table
1199 table = pendingClassRefsMapTable ();
1200
1201 // Create entry containing the class reference
1202 pending = _malloc_internal(sizeof(PendingClassRef));
1203 pending->ref = ref;
1204
1205 // Link new entry into head of list of entries for this class
1206 pending->next = NXMapGet (table, className);
1207
1208 // (Re)place entry list in the table
1209 (void) NXMapKeyCopyingInsert (table, className, pending);
1210
1211 if (PrintConnecting) {
1212 _objc_inform("CONNECT: pended reference to class '%s' at %p",
1213 className, (void *)ref);
1214 }
1215 }
1216
1217
1218 /***********************************************************************
1219 * resolve_references_to_class
1220 * Fix up any pending class refs to this class.
1221 **********************************************************************/
1222 static void resolve_references_to_class(struct objc_class *cls)
1223 {
1224 PendingClassRef *pending;
1225
1226 if (!pendingClassRefsMap) return; // no unresolved refs for any class
1227
1228 pending = NXMapGet(pendingClassRefsMap, cls->name);
1229 if (!pending) return; // no unresolved refs for this class
1230
1231 NXMapKeyFreeingRemove(pendingClassRefsMap, cls->name);
1232
1233 if (PrintConnecting) {
1234 _objc_inform("CONNECT: resolving references to class '%s'", cls->name);
1235 }
1236
1237 while (pending) {
1238 PendingClassRef *next = pending->next;
1239 if (pending->ref) *pending->ref = cls;
1240 _free_internal(pending);
1241 pending = next;
1242 }
1243
1244 if (NXCountMapTable(pendingClassRefsMap) == 0) {
1245 NXFreeMapTable(pendingClassRefsMap);
1246 pendingClassRefsMap = NULL;
1247 }
1248 }
1249
1250
1251 /***********************************************************************
1252 * resolve_subclasses_of_class
1253 * Fix up any pending subclasses of this class.
1254 **********************************************************************/
1255 static void resolve_subclasses_of_class(struct objc_class *cls)
1256 {
1257 PendingSubclass *pending;
1258
1259 if (!pendingSubclassesMap) return; // no unresolved subclasses
1260
1261 pending = NXMapGet(pendingSubclassesMap, cls->name);
1262 if (!pending) return; // no unresolved subclasses for this class
1263
1264 NXMapKeyFreeingRemove(pendingSubclassesMap, cls->name);
1265
1266 // Destroy the pending table if it's now empty, to save memory.
1267 if (NXCountMapTable(pendingSubclassesMap) == 0) {
1268 NXFreeMapTable(pendingSubclassesMap);
1269 pendingSubclassesMap = NULL;
1270 }
1271
1272 if (PrintConnecting) {
1273 _objc_inform("CONNECT: resolving subclasses of class '%s'", cls->name);
1274 }
1275
1276 while (pending) {
1277 PendingSubclass *next = pending->next;
1278 if (pending->subclass) connect_class(pending->subclass);
1279 _free_internal(pending);
1280 pending = next;
1281 }
1282 }
1283
1284
1285 /***********************************************************************
1286 * get_base_method_list
1287 * Returns the method list containing the class's own methods,
1288 * ignoring any method lists added by categories or class_addMethods.
1289 * Called only by add_class_to_loadable_list.
1290 * Does not hold methodListLock because add_class_to_loadable_list
1291 * does not manipulate in-use classes.
1292 **********************************************************************/
1293 static struct objc_method_list *get_base_method_list(struct objc_class *cls)
1294 {
1295 struct objc_method_list **ptr;
1296
1297 if (!cls->methodLists) return NULL;
1298 if (cls->info & CLS_NO_METHOD_ARRAY) return (struct objc_method_list *)cls->methodLists;
1299 ptr = cls->methodLists;
1300 if (!*ptr || *ptr == END_OF_METHODS_LIST) return NULL;
1301 while ( *ptr != 0 && *ptr != END_OF_METHODS_LIST ) { ptr++; }
1302 --ptr;
1303 return *ptr;
1304 }
1305
1306
1307 /***********************************************************************
1308 * add_class_to_loadable_list
1309 * Class cls has just become connected. Schedule it for +load if
1310 * it implements a +load method.
1311 **********************************************************************/
1312 static void add_class_to_loadable_list(struct objc_class *cls)
1313 {
1314 IMP method = NULL;
1315 struct objc_method_list *mlist;
1316
1317 if (cls->isa->info & CLS_HAS_LOAD_METHOD) {
1318 mlist = get_base_method_list(cls->isa);
1319 if (mlist) {
1320 method = lookupNamedMethodInMethodList (mlist, "load");
1321 }
1322 }
1323 // Don't bother if cls has no +load method
1324 if (!method) return;
1325
1326 if (PrintLoading) {
1327 _objc_inform("LOAD: class '%s' scheduled for +load", cls->name);
1328 }
1329
1330 if (loadable_classes_used == loadable_classes_allocated) {
1331 loadable_classes_allocated = loadable_classes_allocated*2 + 16;
1332 loadable_classes =
1333 _realloc_internal(loadable_classes,
1334 loadable_classes_allocated *
1335 sizeof(struct loadable_class));
1336 }
1337
1338 loadable_classes[loadable_classes_used].cls = cls;
1339 loadable_classes[loadable_classes_used].method = method;
1340 loadable_classes_used++;
1341 }
1342
1343
1344 /***********************************************************************
1345 * add_category_to_loadable_list
1346 * Category cat's parent class exists and the category has been attached
1347 * to its class. Schedule this category for +load after its parent class
1348 * becomes connected and has its own +load method called.
1349 **********************************************************************/
1350 static void add_category_to_loadable_list(struct objc_category *cat)
1351 {
1352 IMP method = NULL;
1353 struct objc_method_list *mlist;
1354
1355 mlist = cat->class_methods;
1356 if (mlist) {
1357 method = lookupNamedMethodInMethodList (mlist, "load");
1358 }
1359 // Don't bother if cat has no +load method
1360 if (!method) return;
1361
1362 if (PrintLoading) {
1363 _objc_inform("LOAD: category '%s(%s)' scheduled for +load",
1364 cat->class_name, cat->category_name);
1365 }
1366
1367 if (loadable_categories_used == loadable_categories_allocated) {
1368 loadable_categories_allocated = loadable_categories_allocated*2 + 16;
1369 loadable_categories =
1370 _realloc_internal(loadable_categories,
1371 loadable_categories_allocated *
1372 sizeof(struct loadable_category));
1373 }
1374
1375 loadable_categories[loadable_categories_used].cat = cat;
1376 loadable_categories[loadable_categories_used].method = method;
1377 loadable_categories_used++;
1378 }
1379
1380
1381 /***********************************************************************
1382 * remove_class_from_loadable_list
1383 * Class cls may have been loadable before, but it is now no longer
1384 * loadable (because its image is being unmapped).
1385 **********************************************************************/
1386 static void remove_class_from_loadable_list(struct objc_class *cls)
1387 {
1388 if (loadable_classes) {
1389 int i;
1390 for (i = 0; i < loadable_classes_used; i++) {
1391 if (loadable_classes[i].cls == cls) {
1392 loadable_classes[i].cls = NULL;
1393 if (PrintLoading) {
1394 _objc_inform("LOAD: class '%s' unscheduled for +load", cls->name);
1395 }
1396 return;
1397 }
1398 }
1399 }
1400 }
1401
1402
1403 /***********************************************************************
1404 * remove_category_from_loadable_list
1405 * Category cat may have been loadable before, but it is now no longer
1406 * loadable (because its image is being unmapped).
1407 **********************************************************************/
1408 static void remove_category_from_loadable_list(struct objc_category *cat)
1409 {
1410 if (loadable_categories) {
1411 int i;
1412 for (i = 0; i < loadable_categories_used; i++) {
1413 if (loadable_categories[i].cat == cat) {
1414 loadable_categories[i].cat = NULL;
1415 if (PrintLoading) {
1416 _objc_inform("LOAD: category '%s(%s)' unscheduled for +load",
1417 cat->class_name, cat->category_name);
1418 }
1419 return;
1420 }
1421 }
1422 }
1423 }
1424
1425
1426 /***********************************************************************
1427 * call_class_loads
1428 * Call all pending class +load methods.
1429 * If new classes become loadable, +load is NOT called for them.
1430 *
1431 * Called only by call_load_methods().
1432 **********************************************************************/
1433 static void call_class_loads(void)
1434 {
1435 int i;
1436
1437 // Detach current loadable list.
1438 struct loadable_class *classes = loadable_classes;
1439 int used = loadable_classes_used;
1440 loadable_classes = NULL;
1441 loadable_classes_allocated = 0;
1442 loadable_classes_used = 0;
1443
1444 // Call all +loads for the detached list.
1445 for (i = 0; i < used; i++) {
1446 struct objc_class *cls = classes[i].cls;
1447 IMP load_method = classes[i].method;
1448 if (!cls) continue;
1449
1450 if (PrintLoading) {
1451 _objc_inform("LOAD: +[%s load]\n", cls->name);
1452 }
1453 (*load_method) ((id) cls, @selector(load));
1454 }
1455
1456 // Destroy the detached list.
1457 if (classes) _free_internal(classes);
1458 }
1459
1460
1461 /***********************************************************************
1462 * call_category_loads
1463 * Call some pending category +load methods.
1464 * The parent class of the +load-implementing categories has all of
1465 * its categories attached, in case some are lazily waiting for +initalize.
1466 * Don't call +load unless the parent class is connected.
1467 * If new categories become loadable, +load is NOT called, and they
1468 * are added to the end of the loadable list, and we return TRUE.
1469 * Return FALSE if no new categories became loadable.
1470 *
1471 * Called only by call_load_methods().
1472 **********************************************************************/
1473 static BOOL call_category_loads(void)
1474 {
1475 int i, shift;
1476 BOOL new_categories_added = NO;
1477
1478 // Detach current loadable list.
1479 struct loadable_category *cats = loadable_categories;
1480 int used = loadable_categories_used;
1481 int allocated = loadable_categories_allocated;
1482 loadable_categories = NULL;
1483 loadable_categories_allocated = 0;
1484 loadable_categories_used = 0;
1485
1486 // Call all +loads for the detached list.
1487 for (i = 0; i < used; i++) {
1488 struct objc_category *cat = cats[i].cat;
1489 IMP load_method = cats[i].method;
1490 struct objc_class *cls;
1491 if (!cat) continue;
1492
1493 cls = objc_getClass(cat->class_name);
1494 if (cls && class_is_connected(cls)) {
1495 if (PrintLoading) {
1496 _objc_inform("LOAD: +[%s(%s) load]\n",
1497 cls->name, cat->category_name);
1498 }
1499 (*load_method) ((id) cls, @selector(load));
1500 cats[i].cat = NULL;
1501 }
1502 }
1503
1504 // Compact detached list (order-preserving)
1505 shift = 0;
1506 for (i = 0; i < used; i++) {
1507 if (cats[i].cat) {
1508 cats[i-shift] = cats[i];
1509 } else {
1510 shift++;
1511 }
1512 }
1513 used -= shift;
1514
1515 // Copy any new +load candidates from the new list to the detached list.
1516 new_categories_added = (loadable_categories_used > 0);
1517 for (i = 0; i < loadable_categories_used; i++) {
1518 if (used == allocated) {
1519 allocated = allocated*2 + 16;
1520 cats = _realloc_internal(cats, allocated *
1521 sizeof(struct loadable_category));
1522 }
1523 cats[used++] = loadable_categories[i];
1524 }
1525
1526 // Destroy the new list.
1527 if (loadable_categories) _free_internal(loadable_categories);
1528
1529 // Reattach the (now augmented) detached list.
1530 // But if there's nothing left to load, destroy the list.
1531 if (used) {
1532 loadable_categories = cats;
1533 loadable_categories_used = used;
1534 loadable_categories_allocated = allocated;
1535 } else {
1536 if (cats) _free_internal(cats);
1537 loadable_categories = NULL;
1538 loadable_categories_used = 0;
1539 loadable_categories_allocated = 0;
1540 }
1541
1542 if (PrintLoading) {
1543 if (loadable_categories_used != 0) {
1544 _objc_inform("LOAD: %d categories still waiting for +load\n",
1545 loadable_categories_used);
1546 }
1547 }
1548
1549 return new_categories_added;
1550 }
1551
1552
1553 /***********************************************************************
1554 * call_load_methods
1555 * Call all pending class and category +load methods.
1556 * Class +load methods are called superclass-first.
1557 * Category +load methods are not called until after the parent class's +load.
1558 *
1559 * This method must be RE-ENTRANT, because a +load could trigger
1560 * more image mapping. In addition, the superclass-first ordering
1561 * must be preserved in the face of re-entrant calls. Therefore,
1562 * only the OUTERMOST call of this function will do anything, and
1563 * that call will handle all loadable classes, even those generated
1564 * while it was running.
1565 *
1566 * The sequence below preserves +load ordering in the face of
1567 * image loading during a +load, and make sure that no
1568 * +load method is forgotten because it was added during
1569 * a +load call.
1570 * Sequence:
1571 * 1. Repeatedly call class +loads until there aren't any more
1572 * 2. Call category +loads ONCE.
1573 * 3. Run more +loads if:
1574 * (a) there are more classes to load, OR
1575 * (b) there are some potential category +loads that have
1576 * still never been attempted.
1577 * Category +loads are only run once to ensure "parent class first"
1578 * ordering, even if a category +load triggers a new loadable class
1579 * and a new loadable category attached to that class.
1580 *
1581 * fixme this is not thread-safe, but neither is the rest of image mapping.
1582 **********************************************************************/
1583 static void call_load_methods(void)
1584 {
1585 static pthread_t load_method_thread NOBSS = NULL;
1586 BOOL more_categories;
1587
1588 if (load_method_thread) {
1589 // +loads are already being called. Do nothing, but complain
1590 // if it looks like multithreaded use of this thread-unsafe code.
1591
1592 if (! pthread_equal(load_method_thread, pthread_self())) {
1593 _objc_inform("WARNING: multi-threaded library loading detected "
1594 "(implementation is not thread-safe)");
1595 }
1596 return;
1597 }
1598
1599 // Nobody else is calling +loads, so we should do it ourselves.
1600 load_method_thread = pthread_self();
1601
1602 do {
1603 // 1. Repeatedly call class +loads until there aren't any more
1604 while (loadable_classes_used > 0) {
1605 call_class_loads();
1606 }
1607
1608 // 2. Call category +loads ONCE
1609 more_categories = call_category_loads();
1610
1611 // 3. Run more +loads if there are classes OR more untried categories
1612 } while (loadable_classes_used > 0 || more_categories);
1613
1614 load_method_thread = NULL;
1615 }
1616
1617
1618 /***********************************************************************
1619 * really_connect_class
1620 * Connect cls to superclass supercls unconditionally.
1621 * Also adjust the class hash tables and handle +load and pended subclasses.
1622 *
1623 * This should be called from connect_class() ONLY.
1624 **********************************************************************/
1625 static void really_connect_class(struct objc_class *cls,
1626 struct objc_class *supercls)
1627 {
1628 struct objc_class *oldCls;
1629 struct objc_class *meta = cls->isa;
1630
1631 // Wire the classes together.
1632 if (supercls) {
1633 cls->super_class = supercls;
1634 meta->super_class = supercls->isa;
1635 meta->isa = supercls->isa->isa;
1636 } else {
1637 cls->super_class = NULL; // superclass of root class is NULL
1638 meta->super_class = cls; // superclass of root metaclass is root class
1639 meta->isa = meta; // metaclass of root metaclass is root metaclass
1640 }
1641
1642 OBJC_LOCK(&classLock);
1643
1644 // Update hash tables.
1645 NXHashRemove(unconnected_class_hash, cls);
1646 oldCls = NXHashInsert(class_hash, cls);
1647
1648 // Delete unconnected_class_hash if it is now empty.
1649 if (NXCountHashTable(unconnected_class_hash) == 0) {
1650 NXFreeHashTable(unconnected_class_hash);
1651 unconnected_class_hash = NULL;
1652 }
1653
1654 OBJC_UNLOCK(&classLock);
1655
1656 // Warn if the new class has the same name as a previously-installed class.
1657 // The new class is kept and the old class is discarded.
1658 if (oldCls) {
1659 const header_info *oldHeader = _headerForClass(oldCls);
1660 const header_info *newHeader = _headerForClass(cls);
1661 const char *oldName = _nameForHeader(oldHeader->mhdr);
1662 const char *newName = _nameForHeader(newHeader->mhdr);
1663
1664 _objc_inform ("Both %s and %s have implementations of class %s.",
1665 oldName, newName, oldCls->name);
1666 _objc_inform ("Using implementation from %s.", newName);
1667 }
1668
1669 // Prepare for +load and connect newly-connectable subclasses
1670 add_class_to_loadable_list(cls);
1671 resolve_subclasses_of_class(cls);
1672
1673 // GC debugging: make sure all classes with -dealloc also have -finalize
1674 if (CheckFinalizers) {
1675 extern IMP findIMPInClass(Class cls, SEL sel);
1676 if (findIMPInClass(cls, sel_getUid("dealloc")) &&
1677 ! findIMPInClass(cls, sel_getUid("finalize")))
1678 {
1679 _objc_inform("GC: class '%s' implements -dealloc but not -finalize", cls->name);
1680 }
1681 }
1682
1683 // Debugging: if this class has ivars, make sure this class's ivars don't
1684 // overlap with its super's. This catches some broken fragile base classes.
1685 // Do not use super->instance_size vs. self->ivar[0] to check this.
1686 // Ivars may be packed across instance_size boundaries.
1687 if (DebugFragileSuperclasses && cls->ivars && cls->ivars->ivar_count) {
1688 struct objc_class *ivar_cls = supercls;
1689
1690 // Find closest superclass that has some ivars, if one exists.
1691 while (ivar_cls &&
1692 (!ivar_cls->ivars || ivar_cls->ivars->ivar_count == 0))
1693 {
1694 ivar_cls = ivar_cls->super_class;
1695 }
1696
1697 if (ivar_cls) {
1698 // Compare superclass's last ivar to this class's first ivar
1699 struct objc_ivar *super_ivar =
1700 &ivar_cls->ivars->ivar_list[ivar_cls->ivars->ivar_count - 1];
1701 struct objc_ivar *self_ivar =
1702 &cls->ivars->ivar_list[0];
1703
1704 // fixme could be smarter about super's ivar size
1705 if (self_ivar->ivar_offset <= super_ivar->ivar_offset) {
1706 _objc_inform("WARNING: ivars of superclass '%s' and "
1707 "subclass '%s' overlap; superclass may have "
1708 "changed since subclass was compiled",
1709 ivar_cls->name, cls->name);
1710 }
1711 }
1712 }
1713 }
1714
1715
1716 /***********************************************************************
1717 * connect_class
1718 * Connect class cls to its superclasses, if possible.
1719 * If cls becomes connected, move it from unconnected_class_hash
1720 * to connected_class_hash.
1721 * Returns TRUE if cls is connected.
1722 * Returns FALSE if cls could not be connected for some reason
1723 * (missing superclass or still-unconnected superclass)
1724 **********************************************************************/
1725 static BOOL connect_class(struct objc_class *cls)
1726 {
1727 if (class_is_connected(cls)) {
1728 // This class is already connected to its superclass.
1729 // Do nothing.
1730 return TRUE;
1731 }
1732 else if (cls->super_class == NULL) {
1733 // This class is a root class.
1734 // Connect it to itself.
1735
1736 if (PrintConnecting) {
1737 _objc_inform("CONNECT: class '%s' now connected (root class)",
1738 cls->name);
1739 }
1740
1741 really_connect_class(cls, NULL);
1742 return TRUE;
1743 }
1744 else {
1745 // This class is not a root class and is not yet connected.
1746 // Connect it if its superclass and root class are already connected.
1747 // Otherwise, add this class to the to-be-connected list,
1748 // pending the completion of its superclass and root class.
1749
1750 // At this point, cls->super_class and cls->isa->isa are still STRINGS
1751 char *supercls_name = (char *)cls->super_class;
1752 struct objc_class *supercls;
1753
1754 // YES unconnected, YES class handler
1755 if (NULL == (supercls = look_up_class(supercls_name, YES, YES))) {
1756 // Superclass does not exist yet.
1757 // pendClassInstallation will handle duplicate pends of this class
1758 pendClassInstallation(cls, supercls_name);
1759
1760 if (PrintConnecting) {
1761 _objc_inform("CONNECT: class '%s' NOT connected (missing super)", cls->name);
1762 }
1763 return FALSE;
1764 }
1765
1766 if (! connect_class(supercls)) {
1767 // Superclass exists but is not yet connected.
1768 // pendClassInstallation will handle duplicate pends of this class
1769 pendClassInstallation(cls, supercls_name);
1770
1771 if (PrintConnecting) {
1772 _objc_inform("CONNECT: class '%s' NOT connected (unconnected super)", cls->name);
1773 }
1774 return FALSE;
1775 }
1776
1777 // Superclass exists and is connected.
1778 // Connect this class to the superclass.
1779
1780 if (PrintConnecting) {
1781 _objc_inform("CONNECT: class '%s' now connected", cls->name);
1782 }
1783
1784 really_connect_class(cls, supercls);
1785 return TRUE;
1786 }
1787 }
1788
1789
1790 /***********************************************************************
1791 * _objc_read_classes_from_image.
1792 * Read classes from the given image, perform assorted minor fixups,
1793 * scan for +load implementation.
1794 * Does not connect classes to superclasses.
1795 * Does attach pended categories to the classes.
1796 * Adds all classes to unconnected_class_hash. class_hash is unchanged.
1797 **********************************************************************/
1798 static void _objc_read_classes_from_image(header_info *hi)
1799 {
1800 unsigned int index;
1801 unsigned int midx;
1802 Module mods;
1803 int isBundle = (hi->mhdr->filetype == MH_BUNDLE);
1804
1805 if (_objcHeaderIsReplacement(hi)) {
1806 // Ignore any classes in this image
1807 return;
1808 }
1809
1810 // class_hash starts small, enough only for libobjc itself.
1811 // If other Objective-C libraries are found, immediately resize
1812 // class_hash, assuming that Foundation and AppKit are about
1813 // to add lots of classes.
1814 OBJC_LOCK(&classLock);
1815 if (hi->mhdr != &_mh_dylib_header && _NXHashCapacity(class_hash) < 1024) {
1816 _NXHashRehashToCapacity(class_hash, 1024);
1817 }
1818 OBJC_UNLOCK(&classLock);
1819
1820 // Major loop - process all modules in the image
1821 mods = hi->mod_ptr;
1822 for (midx = 0; midx < hi->mod_count; midx += 1)
1823 {
1824 // Skip module containing no classes
1825 if (mods[midx].symtab == NULL)
1826 continue;
1827
1828 // Minor loop - process all the classes in given module
1829 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
1830 {
1831 struct objc_class * newCls;
1832 struct objc_method_list *mlist;
1833
1834 // Locate the class description pointer
1835 newCls = mods[midx].symtab->defs[index];
1836
1837 // Classes loaded from Mach-O bundles can be unloaded later.
1838 // Nothing uses this class yet, so _class_setInfo is not needed.
1839 if (isBundle) newCls->info |= CLS_FROM_BUNDLE;
1840 if (isBundle) newCls->isa->info |= CLS_FROM_BUNDLE;
1841
1842 // Use common static empty cache instead of NULL
1843 if (newCls->cache == NULL)
1844 newCls->cache = (Cache) &emptyCache;
1845 if (newCls->isa->cache == NULL)
1846 newCls->isa->cache = (Cache) &emptyCache;
1847
1848 // Set metaclass version
1849 newCls->isa->version = mods[midx].version;
1850
1851 // methodLists is NULL or a single list, not an array
1852 newCls->info |= CLS_NO_METHOD_ARRAY;
1853 newCls->isa->info |= CLS_NO_METHOD_ARRAY;
1854
1855 // Check for +load implementation before categories are attached
1856 if ((mlist = get_base_method_list(newCls->isa))) {
1857 if (lookupNamedMethodInMethodList (mlist, "load")) {
1858 newCls->isa->info |= CLS_HAS_LOAD_METHOD;
1859 }
1860 }
1861
1862 // Install into unconnected_class_hash
1863 OBJC_LOCK(&classLock);
1864 if (!unconnected_class_hash) {
1865 unconnected_class_hash =
1866 NXCreateHashTableFromZone(classHashPrototype, 128, NULL,
1867 _objc_internal_zone());
1868 }
1869 NXHashInsert(unconnected_class_hash, newCls);
1870 OBJC_UNLOCK(&classLock);
1871
1872 // Fix up pended class refs to this class, if any
1873 resolve_references_to_class(newCls);
1874
1875 // Attach pended categories for this class, if any
1876 resolve_categories_for_class(newCls);
1877 }
1878 }
1879 }
1880
1881
1882 /***********************************************************************
1883 * _objc_connect_classes_from_image.
1884 * Connect the classes in the given image to their superclasses,
1885 * or register them for later connection if any superclasses are missing.
1886 **********************************************************************/
1887 static void _objc_connect_classes_from_image(header_info *hi)
1888 {
1889 unsigned int index;
1890 unsigned int midx;
1891 Module mods;
1892 BOOL replacement = _objcHeaderIsReplacement(hi);
1893
1894 // Major loop - process all modules in the image
1895 mods = hi->mod_ptr;
1896 for (midx = 0; midx < hi->mod_count; midx += 1)
1897 {
1898 // Skip module containing no classes
1899 if (mods[midx].symtab == NULL)
1900 continue;
1901
1902 // Minor loop - process all the classes in given module
1903 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
1904 {
1905 struct objc_class *cls = mods[midx].symtab->defs[index];
1906 if (! replacement) {
1907 BOOL connected = connect_class(cls);
1908 if (connected && callbackFunction) {
1909 (*callbackFunction)(cls, 0);
1910 }
1911 } else {
1912 // Replacement image - fix up super_class only (#3704817)
1913 const char *super_name = (const char *) cls->super_class;
1914 if (super_name) cls->super_class = objc_getClass(super_name);
1915 }
1916 }
1917 }
1918 }
1919
1920
1921 /***********************************************************************
1922 * _objc_map_class_refs_for_image. Convert the class ref entries from
1923 * a class name string pointer to a class pointer. If the class does
1924 * not yet exist, the reference is added to a list of pending references
1925 * to be fixed up at a later date.
1926 **********************************************************************/
1927 static void _objc_map_class_refs_for_image (header_info * hi)
1928 {
1929 struct objc_class * * cls_refs;
1930 unsigned int size;
1931 unsigned int index;
1932
1933 // Locate class refs in image
1934 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
1935 if (!cls_refs)
1936 return;
1937 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
1938
1939 // Process each class ref
1940 for (index = 0; index < size; index += 1)
1941 {
1942 const char * ref;
1943 struct objc_class * cls;
1944
1945 // Get ref to convert from name string to class pointer
1946 ref = (const char *) cls_refs[index];
1947
1948 // Get pointer to class of this name
1949 // YES unconnected, YES class loader
1950 cls = look_up_class(ref, YES, YES);
1951 if (cls) {
1952 // Referenced class exists. Fix up the reference.
1953 cls_refs[index] = cls;
1954 } else {
1955 // Referenced class does not exist yet. Insert a placeholder
1956 // class and fix up the reference later.
1957 pendClassReference (&cls_refs[index], ref);
1958 cls_refs[index] = _objc_getNonexistentClass ();
1959 }
1960 }
1961 }
1962
1963
1964 /***********************************************************************
1965 * _objc_remove_pending_class_refs_in_image
1966 * Delete any pending class ref fixups for class refs in the given image,
1967 * because the image is about to be unloaded.
1968 **********************************************************************/
1969 static void _objc_remove_pending_class_refs_in_image(header_info *hi)
1970 {
1971 struct objc_class **cls_refs, **cls_refs_end;
1972 unsigned int size;
1973
1974 if (!pendingClassRefsMap) return;
1975
1976 // Locate class refs in this image
1977 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
1978 if (!cls_refs)
1979 return;
1980 cls_refs = (struct objc_class **) ((uintptr_t)cls_refs + hi->image_slide);
1981 cls_refs_end = (struct objc_class **)(size + (uintptr_t)cls_refs);
1982
1983 // Search the pending class ref table for class refs in this range.
1984 // The class refs may have already been stomped with nonexistentClass,
1985 // so there's no way to recover the original class name.
1986
1987 const char *key;
1988 PendingClassRef *pending;
1989 NXMapState state = NXInitMapState(pendingClassRefsMap);
1990 while(NXNextMapState(pendingClassRefsMap, &state,
1991 (const void **)&key, (const void **)&pending))
1992 {
1993 for ( ; pending != NULL; pending = pending->next) {
1994 if (pending->ref >= cls_refs && pending->ref < cls_refs_end) {
1995 pending->ref = NULL;
1996 }
1997 }
1998 }
1999 }
2000
2001
2002 /***********************************************************************
2003 * map_selrefs. Register each selector in the specified array. If a
2004 * given selector is already registered, update this array to point to
2005 * the registered selector string.
2006 * If copy is TRUE, all selector data is always copied. This is used
2007 * for registering selectors from unloadable bundles, so the selector
2008 * can still be used after the bundle's data segment is unmapped.
2009 * Returns YES if dst was written to, NO if it was unchanged.
2010 **********************************************************************/
2011 static inline BOOL map_selrefs(SEL *src, SEL *dst, size_t size, BOOL copy)
2012 {
2013 BOOL result = NO;
2014 unsigned int cnt = size / sizeof(SEL);
2015 unsigned int index;
2016
2017 sel_lock();
2018
2019 // Process each selector
2020 for (index = 0; index < cnt; index += 1)
2021 {
2022 SEL sel;
2023
2024 // Lookup pointer to uniqued string
2025 sel = sel_registerNameNoLock((const char *) src[index], copy);
2026
2027 // Replace this selector with uniqued one (avoid
2028 // modifying the VM page if this would be a NOP)
2029 if (dst[index] != sel) {
2030 dst[index] = sel;
2031 result = YES;
2032 }
2033 }
2034
2035 sel_unlock();
2036
2037 return result;
2038 }
2039
2040
2041 /***********************************************************************
2042 * map_method_descs. For each method in the specified method list,
2043 * replace the name pointer with a uniqued selector.
2044 * If copy is TRUE, all selector data is always copied. This is used
2045 * for registering selectors from unloadable bundles, so the selector
2046 * can still be used after the bundle's data segment is unmapped.
2047 **********************************************************************/
2048 static void map_method_descs (struct objc_method_description_list * methods, BOOL copy)
2049 {
2050 unsigned int index;
2051
2052 sel_lock();
2053
2054 // Process each method
2055 for (index = 0; index < methods->count; index += 1)
2056 {
2057 struct objc_method_description * method;
2058 SEL sel;
2059
2060 // Get method entry to fix up
2061 method = &methods->list[index];
2062
2063 // Lookup pointer to uniqued string
2064 sel = sel_registerNameNoLock((const char *) method->name, copy);
2065
2066 // Replace this selector with uniqued one (avoid
2067 // modifying the VM page if this would be a NOP)
2068 if (method->name != sel)
2069 method->name = sel;
2070 }
2071
2072 sel_unlock();
2073 }
2074
2075 /***********************************************************************
2076 * _fixup.
2077 **********************************************************************/
2078 @interface Protocol(RuntimePrivate)
2079 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
2080 @end
2081
2082 /***********************************************************************
2083 * _objc_fixup_protocol_objects_for_image. For each protocol in the
2084 * specified image, selectorize the method names and call +_fixup.
2085 **********************************************************************/
2086 static void _objc_fixup_protocol_objects_for_image (header_info * hi)
2087 {
2088 unsigned int size;
2089 OBJC_PROTOCOL_PTR protos;
2090 unsigned int index;
2091 int isBundle = hi->mhdr->filetype == MH_BUNDLE;
2092
2093 // Locate protocols in the image
2094 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
2095 if (!protos)
2096 return;
2097
2098 // Apply the slide bias
2099 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
2100
2101 // Process each protocol
2102 for (index = 0; index < size; index += 1)
2103 {
2104 // Selectorize the instance methods
2105 if (protos[index] OBJC_PROTOCOL_DEREF instance_methods)
2106 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF instance_methods, isBundle);
2107
2108 // Selectorize the class methods
2109 if (protos[index] OBJC_PROTOCOL_DEREF class_methods)
2110 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF class_methods, isBundle);
2111 }
2112
2113 // Invoke Protocol class method to fix up the protocol
2114 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
2115 }
2116
2117 /***********************************************************************
2118 * _objc_headerStart. Return what headers we know about.
2119 **********************************************************************/
2120 header_info * _objc_headerStart ()
2121 {
2122
2123 // Take advatage of our previous work
2124 return FirstHeader;
2125 }
2126
2127 void _objc_bindModuleContainingList() {
2128 /* We define this for backwards binary compat with things which should not
2129 * have been using it (cough OmniWeb), but now it does nothing for them.
2130 */
2131 }
2132
2133
2134 /***********************************************************************
2135 * _objc_addHeader.
2136 **********************************************************************/
2137
2138 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
2139 #define HINFO_SIZE 16
2140
2141 static int HeaderInfoCounter NOBSS = 0;
2142 static header_info HeaderInfoTable[HINFO_SIZE] NOBSS = { {0} };
2143
2144 static header_info * _objc_addHeader(const struct mach_header *header)
2145 {
2146 int mod_count = 0;
2147 uintptr_t mod_unslid;
2148 uint32_t info_size = 0;
2149 uintptr_t image_info_unslid;
2150 const struct segment_command *objc_segment;
2151 ptrdiff_t slide;
2152 header_info *result;
2153
2154 // Locate the __OBJC segment
2155 objc_segment = getsegbynamefromheader(header, SEG_OBJC);
2156 if (!objc_segment) return NULL;
2157
2158 // Locate some sections in the __OBJC segment
2159 mod_unslid = (uintptr_t)_getObjcModules(header, &mod_count);
2160 if (!mod_unslid) return NULL;
2161 image_info_unslid = (uintptr_t)_getObjcImageInfo(header, &info_size);
2162
2163 // Calculate vm slide.
2164 slide = _getImageSlide(header);
2165
2166
2167 // Find or allocate a header_info entry.
2168 if (HeaderInfoCounter < HINFO_SIZE) {
2169 result = &HeaderInfoTable[HeaderInfoCounter++];
2170 } else {
2171 result = _malloc_internal(sizeof(header_info));
2172 }
2173
2174 // Set up the new header_info entry.
2175 result->mhdr = header;
2176 result->mod_ptr = (Module)(mod_unslid + slide);
2177 result->mod_count = mod_count;
2178 result->image_slide = slide;
2179 result->objcSegmentHeader = objc_segment;
2180 if (image_info_unslid) {
2181 result->info = (objc_image_info *)(image_info_unslid + slide);
2182 } else {
2183 result->info = NULL;
2184 }
2185
2186 // Make sure every copy of objc_image_info in this image is the same.
2187 // This means same version and same bitwise contents.
2188 if (result->info) {
2189 objc_image_info *start = result->info;
2190 objc_image_info *end =
2191 (objc_image_info *)(info_size + (uint8_t *)start);
2192 objc_image_info *info = start;
2193 while (info < end) {
2194 // version is byte size, except for version 0
2195 size_t struct_size = info->version;
2196 if (struct_size == 0) struct_size = 2 * sizeof(uint32_t);
2197 if (info->version != start->version ||
2198 0 != memcmp(info, start, struct_size))
2199 {
2200 _objc_fatal("'%s' has inconsistently-compiled Objective-C "
2201 "code. Please recompile all code in it.",
2202 _nameForHeader(header));
2203 }
2204 info = (objc_image_info *)(struct_size + (uint8_t *)info);
2205 }
2206 }
2207
2208 // Add the header to the header list.
2209 // The header is appended to the list, to preserve the bottom-up order.
2210 result->next = NULL;
2211 if (!FirstHeader) {
2212 // list is empty
2213 FirstHeader = LastHeader = result;
2214 } else {
2215 if (!LastHeader) {
2216 // list is not empty, but LastHeader is invalid - recompute it
2217 LastHeader = FirstHeader;
2218 while (LastHeader->next) LastHeader = LastHeader->next;
2219 }
2220 // LastHeader is now valid
2221 LastHeader->next = result;
2222 LastHeader = result;
2223 }
2224
2225 return result;
2226 }
2227
2228
2229 /***********************************************************************
2230 * _objc_RemoveHeader
2231 * Remove the given header from the header list.
2232 * FirstHeader is updated.
2233 * LastHeader is set to NULL. Any code that uses LastHeader must
2234 * detect this NULL and recompute LastHeader by traversing the list.
2235 **********************************************************************/
2236 static void _objc_removeHeader(header_info *hi)
2237 {
2238 header_info **hiP;
2239
2240 for (hiP = &FirstHeader; *hiP != NULL; hiP = &(**hiP).next) {
2241 if (*hiP == hi) {
2242 header_info *deadHead = *hiP;
2243
2244 // Remove from the linked list (updating FirstHeader if necessary).
2245 *hiP = (**hiP).next;
2246
2247 // Update LastHeader if necessary.
2248 if (LastHeader == deadHead) {
2249 LastHeader = NULL; // will be recomputed next time it's used
2250 }
2251
2252 // Free the memory, unless it was in the static HeaderInfoTable.
2253 if (deadHead < HeaderInfoTable ||
2254 deadHead >= HeaderInfoTable + HINFO_SIZE)
2255 {
2256 _free_internal(deadHead);
2257 }
2258
2259 break;
2260 }
2261 }
2262 }
2263
2264
2265 /***********************************************************************
2266 * check_gc
2267 * Check whether the executable supports or requires GC, and make sure
2268 * all already-loaded libraries support the executable's GC mode.
2269 * Returns TRUE if the executable wants GC on.
2270 **********************************************************************/
2271 static BOOL check_wants_gc(void)
2272 {
2273 // GC is off in Tiger.
2274 return NO;
2275 /*
2276 const header_info *hi;
2277 BOOL appWantsGC;
2278
2279 // Environment variables can override the following.
2280 if (ForceGC) {
2281 _objc_inform("GC: forcing GC ON because OBJC_FORCE_GC is set");
2282 appWantsGC = YES;
2283 }
2284 else if (ForceNoGC) {
2285 _objc_inform("GC: forcing GC OFF because OBJC_FORCE_NO_GC is set");
2286 appWantsGC = NO;
2287 }
2288 else {
2289 // Find the executable and check its GC bits.
2290 // If the executable cannot be found, default to NO.
2291 // (The executable will not be found if the executable contains
2292 // no Objective-C code.)
2293 appWantsGC = NO;
2294 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
2295 if (hi->mhdr->filetype == MH_EXECUTE) {
2296 appWantsGC = _objcHeaderSupportsGC(hi) ? YES : NO;
2297 if (PrintGC) {
2298 _objc_inform("GC: executable '%s' %s GC",
2299 _nameForHeader(hi->mhdr),
2300 appWantsGC ? "supports" : "does not support");
2301 }
2302 }
2303 }
2304 }
2305 return appWantsGC;
2306 */
2307 }
2308
2309 /***********************************************************************
2310 * verify_gc_readiness
2311 * if we want gc, verify that every header describes files compiled
2312 * and presumably ready for gc.
2313 ************************************************************************/
2314
2315 static void verify_gc_readiness(BOOL wantsGC, header_info *hi)
2316 {
2317 BOOL busted = NO;
2318
2319 // Find the libraries and check their GC bits against the app's request
2320 for (; hi != NULL; hi = hi->next) {
2321 if (hi->mhdr->filetype == MH_EXECUTE) {
2322 continue;
2323 }
2324 else if (hi->mhdr == &_mh_dylib_header) {
2325 // libobjc itself works with anything even though it is not
2326 // compiled with -fobjc-gc (fixme should it be?)
2327 }
2328 else if (wantsGC && ! _objcHeaderSupportsGC(hi)) {
2329 // App wants GC but library does not support it - bad
2330 _objc_inform("'%s' was not compiled with -fobjc-gc, but "
2331 "the application requires GC",
2332 _nameForHeader(hi->mhdr));
2333 busted = YES;
2334 }
2335
2336 if (PrintGC) {
2337 _objc_inform("GC: library '%s' %s GC", _nameForHeader(hi->mhdr),
2338 _objcHeaderSupportsGC(hi) ? "supports" : "does not support");
2339 }
2340 }
2341
2342 if (busted) {
2343 // GC state is not consistent.
2344 // Kill the process unless one of the forcing flags is set.
2345 if (!ForceGC && !ForceNoGC) {
2346 _objc_fatal("*** GC capability of application and some libraries did not match");
2347 }
2348 }
2349 }
2350
2351
2352 /***********************************************************************
2353 * _objc_fixup_selector_refs. Register all of the selectors in each
2354 * image, and fix them all up.
2355 **********************************************************************/
2356 static void _objc_fixup_selector_refs (const header_info * hi)
2357 {
2358 unsigned int count;
2359 Module mods;
2360 vm_address_t local_sels;
2361 vm_size_t local_size;
2362
2363 mods = hi->mod_ptr;
2364
2365 // Fix up message refs
2366 local_sels = (vm_address_t) _getObjcMessageRefs ((headerType *) hi->mhdr, &count);
2367 local_size = count * sizeof(SEL);
2368
2369 if (local_sels) {
2370 vm_address_t aligned_start, aligned_end;
2371
2372 local_sels = local_sels + hi->image_slide;
2373 aligned_start = round_page(local_sels);
2374 aligned_end = trunc_page(local_sels + local_size);
2375
2376 map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size,
2377 hi->mhdr->filetype == MH_BUNDLE);
2378 }
2379 }
2380
2381
2382 /***********************************************************************
2383 * objc_setConfiguration
2384 * Read environment variables that affect the runtime.
2385 * Also print environment variable help, if requested.
2386 **********************************************************************/
2387 static void objc_setConfiguration() {
2388 int PrintHelp = (getenv("OBJC_HELP") != NULL);
2389 int PrintOptions = (getenv("OBJC_PRINT_OPTIONS") != NULL);
2390
2391 if (PrintHelp) {
2392 _objc_inform("OBJC_HELP: describe Objective-C runtime environment variables");
2393 if (PrintOptions) {
2394 _objc_inform("OBJC_HELP is set");
2395 }
2396 _objc_inform("OBJC_PRINT_OPTIONS: list which options are set");
2397 }
2398 if (PrintOptions) {
2399 _objc_inform("OBJC_PRINT_OPTIONS is set");
2400 }
2401
2402 #define OPTION(var, env, help) \
2403 if ( var == -1 ) { \
2404 var = getenv(#env) != NULL; \
2405 if (PrintHelp) _objc_inform(#env ": " help); \
2406 if (PrintOptions && var) _objc_inform(#env " is set"); \
2407 }
2408
2409 OPTION(PrintImages, OBJC_PRINT_IMAGES,
2410 "log image and library names as the runtime loads them");
2411 OPTION(PrintConnecting, OBJC_PRINT_CONNECTION,
2412 "log progress of class and category connections");
2413 OPTION(PrintLoading, OBJC_PRINT_LOAD_METHODS,
2414 "log class and category +load methods as they are called");
2415 OPTION(PrintRTP, OBJC_PRINT_RTP,
2416 "log initialization of the Objective-C runtime pages");
2417 OPTION(PrintGC, OBJC_PRINT_GC,
2418 "log some GC operations");
2419 OPTION(PrintSharing, OBJC_PRINT_SHARING,
2420 "log cross-process memory sharing");
2421 OPTION(PrintCxxCtors, OBJC_PRINT_CXX_CTORS,
2422 "log calls to C++ ctors and dtors for instance variables");
2423
2424 OPTION(DebugUnload, OBJC_DEBUG_UNLOAD,
2425 "warn about poorly-behaving bundles when unloaded");
2426 OPTION(DebugFragileSuperclasses, OBJC_DEBUG_FRAGILE_SUPERCLASSES,
2427 "warn about subclasses that may have been broken by subsequent changes to superclasses");
2428
2429 OPTION(UseInternalZone, OBJC_USE_INTERNAL_ZONE,
2430 "allocate runtime data in a dedicated malloc zone");
2431 OPTION(AllowInterposing, OBJC_ALLOW_INTERPOSING,
2432 "allow function interposing of objc_msgSend()");
2433
2434 OPTION(ForceGC, OBJC_FORCE_GC,
2435 "force GC ON, even if the executable wants it off");
2436 OPTION(ForceNoGC, OBJC_FORCE_NO_GC,
2437 "force GC OFF, even if the executable wants it on");
2438 OPTION(CheckFinalizers, OBJC_CHECK_FINALIZERS,
2439 "warn about classes that implement -dealloc but not -finalize");
2440 #undef OPTION
2441 }
2442
2443
2444 /***********************************************************************
2445 * objc_setMultithreaded.
2446 **********************************************************************/
2447 void objc_setMultithreaded (BOOL flag)
2448 {
2449 // Nothing here. Thread synchronization in the runtime is always active.
2450 }
2451
2452
2453
2454 /***********************************************************************
2455 * _objc_pthread_destroyspecific
2456 * Destructor for objc's per-thread data.
2457 * arg shouldn't be NULL, but we check anyway.
2458 **********************************************************************/
2459 extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
2460 void _objc_pthread_destroyspecific(void *arg)
2461 {
2462 _objc_pthread_data *data = (_objc_pthread_data *)arg;
2463 if (data != NULL) {
2464 _destroyInitializingClassList(data->initializingClasses);
2465
2466 // add further cleanup here...
2467
2468 _free_internal(data);
2469 }
2470 }
2471
2472
2473 /***********************************************************************
2474 * _objcInit
2475 * Former library initializer. This function is now merely a placeholder
2476 * for external callers. All runtime initialization has now been moved
2477 * to map_images().
2478 **********************************************************************/
2479 void _objcInit(void)
2480 {
2481 // do nothing
2482 }
2483
2484
2485 /***********************************************************************
2486 * map_images
2487 * Process the given images which are being mapped in by dyld.
2488 * All class registration and fixups are performed (or deferred pending
2489 * discovery of missing superclasses etc), and +load methods are called.
2490 *
2491 * info[] is in bottom-up order i.e. libobjc will be earlier in the
2492 * array than any library that links to libobjc.
2493 **********************************************************************/
2494 static void map_images(const struct dyld_image_info infoList[],
2495 uint32_t infoCount)
2496 {
2497 static BOOL firstTime = YES;
2498 static BOOL wantsGC NOBSS = NO;
2499 uint32_t i;
2500 header_info *firstNewHeader = NULL;
2501 header_info *hInfo;
2502
2503 // Perform first-time initialization if necessary.
2504 // This function is called before ordinary library initializers.
2505 if (firstTime) {
2506 pthread_key_create(&_objc_pthread_key, _objc_pthread_destroyspecific);
2507 objc_setConfiguration(); // read environment variables
2508 _objc_init_class_hash (); // create class_hash
2509 // grab selectors for which @selector() doesn't work
2510 cxx_construct_sel = sel_registerName(cxx_construct_name);
2511 cxx_destruct_sel = sel_registerName(cxx_destruct_name);
2512 }
2513
2514 if (PrintImages) {
2515 _objc_inform("IMAGES: processing %u newly-mapped images...\n", infoCount);
2516 }
2517
2518
2519 // Find all images with an __OBJC segment.
2520 // firstNewHeader is set the the first one, and the header_info
2521 // linked list following firstNewHeader is the rest.
2522 for (i = 0; i < infoCount; i++) {
2523 const struct mach_header *mhdr = infoList[i].imageLoadAddress;
2524
2525 hInfo = _objc_addHeader(mhdr);
2526 if (!hInfo) {
2527 // no objc data in this entry
2528 if (PrintImages) {
2529 _objc_inform("IMAGES: image '%s' contains no __OBJC segment\n",
2530 infoList[i].imageFilePath);
2531 }
2532 continue;
2533 }
2534
2535 if (!firstNewHeader) firstNewHeader = hInfo;
2536
2537 if (PrintImages) {
2538 _objc_inform("IMAGES: loading image for %s%s%s%s\n",
2539 _nameForHeader(mhdr),
2540 mhdr->filetype == MH_BUNDLE ? " (bundle)" : "",
2541 _objcHeaderIsReplacement(hInfo) ? " (replacement)":"",
2542 _objcHeaderSupportsGC(hInfo) ? " (supports GC)":"");
2543 }
2544 }
2545
2546 // Perform one-time runtime initialization that must be deferred until
2547 // the executable itself is found. This needs to be done before
2548 // further initialization.
2549 // (The executable may not be present in this infoList if the
2550 // executable does not contain Objective-C code but Objective-C
2551 // is dynamically loaded later. In that case, check_wants_gc()
2552 // will do the right thing.)
2553 if (firstTime) {
2554 wantsGC = check_wants_gc();
2555 verify_gc_readiness(wantsGC, FirstHeader);
2556 // TIGER DEVELOPMENT ONLY
2557 // REQUIRE A SPECIAL NON-SHIPPING FILE TO ENABLE GC
2558 if (wantsGC) {
2559 // make sure that the special file is there before proceeding with GC
2560 struct stat ignored;
2561 wantsGC = stat("/autozone", &ignored) != -1;
2562 if (!wantsGC && PrintGC)
2563 _objc_inform("GC: disabled, lacking /autozone file");
2564 }
2565
2566 gc_init(wantsGC); // needs executable for GC decision
2567 rtp_init(); // needs GC decision first
2568 } else {
2569 verify_gc_readiness(wantsGC, firstNewHeader);
2570 }
2571
2572
2573 // Initialize everything. Parts of this order are important for
2574 // correctness or performance.
2575
2576 // Read classes from all images.
2577 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2578 _objc_read_classes_from_image(hInfo);
2579 }
2580
2581 // Read categories from all images.
2582 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2583 _objc_read_categories_from_image(hInfo);
2584 }
2585
2586 // Connect classes from all images.
2587 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2588 _objc_connect_classes_from_image(hInfo);
2589 }
2590
2591 // Fix up class refs, selector refs, and protocol objects from all images.
2592 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2593 _objc_map_class_refs_for_image(hInfo);
2594 _objc_fixup_selector_refs(hInfo);
2595 _objc_fixup_protocol_objects_for_image(hInfo);
2596 }
2597
2598 firstTime = NO;
2599
2600 // Call pending +load methods.
2601 // Note that this may in turn cause map_images() to be called again.
2602 call_load_methods();
2603 }
2604
2605
2606 /***********************************************************************
2607 * unmap_images
2608 * Process the given images which are about to be unmapped by dyld.
2609 * Currently we assume only MH_BUNDLE images are unmappable, and
2610 * print warnings about anything else.
2611 **********************************************************************/
2612 static void unmap_images(const struct dyld_image_info infoList[],
2613 uint32_t infoCount)
2614 {
2615 uint32_t i;
2616
2617 if (PrintImages) {
2618 _objc_inform("IMAGES: processing %u newly-unmapped images...\n", infoCount);
2619 }
2620
2621 for (i = 0; i < infoCount; i++) {
2622 const struct mach_header *mhdr = infoList[i].imageLoadAddress;
2623
2624 if (mhdr->filetype == MH_BUNDLE) {
2625 _objc_unmap_image(mhdr);
2626 } else {
2627 // currently only MH_BUNDLEs can be unmapped safely
2628 if (PrintImages) {
2629 _objc_inform("IMAGES: unmapped image '%s' was not a Mach-O bundle; ignoring\n", infoList[i].imageFilePath);
2630 }
2631 }
2632 }
2633 }
2634
2635
2636 /***********************************************************************
2637 * _objc_notify_images
2638 * Callback from dyld informing objc of images to be added or removed.
2639 * This function is never called directly. Instead, a section
2640 * __OBJC,__image_notify contains a function pointer to this, and dyld
2641 * discovers it from there.
2642 **********************************************************************/
2643 __private_extern__
2644 void _objc_notify_images(enum dyld_image_mode mode, uint32_t infoCount,
2645 const struct dyld_image_info infoList[])
2646 {
2647 if (mode == dyld_image_adding) {
2648 map_images(infoList, infoCount);
2649 } else if (mode == dyld_image_removing) {
2650 unmap_images(infoList, infoCount);
2651 }
2652 }
2653
2654
2655 /***********************************************************************
2656 * _objc_remove_classes_in_image
2657 * Remove all classes in the given image from the runtime, because
2658 * the image is about to be unloaded.
2659 * Things to clean up:
2660 * class_hash
2661 * unconnected_class_hash
2662 * pending subclasses list (only if class is still unconnected)
2663 * loadable class list
2664 * class's method caches
2665 * class refs in all other images
2666 **********************************************************************/
2667 static void _objc_remove_classes_in_image(header_info *hi)
2668 {
2669 unsigned int index;
2670 unsigned int midx;
2671 Module mods;
2672
2673 OBJC_LOCK(&classLock);
2674
2675 // Major loop - process all modules in the image
2676 mods = hi->mod_ptr;
2677 for (midx = 0; midx < hi->mod_count; midx += 1)
2678 {
2679 // Skip module containing no classes
2680 if (mods[midx].symtab == NULL)
2681 continue;
2682
2683 // Minor loop - process all the classes in given module
2684 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
2685 {
2686 struct objc_class * cls;
2687
2688 // Locate the class description pointer
2689 cls = mods[midx].symtab->defs[index];
2690
2691 // Remove from loadable class list, if present
2692 remove_class_from_loadable_list(cls);
2693
2694 // Remove from unconnected_class_hash and pending subclasses
2695 if (unconnected_class_hash && NXHashMember(unconnected_class_hash, cls)) {
2696 NXHashRemove(unconnected_class_hash, cls);
2697 if (pendingSubclassesMap) {
2698 // Find this class in its superclass's pending list
2699 char *supercls_name = (char *)cls->super_class;
2700 PendingSubclass *pending =
2701 NXMapGet(pendingSubclassesMap, supercls_name);
2702 for ( ; pending != NULL; pending = pending->next) {
2703 if (pending->subclass == cls) {
2704 pending->subclass = Nil;
2705 break;
2706 }
2707 }
2708 }
2709 }
2710
2711 // Remove from class_hash
2712 NXHashRemove(class_hash, cls);
2713
2714 // Free method list array (from objcTweakMethodListPointerForClass)
2715 // These blocks might be from user code; don't use free_internal
2716 if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) {
2717 free(cls->methodLists);
2718 }
2719 if (cls->isa->methodLists && !(cls->isa->info & CLS_NO_METHOD_ARRAY)) {
2720 free(cls->isa->methodLists);
2721 }
2722
2723 // Free method caches, if any
2724 if (cls->cache && cls->cache != &emptyCache) {
2725 _free_internal(cls->cache);
2726 }
2727 if (cls->isa->cache && cls->isa->cache != &emptyCache) {
2728 _free_internal(cls->isa->cache);
2729 }
2730 }
2731 }
2732
2733
2734 // Search all other images for class refs that point back to this range.
2735 // Un-fix and re-pend any such class refs.
2736
2737 // Get the location of the dying image's __OBJC segment
2738 uintptr_t seg = hi->objcSegmentHeader->vmaddr + hi->image_slide;
2739 size_t seg_size = hi->objcSegmentHeader->filesize;
2740
2741 header_info *other_hi;
2742 for (other_hi = FirstHeader; other_hi != NULL; other_hi = other_hi->next) {
2743 struct objc_class **other_refs;
2744 unsigned int size;
2745 if (other_hi == hi) continue; // skip the image being unloaded
2746
2747 // Locate class refs in the other image
2748 other_refs = _getObjcClassRefs((headerType *)other_hi->mhdr, &size);
2749 if (!other_refs) continue;
2750 other_refs = (struct objc_class **)((uintptr_t)other_refs + other_hi->image_slide);
2751
2752 // Process each class ref
2753 for (index = 0; index < size; index++) {
2754 if ((uintptr_t)(other_refs[index]) >= seg &&
2755 (uintptr_t)(other_refs[index]) < seg+seg_size)
2756 {
2757 pendClassReference(&other_refs[index],other_refs[index]->name);
2758 other_refs[index] = _objc_getNonexistentClass ();
2759 }
2760 }
2761 }
2762
2763 OBJC_UNLOCK(&classLock);
2764 }
2765
2766
2767 /***********************************************************************
2768 * _objc_remove_categories_in_image
2769 * Remove all categories in the given image from the runtime, because
2770 * the image is about to be unloaded.
2771 * Things to clean up:
2772 * unresolved category list
2773 * loadable category list
2774 **********************************************************************/
2775 static void _objc_remove_categories_in_image(header_info *hi)
2776 {
2777 Module mods;
2778 unsigned int midx;
2779
2780 // Major loop - process all modules in the header
2781 mods = hi->mod_ptr;
2782
2783 for (midx = 0; midx < hi->mod_count; midx++) {
2784 unsigned int index;
2785 unsigned int total;
2786 Symtab symtab = mods[midx].symtab;
2787
2788 // Nothing to do for a module without a symbol table
2789 if (symtab == NULL) continue;
2790
2791 // Total entries in symbol table (class entries followed
2792 // by category entries)
2793 total = symtab->cls_def_cnt + symtab->cat_def_cnt;
2794
2795 // Minor loop - check all categories from given module
2796 for (index = symtab->cls_def_cnt; index < total; index++) {
2797 struct objc_category *cat = symtab->defs[index];
2798
2799 // Clean up loadable category list
2800 remove_category_from_loadable_list(cat);
2801
2802 // Clean up category_hash
2803 if (category_hash) {
2804 _objc_unresolved_category *cat_entry =
2805 NXMapGet(category_hash, cat->class_name);
2806 for ( ; cat_entry != NULL; cat_entry = cat_entry->next) {
2807 if (cat_entry->cat == cat) {
2808 cat_entry->cat = NULL;
2809 break;
2810 }
2811 }
2812 }
2813 }
2814 }
2815 }
2816
2817
2818 /***********************************************************************
2819 * unload_paranoia
2820 * Various paranoid debugging checks that look for poorly-behaving
2821 * unloadable bundles.
2822 * Called by _objc_unmap_image when OBJC_UNLOAD_DEBUG is set.
2823 **********************************************************************/
2824 static void unload_paranoia(header_info *hi)
2825 {
2826 // Get the location of the dying image's __OBJC segment
2827 uintptr_t seg = hi->objcSegmentHeader->vmaddr + hi->image_slide;
2828 size_t seg_size = hi->objcSegmentHeader->filesize;
2829
2830 _objc_inform("UNLOAD DEBUG: unloading image '%s' [%p..%p]",
2831 _nameForHeader(hi->mhdr), seg, seg+seg_size);
2832
2833 OBJC_LOCK(&classLock);
2834
2835 // Make sure the image contains no categories on surviving classes.
2836 {
2837 Module mods;
2838 unsigned int midx;
2839
2840 // Major loop - process all modules in the header
2841 mods = hi->mod_ptr;
2842
2843 for (midx = 0; midx < hi->mod_count; midx++) {
2844 unsigned int index;
2845 unsigned int total;
2846 Symtab symtab = mods[midx].symtab;
2847
2848 // Nothing to do for a module without a symbol table
2849 if (symtab == NULL) continue;
2850
2851 // Total entries in symbol table (class entries followed
2852 // by category entries)
2853 total = symtab->cls_def_cnt + symtab->cat_def_cnt;
2854
2855 // Minor loop - check all categories from given module
2856 for (index = symtab->cls_def_cnt; index < total; index++) {
2857 struct objc_category *cat = symtab->defs[index];
2858 struct objc_class query;
2859
2860 query.name = cat->class_name;
2861 if (NXHashMember(class_hash, &query)) {
2862 _objc_inform("UNLOAD DEBUG: dying image contains category '%s(%s)' on surviving class '%s'!", cat->class_name, cat->category_name, cat->class_name);
2863 }
2864 }
2865 }
2866 }
2867
2868 // Make sure no surviving class is in the dying image.
2869 // Make sure no surviving class has a superclass in the dying image.
2870 // fixme check method implementations too
2871 {
2872 struct objc_class *cls;
2873 NXHashState state;
2874
2875 state = NXInitHashState(class_hash);
2876 while (NXNextHashState(class_hash, &state, (void **)&cls)) {
2877 if ((vm_address_t)cls >= seg &&
2878 (vm_address_t)cls < seg+seg_size)
2879 {
2880 _objc_inform("UNLOAD DEBUG: dying image contains surviving class '%s'!", cls->name);
2881 }
2882
2883 if ((vm_address_t)cls->super_class >= seg &&
2884 (vm_address_t)cls->super_class < seg+seg_size)
2885 {
2886 _objc_inform("UNLOAD DEBUG: dying image contains superclass '%s' of surviving class '%s'!", cls->super_class->name, cls->name);
2887 }
2888 }
2889 }
2890
2891 OBJC_UNLOCK(&classLock);
2892 }
2893
2894
2895 /***********************************************************************
2896 * _objc_unmap_image.
2897 * Destroy any Objective-C data for the given image, which is about to
2898 * be unloaded by dyld.
2899 * Note: not thread-safe, but image loading isn't either.
2900 **********************************************************************/
2901 static void _objc_unmap_image(const headerType *mh)
2902 {
2903 header_info *hi;
2904
2905 // Find the runtime's header_info struct for the image
2906 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
2907 if (hi->mhdr == mh) break;
2908 }
2909 if (hi == NULL) return; // no objc data for this image
2910
2911 if (PrintImages) {
2912 _objc_inform("IMAGES: unloading image for %s%s%s%s\n",
2913 _nameForHeader(mh),
2914 mh->filetype == MH_BUNDLE ? " (bundle)" : "",
2915 _objcHeaderIsReplacement(hi) ? " (replacement)" : "",
2916 _objcHeaderSupportsGC(hi) ? " (supports GC)" : "");
2917 }
2918
2919 // Cleanup:
2920 // Remove image's classes from the class list and free auxiliary data.
2921 // Remove image's unresolved or loadable categories and free auxiliary data
2922 // Remove image's unresolved class refs.
2923 _objc_remove_classes_in_image(hi);
2924 _objc_remove_categories_in_image(hi);
2925 _objc_remove_pending_class_refs_in_image(hi);
2926
2927 // Perform various debugging checks if requested.
2928 if (DebugUnload) unload_paranoia(hi);
2929
2930 // Remove header_info from header list
2931 _objc_removeHeader(hi);
2932 }
2933
2934
2935 /***********************************************************************
2936 * _objc_setNilReceiver
2937 **********************************************************************/
2938 id _objc_setNilReceiver(id newNilReceiver)
2939 {
2940 id oldNilReceiver;
2941
2942 oldNilReceiver = _objc_nilReceiver;
2943 _objc_nilReceiver = newNilReceiver;
2944
2945 return oldNilReceiver;
2946 }
2947
2948 /***********************************************************************
2949 * _objc_getNilReceiver
2950 **********************************************************************/
2951 id _objc_getNilReceiver(void)
2952 {
2953 return _objc_nilReceiver;
2954 }
2955
2956
2957 /***********************************************************************
2958 * _objc_setClassLoader
2959 * Similar to objc_setClassHandler, but objc_classLoader is used for
2960 * both objc_getClass() and objc_lookupClass(), and objc_classLoader
2961 * pre-empts objc_classHandler.
2962 **********************************************************************/
2963 void _objc_setClassLoader(BOOL (*newClassLoader)(const char *))
2964 {
2965 _objc_classLoader = newClassLoader;
2966 }
2967
2968
2969 #if defined(__ppc__)
2970
2971 /**********************************************************************
2972 * objc_write_branch
2973 * Writes at entry a PPC branch instruction sequence that branches to target.
2974 * The sequence written will be 1 or 4 instructions long.
2975 * Returns the number of instructions written.
2976 **********************************************************************/
2977 __private_extern__ size_t objc_write_branch(void *entry, void *target)
2978 {
2979 unsigned *address = (unsigned *)entry; // location to store the 32 bit PPC instructions
2980 intptr_t destination = (intptr_t)target; // destination as an absolute address
2981 intptr_t displacement = (intptr_t)destination - (intptr_t)address; // destination as a branch relative offset
2982
2983 // Test to see if either the displacement or destination is within the +/- 2^25 range needed
2984 // for a simple PPC branch instruction. Shifting the high bit of the displacement (or destination)
2985 // left 6 bits and then 6 bits arithmetically to the right does a sign extend of the 26th bit. If
2986 // that result is equivalent to the original value, then the displacement (or destination) will fit
2987 // into a simple branch. Otherwise a four instruction branch sequence is required.
2988 if (((displacement << 6) >> 6) == displacement) {
2989 // use a relative branch with the displacement
2990 address[0] = 0x48000000 | (displacement & 0x03fffffc); // b *+displacement
2991 // issued 1 instruction
2992 return 1;
2993 } else if (((destination << 6) >> 6) == destination) {
2994 // use an absolute branch with the destination
2995 address[0] = 0x48000000 | (destination & 0x03fffffc) | 2; // ba destination (2 is the absolute flag)
2996 // issued 1 instruction
2997 return 1;
2998 } else {
2999 // The four instruction branch sequence requires that the destination be loaded
3000 // into a register, moved to the CTR register then branch using the contents
3001 // of the CTR register.
3002 unsigned lo = destination & 0xffff;
3003 unsigned hi = (destination >> 16) & 0xffff;
3004
3005 address[0] = 0x3d800000 | hi; // lis r12,hi ; load the hi half of destination
3006 address[1] = 0x618c0000 | lo; // ori r12,r12,lo ; merge in the lo half of destination
3007 address[2] = 0x7d8903a6; // mtctr ; move destination to the CTR register
3008 address[3] = 0x4e800420; // bctr ; branch to destination
3009 // issued 4 instructions
3010 return 4;
3011 }
3012 }
3013
3014 // defined(__ppc__)
3015 #endif
3016
3017
3018 /**********************************************************************
3019 * secure_open
3020 * Securely open a file from a world-writable directory (like /tmp)
3021 * If the file does not exist, it will be atomically created with mode 0600
3022 * If the file exists, it must be, and remain after opening:
3023 * 1. a regular file (in particular, not a symlink)
3024 * 2. owned by euid
3025 * 3. permissions 0600
3026 * 4. link count == 1
3027 * Returns a file descriptor or -1. Errno may or may not be set on error.
3028 **********************************************************************/
3029 __private_extern__ int secure_open(const char *filename, int flags, uid_t euid)
3030 {
3031 struct stat fs, ls;
3032 int fd = -1;
3033 BOOL truncate = NO;
3034 BOOL create = NO;
3035
3036 if (flags & O_TRUNC) {
3037 // Don't truncate the file until after it is open and verified.
3038 truncate = YES;
3039 flags &= ~O_TRUNC;
3040 }
3041 if (flags & O_CREAT) {
3042 // Don't create except when we're ready for it
3043 create = YES;
3044 flags &= ~O_CREAT;
3045 flags &= ~O_EXCL;
3046 }
3047
3048 if (lstat(filename, &ls) < 0) {
3049 if (errno == ENOENT && create) {
3050 // No such file - create it
3051 fd = open(filename, flags | O_CREAT | O_EXCL, 0600);
3052 if (fd >= 0) {
3053 // File was created successfully.
3054 // New file does not need to be truncated.
3055 return fd;
3056 } else {
3057 // File creation failed.
3058 return -1;
3059 }
3060 } else {
3061 // lstat failed, or user doesn't want to create the file
3062 return -1;
3063 }
3064 } else {
3065 // lstat succeeded - verify attributes and open
3066 if (S_ISREG(ls.st_mode) && // regular file?
3067 ls.st_nlink == 1 && // link count == 1?
3068 ls.st_uid == euid && // owned by euid?
3069 (ls.st_mode & ALLPERMS) == (S_IRUSR | S_IWUSR)) // mode 0600?
3070 {
3071 // Attributes look ok - open it and check attributes again
3072 fd = open(filename, flags, 0000);
3073 if (fd >= 0) {
3074 // File is open - double-check attributes
3075 if (0 == fstat(fd, &fs) &&
3076 fs.st_nlink == ls.st_nlink && // link count == 1?
3077 fs.st_uid == ls.st_uid && // owned by euid?
3078 fs.st_mode == ls.st_mode && // regular file, 0600?
3079 fs.st_ino == ls.st_ino && // same inode as before?
3080 fs.st_dev == ls.st_dev) // same device as before?
3081 {
3082 // File is open and OK
3083 if (truncate) ftruncate(fd, 0);
3084 return fd;
3085 } else {
3086 // Opened file looks funny - close it
3087 close(fd);
3088 return -1;
3089 }
3090 } else {
3091 // File didn't open
3092 return -1;
3093 }
3094 } else {
3095 // Unopened file looks funny - don't open it
3096 return -1;
3097 }
3098 }
3099 }
3100
3101