2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
25 /***********************************************************************
27 * Copyright 1988-1996, NeXT Software, Inc.
30 **********************************************************************/
32 /***********************************************************************
33 * Class loading and connecting (GrP 2004-2-11)
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
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.
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)
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.
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.
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.
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.
83 * Image mapping sequence:
85 * Read all classes in all new images.
86 * Add them all to unconnected_class_hash.
87 * Fix up any pended classrefs referring to them.
88 * Attach any pending categories.
89 * Read all categories in all new images.
90 * Attach categories whose parent class exists (connected or not),
92 * Mark them all eligible for +load (if implemented), even if the
93 * parent class is missing.
94 * Try to connect all classes in all new images.
95 * If the superclass is missing, pend the class
96 * If the superclass is unconnected, try to recursively connect it
97 * If the superclass is connected:
99 * mark the class eligible for +load, if implemented
100 * connect any pended subclasses of the class
101 * Resolve selector refs and class refs in all new images.
102 * Class refs whose classes still do not exist are pended.
103 * Fix up protocol objects in all new images.
104 * Call +load for classes and categories.
105 * May include classes or categories that are not in these images,
106 * but are newly eligible because of these image.
107 * Class +loads will be called superclass-first because of the
108 * superclass-first nature of the connecting process.
109 * Category +load needs to be deferred until the parent class is
110 * connected and has had its +load called.
112 * Performance: all classes are read before any categories are read.
113 * Fewer categories need be pended for lack of a parent class.
115 * Performance: all categories are attempted to be attached before
116 * any classes are connected. Fewer class caches need be flushed.
117 * (Unconnected classes and their respective subclasses are guaranteed
118 * to be un-messageable, so their caches will be empty.)
120 * Performance: all classes are read before any classes are connected.
121 * Fewer classes need be pended for lack of a superclass.
123 * Correctness: all selector and class refs are fixed before any
124 * protocol fixups or +load methods. libobjc itself contains selector
125 * and class refs which are used in protocol fixup and +load.
127 * Correctness: +load methods are scheduled in bottom-up link order.
128 * This constraint is in addition to superclass order. Some +load
129 * implementations expect to use another class in a linked-to library,
130 * even if the two classes don't share a direct superclass relationship.
132 **********************************************************************/
135 /***********************************************************************
137 **********************************************************************/
139 #include <mach-o/ldsyms.h>
140 #include <mach-o/dyld.h>
141 #include <mach-o/dyld_gdb.h>
142 #include <mach/mach.h>
143 #include <mach/mach_error.h>
145 // project headers first, otherwise we get the installed ones
146 #import "objc-class.h"
147 #import <objc/objc-runtime.h>
148 #import <objc/hashtable2.h>
150 #import "objc-private.h"
151 #import <objc/Object.h>
152 #import <objc/Protocol.h>
154 #import "objc-auto.h"
156 #include <sys/time.h>
157 #include <sys/resource.h>
158 #include <sys/types.h>
159 #include <sys/stat.h>
162 /* NXHashTable SPI */
163 OBJC_EXPORT unsigned _NXHashCapacity(NXHashTable *table);
164 OBJC_EXPORT void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity);
167 OBJC_EXPORT Class _objc_getNonexistentClass(void);
170 OBJC_EXPORT Class getOriginalClassForPosingClass(Class);
173 /***********************************************************************
174 * Constants and macros internal to this module.
175 **********************************************************************/
177 /* Turn on support for literal string objects. */
178 #define LITERAL_STRING_OBJECTS
180 /***********************************************************************
181 * Types internal to this module.
182 **********************************************************************/
184 typedef struct _objc_unresolved_category
186 struct _objc_unresolved_category * next;
187 struct objc_category * cat; // may be NULL
189 } _objc_unresolved_category;
191 typedef struct _PendingSubclass
193 struct objc_class *subclass; // subclass to finish connecting; may be NULL
194 struct _PendingSubclass *next;
197 typedef struct _PendingClassRef
199 struct objc_class **ref; // class reference to fix up; may be NULL
200 struct _PendingClassRef *next;
203 struct loadable_class {
204 struct objc_class *cls; // may be NULL
208 struct loadable_category {
209 struct objc_category *cat; // may be NULL
214 /***********************************************************************
216 **********************************************************************/
218 // Function called after class has been fixed up (MACH only)
219 void (*callbackFunction)(Class, const char *) = 0;
221 // Lock for class hashtable
222 OBJC_DECLARE_LOCK (classLock);
224 // Settings from environment variables
225 __private_extern__ int PrintImages = -1; // env OBJC_PRINT_IMAGES
226 __private_extern__ int PrintLoading = -1; // env OBJC_PRINT_LOAD_METHODS
227 __private_extern__ int PrintConnecting = -1; // env OBJC_PRINT_CONNECTION
228 __private_extern__ int PrintRTP = -1; // env OBJC_PRINT_RTP
229 __private_extern__ int PrintGC = -1; // env OBJC_PRINT_GC
230 __private_extern__ int PrintSharing = -1; // env OBJC_PRINT_SHARING
231 __private_extern__ int PrintCxxCtors = -1; // env OBJC_PRINT_CXX_CTORS
233 __private_extern__ int UseInternalZone = -1; // env OBJC_USE_INTERNAL_ZONE
234 __private_extern__ int AllowInterposing = -1;// env OBJC_ALLOW_INTERPOSING
236 __private_extern__ int DebugUnload = -1; // env OBJC_DEBUG_UNLOAD
237 __private_extern__ int DebugFragileSuperclasses = -1; // env OBJC_DEBUG_FRAGILE_SUPERCLASSES
239 __private_extern__ int ForceGC = -1; // env OBJC_FORCE_GC
240 __private_extern__ int ForceNoGC = -1; // env OBJC_FORCE_NO_GC
241 __private_extern__ int CheckFinalizers = -1; // env OBJC_CHECK_FINALIZERS
243 // objc's key for pthread_getspecific
244 __private_extern__ pthread_key_t _objc_pthread_key = 0;
246 // List of classes that need +load called (pending superclass +load)
247 // This list always has superclasses first because of the way it is constructed
248 static struct loadable_class *loadable_classes NOBSS = NULL;
249 static int loadable_classes_used NOBSS = 0;
250 static int loadable_classes_allocated NOBSS = 0;
252 // List of categories that need +load called (pending parent class +load)
253 static struct loadable_category *loadable_categories NOBSS = NULL;
254 static int loadable_categories_used NOBSS = 0;
255 static int loadable_categories_allocated NOBSS = 0;
257 // Selectors for which @selector() doesn't work
258 __private_extern__ SEL cxx_construct_sel = NULL;
259 __private_extern__ SEL cxx_destruct_sel = NULL;
260 __private_extern__ const char *cxx_construct_name = ".cxx_construct";
261 __private_extern__ const char *cxx_destruct_name = ".cxx_destruct";
264 /***********************************************************************
265 * Function prototypes internal to this module.
266 **********************************************************************/
268 static unsigned classHash (void * info, struct objc_class * data);
269 static int classIsEqual (void * info, struct objc_class * name, struct objc_class * cls);
270 static int _objc_defaultClassHandler (const char * clsName);
271 static void _objcTweakMethodListPointerForClass (struct objc_class * cls);
272 static void _objc_add_category_flush_caches(struct objc_class * cls, struct objc_category * category, int version);
273 static void _objc_add_category(struct objc_class * cls, struct objc_category * category, int version);
274 static void _objc_register_category (struct objc_category * cat, long version);
275 static void _objc_read_categories_from_image (header_info * hi);
276 static const header_info * _headerForClass (struct objc_class * cls);
277 static NXMapTable * pendingClassRefsMapTable (void);
278 static NXMapTable * pendingSubclassesMapTable (void);
279 static void _objc_read_classes_from_image (header_info * hi);
280 static void _objc_map_class_refs_for_image (header_info * hi);
281 static void _objc_fixup_protocol_objects_for_image (header_info * hi);
282 static void _objc_fixup_selector_refs (const header_info * hi);
283 static void _objc_unmap_image(const headerType *mh);
284 static BOOL connect_class(struct objc_class *cls);
285 static void add_category_to_loadable_list(struct objc_category *cat);
286 static vm_range_t get_shared_range(vm_address_t start, vm_address_t end);
287 static void offer_shared_range(vm_address_t start, vm_address_t end);
288 static void install_shared_range(vm_range_t remote, vm_address_t local);
289 static void clear_shared_range_file_cache(void);
292 /***********************************************************************
293 * Static data internal to this module.
294 **********************************************************************/
296 // we keep a linked list of header_info's describing each image as told to us by dyld
297 static header_info *FirstHeader NOBSS = 0; // NULL means empty list
298 static header_info *LastHeader NOBSS = 0; // NULL means invalid; recompute it
300 // Hash table of classes
301 static NXHashTable * class_hash NOBSS = 0;
302 static NXHashTablePrototype classHashPrototype =
304 (unsigned (*) (const void *, const void *)) classHash,
305 (int (*)(const void *, const void *, const void *)) classIsEqual,
309 // Hash table of unconnected classes
310 static NXHashTable *unconnected_class_hash NOBSS = NULL;
312 // Exported copy of class_hash variable (hook for debugging tools)
313 NXHashTable *_objc_debug_class_hash = NULL;
315 // Function pointer objc_getClass calls through when class is not found
316 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
318 // Function pointer called by objc_getClass and objc_lookupClass when
319 // class is not found. _objc_classLoader is called before objc_classHandler.
320 static BOOL (*_objc_classLoader)(const char *) = NULL;
322 // Category and class registries
323 // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
324 // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
325 static NXMapTable * category_hash = NULL;
327 // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
328 // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
329 static NXMapTable * pendingClassRefsMap = NULL;
330 static NXMapTable * pendingSubclassesMap = NULL;
332 /***********************************************************************
333 * objc_dump_class_hash. Log names of all known classes.
334 **********************************************************************/
335 void objc_dump_class_hash (void)
339 struct objc_class * data;
344 state = NXInitHashState (table);
345 while (NXNextHashState (table, &state, (void **) &data))
346 printf ("class %d: %s\n", ++count, data->name);
349 /***********************************************************************
351 **********************************************************************/
352 static unsigned classHash (void * info,
353 struct objc_class * data)
355 // Nil classes hash to zero
359 // Call through to real hash function
360 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
363 /***********************************************************************
364 * classIsEqual. Returns whether the class names match. If we ever
365 * check more than the name, routines like objc_lookUpClass have to
367 **********************************************************************/
368 static int classIsEqual (void * info,
369 struct objc_class * name,
370 struct objc_class * cls)
372 // Standard string comparison
373 // Our local inlined version is significantly shorter on PPC and avoids the
374 // mflr/mtlr and dyld_stub overhead when calling strcmp.
375 return _objc_strcmp(name->name, cls->name) == 0;
379 /***********************************************************************
380 * NXMapKeyCopyingInsert
381 * Like NXMapInsert, but strdups the key if necessary.
382 * Used to prevent stale pointers when bundles are unloaded.
383 **********************************************************************/
384 static void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value)
387 void *realValue = NULL;
389 if ((realKey = NXMapMember(table, key, &realValue)) != NX_MAPNOTAKEY) {
390 // key DOES exist in table - use table's key for insertion
392 // key DOES NOT exist in table - copy the new key before insertion
393 realKey = _strdup_internal(key);
395 return NXMapInsert(table, realKey, value);
399 /***********************************************************************
400 * NXMapKeyFreeingRemove
401 * Like NXMapRemove, but frees the existing key if necessary.
402 * Used to prevent stale pointers when bundles are unloaded.
403 **********************************************************************/
404 static void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key)
407 void *realValue = NULL;
409 if ((realKey = NXMapMember(table, key, &realValue)) != NX_MAPNOTAKEY) {
410 // key DOES exist in table - remove pair and free key
411 realValue = NXMapRemove(table, realKey);
412 _free_internal(realKey); // the key from the table, not necessarily the one given
415 // key DOES NOT exist in table - nothing to do
421 /***********************************************************************
422 * _objc_init_class_hash. Return the class lookup table, create it if
424 **********************************************************************/
425 void _objc_init_class_hash (void)
427 // Do nothing if class hash table already exists
431 // class_hash starts small, with only enough capacity for libobjc itself.
432 // If a second library is found by map_images(), class_hash is immediately
433 // resized to capacity 1024 to cut down on rehashes.
434 // Old numbers: A smallish Foundation+AppKit program will have
435 // about 520 classes. Larger apps (like IB or WOB) have more like
436 // 800 classes. Some customers have massive quantities of classes.
437 // Foundation-only programs aren't likely to notice the ~6K loss.
438 class_hash = NXCreateHashTableFromZone (classHashPrototype,
441 _objc_internal_zone ());
442 _objc_debug_class_hash = class_hash;
445 /***********************************************************************
446 * objc_getClassList. Return the known classes.
447 **********************************************************************/
448 int objc_getClassList(Class *buffer, int bufferLen) {
450 struct objc_class * class;
453 OBJC_LOCK(&classLock);
454 num = NXCountHashTable(class_hash);
455 if (NULL == buffer) {
456 OBJC_UNLOCK(&classLock);
460 state = NXInitHashState(class_hash);
461 while (cnt < bufferLen &&
462 NXNextHashState(class_hash, &state, (void **)&class))
464 buffer[cnt++] = class;
466 OBJC_UNLOCK(&classLock);
470 /***********************************************************************
471 * objc_getClasses. Return class lookup table.
473 * NOTE: This function is very dangerous, since you cannot safely use
474 * the hashtable without locking it, and the lock is private!
475 **********************************************************************/
476 void * objc_getClasses (void)
478 // Return the class lookup hash table
482 /***********************************************************************
483 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
484 **********************************************************************/
485 static int _objc_defaultClassHandler (const char * clsName)
487 // Return zero so objc_getClass doesn't bother re-searching
491 /***********************************************************************
492 * objc_setClassHandler. Set objc_classHandler to the specified value.
494 * NOTE: This should probably deal with userSuppliedHandler being NULL,
495 * because the objc_classHandler caller does not check... it would bus
496 * error. It would make sense to handle NULL by restoring the default
497 * handler. Is anyone hacking with this, though?
498 **********************************************************************/
499 void objc_setClassHandler (int (*userSuppliedHandler) (const char *))
501 objc_classHandler = userSuppliedHandler;
505 /***********************************************************************
507 * Map a class name to a class using various methods.
508 * This is the common implementation of objc_lookUpClass and objc_getClass,
509 * and is also used internally to get additional search options.
512 * 2. unconnected_class_hash (optional)
513 * 3. classLoader callback
514 * 4. classHandler callback (optional)
515 **********************************************************************/
516 static id look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler)
518 BOOL includeClassLoader = YES; // class loader cannot be skipped
520 struct objc_class query;
522 query.name = aClassName;
526 if (!result && class_hash) {
527 // Check ordinary classes
528 OBJC_LOCK (&classLock);
529 result = (id)NXHashGet(class_hash, &query);
530 OBJC_UNLOCK (&classLock);
533 if (!result && includeUnconnected && unconnected_class_hash) {
534 // Check not-yet-connected classes
535 OBJC_LOCK(&classLock);
536 result = (id)NXHashGet(unconnected_class_hash, &query);
537 OBJC_UNLOCK(&classLock);
540 if (!result && includeClassLoader && _objc_classLoader) {
541 // Try class loader callback
542 if ((*_objc_classLoader)(aClassName)) {
543 // Re-try lookup without class loader
544 includeClassLoader = NO;
549 if (!result && includeClassHandler && objc_classHandler) {
550 // Try class handler callback
551 if ((*objc_classHandler)(aClassName)) {
552 // Re-try lookup without class handler or class loader
553 includeClassLoader = NO;
554 includeClassHandler = NO;
563 /***********************************************************************
564 * objc_getClass. Return the id of the named class. If the class does
565 * not exist, call _objc_classLoader and then objc_classHandler, either of
566 * which may create a new class.
567 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
568 **********************************************************************/
569 id objc_getClass (const char * aClassName)
571 // NO unconnected, YES class handler
572 return look_up_class(aClassName, NO, YES);
576 /***********************************************************************
577 * objc_getRequiredClass.
578 * Same as objc_getClass, but kills the process if the class is not found.
579 * This is used by ZeroLink, where failing to find a class would be a
580 * compile-time link error without ZeroLink.
581 **********************************************************************/
582 id objc_getRequiredClass(const char *aClassName)
584 id cls = objc_getClass(aClassName);
585 if (!cls) _objc_fatal("link error: class '%s' not found.", aClassName);
590 /***********************************************************************
591 * objc_lookUpClass. Return the id of the named class.
592 * If the class does not exist, call _objc_classLoader, which may create
595 * Formerly objc_getClassWithoutWarning ()
596 **********************************************************************/
597 id objc_lookUpClass (const char * aClassName)
599 // NO unconnected, NO class handler
600 return look_up_class(aClassName, NO, NO);
603 /***********************************************************************
604 * objc_getMetaClass. Return the id of the meta class the named class.
605 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
606 **********************************************************************/
607 id objc_getMetaClass (const char * aClassName)
609 struct objc_class * cls;
611 cls = objc_getClass (aClassName);
614 _objc_inform ("class `%s' not linked into application", aClassName);
621 /***********************************************************************
622 * objc_addClass. Add the specified class to the table of known classes,
623 * after doing a little verification and fixup.
624 **********************************************************************/
625 void objc_addClass (struct objc_class *cls)
627 // Synchronize access to hash table
628 OBJC_LOCK (&classLock);
630 // Make sure both the class and the metaclass have caches!
631 // Clear all bits of the info fields except CLS_CLASS and CLS_META.
632 // Normally these bits are already clear but if someone tries to cons
633 // up their own class on the fly they might need to be cleared.
634 if (cls->cache == NULL) {
635 cls->cache = (Cache) &emptyCache;
636 cls->info = CLS_CLASS;
639 if (cls->isa->cache == NULL) {
640 cls->isa->cache = (Cache) &emptyCache;
641 cls->isa->info = CLS_META;
644 // methodLists should be:
645 // 1. NULL (Tiger and later only)
646 // 2. A -1 terminated method list array
647 // In either case, CLS_NO_METHOD_ARRAY remains clear.
648 // If the user manipulates the method list directly,
649 // they must use the magic private format.
651 // Add the class to the table
652 (void) NXHashInsert (class_hash, cls);
655 OBJC_UNLOCK (&classLock);
658 /***********************************************************************
659 * _objcTweakMethodListPointerForClass.
660 * Change the class's method list pointer to a method list array.
661 * Does nothing if the method list pointer is already a method list array.
662 * If the class is currently in use, methodListLock must be held by the caller.
663 **********************************************************************/
664 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
666 struct objc_method_list * originalList;
667 const int initialEntries = 4;
669 struct objc_method_list ** ptr;
671 // Do nothing if methodLists is already an array.
672 if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) return;
674 // Remember existing list
675 originalList = (struct objc_method_list *) cls->methodLists;
677 // Allocate and zero a method list array
678 mallocSize = sizeof(struct objc_method_list *) * initialEntries;
679 ptr = (struct objc_method_list **) _calloc_internal(1, mallocSize);
681 // Insert the existing list into the array
682 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
683 ptr[0] = originalList;
685 // Replace existing list with array
686 cls->methodLists = ptr;
687 _class_clearInfo(cls, CLS_NO_METHOD_ARRAY);
691 /***********************************************************************
692 * _objc_insertMethods.
693 * Adds methods to a class.
694 * Does not flush any method caches.
695 * Does not take any locks.
696 * If the class is already in use, use class_addMethods() instead.
697 **********************************************************************/
698 void _objc_insertMethods(struct objc_class *cls,
699 struct objc_method_list *mlist)
701 struct objc_method_list ***list;
702 struct objc_method_list **ptr;
707 if (!cls->methodLists) {
708 // cls has no methods - simply use this method list
709 cls->methodLists = (struct objc_method_list **)mlist;
710 _class_setInfo(cls, CLS_NO_METHOD_ARRAY);
714 // Create method list array if necessary
715 _objcTweakMethodListPointerForClass(cls);
717 list = &cls->methodLists;
719 // Locate unused entry for insertion point
721 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
724 // If array is full, add to it
725 if (*ptr == END_OF_METHODS_LIST)
727 // Calculate old and new dimensions
728 endIndex = ptr - *list;
729 oldSize = (endIndex + 1) * sizeof(void *);
730 newSize = oldSize + sizeof(struct objc_method_list *); // only increase by 1
732 // Grow the method list array by one.
733 // This block may be from user code; don't use _realloc_internal
734 *list = (struct objc_method_list **)realloc(*list, newSize);
736 // Zero out addition part of new array
737 bzero (&((*list)[endIndex]), newSize - oldSize);
739 // Place new end marker
740 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
742 // Insertion point corresponds to old array end
743 ptr = &((*list)[endIndex]);
746 // Right shift existing entries by one
747 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
749 // Insert at method list at beginning of array
753 /***********************************************************************
754 * _objc_removeMethods.
755 * Remove methods from a class.
756 * Does not take any locks.
757 * Does not flush any method caches.
758 * If the class is currently in use, use class_removeMethods() instead.
759 **********************************************************************/
760 void _objc_removeMethods(struct objc_class *cls,
761 struct objc_method_list *mlist)
763 struct objc_method_list ***list;
764 struct objc_method_list **ptr;
766 if (cls->methodLists == NULL) {
767 // cls has no methods
770 if (cls->methodLists == (struct objc_method_list **)mlist) {
771 // mlist is the class's only method list - erase it
772 cls->methodLists = NULL;
775 if (cls->info & CLS_NO_METHOD_ARRAY) {
776 // cls has only one method list, and this isn't it - do nothing
780 // cls has a method list array - search it
782 list = &cls->methodLists;
784 // Locate list in the array
786 while (*ptr != mlist) {
787 // fix for radar # 2538790
788 if ( *ptr == END_OF_METHODS_LIST ) return;
795 // Left shift the following entries
796 while (*(++ptr) != END_OF_METHODS_LIST)
801 /***********************************************************************
802 * _objc_add_category. Install the specified category's methods and
803 * protocols into the class it augments.
804 * The class is assumed not to be in use yet: no locks are taken and
805 * no method caches are flushed.
806 **********************************************************************/
807 static inline void _objc_add_category(struct objc_class *cls, struct objc_category *category, int version)
809 if (PrintConnecting) {
810 _objc_inform("CONNECT: attaching category '%s (%s)'", cls->name, category->category_name);
813 // Augment instance methods
814 if (category->instance_methods)
815 _objc_insertMethods (cls, category->instance_methods);
817 // Augment class methods
818 if (category->class_methods)
819 _objc_insertMethods (cls->isa, category->class_methods);
822 if ((version >= 5) && category->protocols)
824 if (cls->isa->version >= 5)
826 category->protocols->next = cls->protocols;
827 cls->protocols = category->protocols;
828 cls->isa->protocols = category->protocols;
832 _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
833 _objc_inform ("class `%s' must be recompiled\n", category->class_name);
838 /***********************************************************************
839 * _objc_add_category_flush_caches. Install the specified category's
840 * methods into the class it augments, and flush the class' method cache.
841 **********************************************************************/
842 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
844 // Install the category's methods into its intended class
845 OBJC_LOCK(&methodListLock);
846 _objc_add_category (cls, category, version);
847 OBJC_UNLOCK(&methodListLock);
849 // Flush caches so category's methods can get called
850 _objc_flush_caches (cls);
854 /***********************************************************************
856 * Reverse the given linked list of pending categories.
857 * The pending category list is built backwards, and needs to be
858 * reversed before actually attaching the categories to a class.
859 * Returns the head of the new linked list.
860 **********************************************************************/
861 static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat)
863 if (!cat) return NULL;
865 _objc_unresolved_category *prev = NULL;
866 _objc_unresolved_category *cur = cat;
867 _objc_unresolved_category *ahead = cat->next;
880 /***********************************************************************
881 * resolve_categories_for_class.
882 * Install all existing categories intended for the specified class.
883 * cls must be a true class and not a metaclass.
884 **********************************************************************/
885 static void resolve_categories_for_class(struct objc_class *cls)
887 _objc_unresolved_category * pending;
888 _objc_unresolved_category * next;
890 // Nothing to do if there are no categories at all
891 if (!category_hash) return;
893 // Locate and remove first element in category list
894 // associated with this class
895 pending = NXMapKeyFreeingRemove (category_hash, cls->name);
897 // Traverse the list of categories, if any, registered for this class
899 // The pending list is built backwards. Reverse it and walk forwards.
900 pending = reverse_cat(pending);
904 // Install the category
905 // use the non-flush-cache version since we are only
906 // called from the class intialization code
907 _objc_add_category(cls, pending->cat, pending->version);
910 // Delink and reclaim this registration
911 next = pending->next;
912 _free_internal(pending);
918 /***********************************************************************
919 * _objc_resolve_categories_for_class.
920 * Public version of resolve_categories_for_class. This was
921 * exported pre-10.4 for Omni et al. to workaround a problem
922 * with too-lazy category attachment.
923 * cls should be a class, but this function can also cope with metaclasses.
924 **********************************************************************/
925 void _objc_resolve_categories_for_class(struct objc_class *cls)
928 // If cls is a metaclass, get the class.
929 // resolve_categories_for_class() requires a real class to work correctly.
931 if (strncmp(cls->name, "_%", 2) == 0) {
932 // Posee's meta's name is smashed and isn't in the class_hash,
933 // so objc_getClass doesn't work.
934 char *baseName = strchr(cls->name, '%'); // get posee's real name
935 cls = objc_getClass(baseName);
937 cls = objc_getClass(cls->name);
941 resolve_categories_for_class(cls);
945 /***********************************************************************
946 * _objc_register_category.
947 * Process a category read from an image.
948 * If the category's class exists, attach the category immediately.
949 * If the category's class does not exist yet, pend the category for
950 * later attachment. Pending categories are attached in the order
951 * they were discovered.
952 **********************************************************************/
953 static void _objc_register_category(struct objc_category *cat, long version)
955 _objc_unresolved_category * new_cat;
956 _objc_unresolved_category * old;
957 struct objc_class *theClass;
959 // If the category's class exists, attach the category.
960 if ((theClass = objc_lookUpClass(cat->class_name))) {
961 _objc_add_category_flush_caches(theClass, cat, version);
965 // If the category's class exists but is unconnected,
966 // then attach the category to the class but don't bother
967 // flushing any method caches (because they must be empty).
968 // YES unconnected, NO class_handler
969 if ((theClass = look_up_class(cat->class_name, YES, NO))) {
970 _objc_add_category(theClass, cat, version);
975 // Category's class does not exist yet.
976 // Save the category for later attachment.
978 if (PrintConnecting) {
979 _objc_inform("CONNECT: pending category '%s (%s)'", cat->class_name, cat->category_name);
982 // Create category lookup table if needed
984 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
986 _objc_internal_zone ());
988 // Locate an existing list of categories, if any, for the class.
989 old = NXMapGet (category_hash, cat->class_name);
991 // Register the category to be fixed up later.
992 // The category list is built backwards, and is reversed again
993 // by resolve_categories_for_class().
994 new_cat = _malloc_internal(sizeof(_objc_unresolved_category));
997 new_cat->version = version;
998 (void) NXMapKeyCopyingInsert (category_hash, cat->class_name, new_cat);
1002 /***********************************************************************
1003 * _objc_read_categories_from_image.
1004 * Read all categories from the given image.
1005 * Install them on their parent classes, or register them for later
1007 * Register them for later +load, if implemented.
1008 **********************************************************************/
1009 static void _objc_read_categories_from_image (header_info * hi)
1014 if (_objcHeaderIsReplacement(hi)) {
1015 // Ignore any categories in this image
1019 // Major loop - process all modules in the header
1022 // NOTE: The module and category lists are traversed backwards
1023 // to preserve the pre-10.4 processing order. Changing the order
1024 // would have a small chance of introducing binary compatibility bugs.
1025 midx = hi->mod_count;
1026 while (midx-- > 0) {
1030 // Nothing to do for a module without a symbol table
1031 if (mods[midx].symtab == NULL)
1034 // Total entries in symbol table (class entries followed
1035 // by category entries)
1036 total = mods[midx].symtab->cls_def_cnt +
1037 mods[midx].symtab->cat_def_cnt;
1039 // Minor loop - register all categories from given module
1041 while (index-- > mods[midx].symtab->cls_def_cnt) {
1042 struct objc_category *cat = mods[midx].symtab->defs[index];
1043 _objc_register_category(cat, mods[midx].version);
1044 add_category_to_loadable_list(cat);
1050 /***********************************************************************
1051 * _headerForAddress.
1052 * addr can be a class or a category
1053 **********************************************************************/
1054 static const header_info *_headerForAddress(void *addr)
1058 header_info * hInfo;
1060 // Check all headers in the vector
1061 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1063 // Locate header data, if any
1064 if (!hInfo->objcSegmentHeader) continue;
1065 seg = hInfo->objcSegmentHeader->vmaddr + hInfo->image_slide;
1066 size = hInfo->objcSegmentHeader->filesize;
1068 // Is the class in this header?
1069 if ((seg <= (unsigned long) addr) &&
1070 ((unsigned long) addr < (seg + size)))
1079 /***********************************************************************
1081 * Return the image header containing this class, or NULL.
1082 * Returns NULL on runtime-constructed classes, and the NSCF classes.
1083 **********************************************************************/
1084 static const header_info *_headerForClass(struct objc_class *cls)
1086 return _headerForAddress(cls);
1090 /***********************************************************************
1092 **********************************************************************/
1093 const char * _nameForHeader (const headerType * header)
1095 return _getObjcHeaderName ((headerType *) header);
1099 /***********************************************************************
1100 * class_is_connected.
1101 * Returns TRUE if class cls is connected.
1102 * A connected class has either a connected superclass or a NULL superclass,
1103 * and is present in class_hash.
1104 **********************************************************************/
1105 static BOOL class_is_connected(struct objc_class *cls)
1108 OBJC_LOCK(&classLock);
1109 result = NXHashMember(class_hash, cls);
1110 OBJC_UNLOCK(&classLock);
1115 /***********************************************************************
1116 * pendingClassRefsMapTable. Return a pointer to the lookup table for
1117 * pending class refs.
1118 **********************************************************************/
1119 static inline NXMapTable *pendingClassRefsMapTable(void)
1121 // Allocate table if needed
1122 if (!pendingClassRefsMap) {
1123 pendingClassRefsMap =
1124 NXCreateMapTableFromZone(NXStrValueMapPrototype,
1125 10, _objc_internal_zone ());
1128 // Return table pointer
1129 return pendingClassRefsMap;
1133 /***********************************************************************
1134 * pendingSubclassesMapTable. Return a pointer to the lookup table for
1135 * pending subclasses.
1136 **********************************************************************/
1137 static inline NXMapTable *pendingSubclassesMapTable(void)
1139 // Allocate table if needed
1140 if (!pendingSubclassesMap) {
1141 pendingSubclassesMap =
1142 NXCreateMapTableFromZone(NXStrValueMapPrototype,
1143 10, _objc_internal_zone ());
1146 // Return table pointer
1147 return pendingSubclassesMap;
1151 /***********************************************************************
1152 * pendClassInstallation
1153 * Finish connecting class cls when its superclass becomes connected.
1154 * Check for multiple pends of the same class because connect_class does not.
1155 **********************************************************************/
1156 static void pendClassInstallation(struct objc_class *cls,
1157 const char *superName)
1160 PendingSubclass *pending;
1161 PendingSubclass *oldList;
1164 // Create and/or locate pending class lookup table
1165 table = pendingSubclassesMapTable ();
1167 // Make sure this class isn't already in the pending list.
1168 oldList = NXMapGet (table, superName);
1169 for (l = oldList; l != NULL; l = l->next) {
1170 if (l->subclass == cls) return; // already here, nothing to do
1173 // Create entry referring to this class
1174 pending = _malloc_internal(sizeof(PendingSubclass));
1175 pending->subclass = cls;
1177 // Link new entry into head of list of entries for this class
1178 pending->next = oldList;
1180 // (Re)place entry list in the table
1181 (void) NXMapKeyCopyingInsert (table, superName, pending);
1185 /***********************************************************************
1186 * pendClassReference
1187 * Fix up a class ref when the class with the given name becomes connected.
1188 **********************************************************************/
1189 static void pendClassReference(struct objc_class **ref,
1190 const char *className)
1193 PendingClassRef *pending;
1195 // Create and/or locate pending class lookup table
1196 table = pendingClassRefsMapTable ();
1198 // Create entry containing the class reference
1199 pending = _malloc_internal(sizeof(PendingClassRef));
1202 // Link new entry into head of list of entries for this class
1203 pending->next = NXMapGet (table, className);
1205 // (Re)place entry list in the table
1206 (void) NXMapKeyCopyingInsert (table, className, pending);
1208 if (PrintConnecting) {
1209 _objc_inform("CONNECT: pended reference to class '%s' at %p",
1210 className, (void *)ref);
1215 /***********************************************************************
1216 * resolve_references_to_class
1217 * Fix up any pending class refs to this class.
1218 **********************************************************************/
1219 static void resolve_references_to_class(struct objc_class *cls)
1221 PendingClassRef *pending;
1223 if (!pendingClassRefsMap) return; // no unresolved refs for any class
1225 pending = NXMapGet(pendingClassRefsMap, cls->name);
1226 if (!pending) return; // no unresolved refs for this class
1228 NXMapKeyFreeingRemove(pendingClassRefsMap, cls->name);
1230 if (PrintConnecting) {
1231 _objc_inform("CONNECT: resolving references to class '%s'", cls->name);
1235 PendingClassRef *next = pending->next;
1236 if (pending->ref) *pending->ref = cls;
1237 _free_internal(pending);
1241 if (NXCountMapTable(pendingClassRefsMap) == 0) {
1242 NXFreeMapTable(pendingClassRefsMap);
1243 pendingClassRefsMap = NULL;
1248 /***********************************************************************
1249 * resolve_subclasses_of_class
1250 * Fix up any pending subclasses of this class.
1251 **********************************************************************/
1252 static void resolve_subclasses_of_class(struct objc_class *cls)
1254 PendingSubclass *pending;
1256 if (!pendingSubclassesMap) return; // no unresolved subclasses
1258 pending = NXMapGet(pendingSubclassesMap, cls->name);
1259 if (!pending) return; // no unresolved subclasses for this class
1261 NXMapKeyFreeingRemove(pendingSubclassesMap, cls->name);
1263 // Destroy the pending table if it's now empty, to save memory.
1264 if (NXCountMapTable(pendingSubclassesMap) == 0) {
1265 NXFreeMapTable(pendingSubclassesMap);
1266 pendingSubclassesMap = NULL;
1269 if (PrintConnecting) {
1270 _objc_inform("CONNECT: resolving subclasses of class '%s'", cls->name);
1274 PendingSubclass *next = pending->next;
1275 if (pending->subclass) connect_class(pending->subclass);
1276 _free_internal(pending);
1282 /***********************************************************************
1283 * get_base_method_list
1284 * Returns the method list containing the class's own methods,
1285 * ignoring any method lists added by categories or class_addMethods.
1286 * Called only by add_class_to_loadable_list.
1287 * Does not hold methodListLock because add_class_to_loadable_list
1288 * does not manipulate in-use classes.
1289 **********************************************************************/
1290 static struct objc_method_list *get_base_method_list(struct objc_class *cls)
1292 struct objc_method_list **ptr;
1294 if (!cls->methodLists) return NULL;
1295 if (cls->info & CLS_NO_METHOD_ARRAY) return (struct objc_method_list *)cls->methodLists;
1296 ptr = cls->methodLists;
1297 if (!*ptr || *ptr == END_OF_METHODS_LIST) return NULL;
1298 while ( *ptr != 0 && *ptr != END_OF_METHODS_LIST ) { ptr++; }
1304 /***********************************************************************
1305 * add_class_to_loadable_list
1306 * Class cls has just become connected. Schedule it for +load if
1307 * it implements a +load method.
1308 **********************************************************************/
1309 static void add_class_to_loadable_list(struct objc_class *cls)
1312 struct objc_method_list *mlist;
1314 mlist = get_base_method_list(cls->isa);
1316 method = lookupNamedMethodInMethodList (mlist, "load");
1318 // Don't bother if cls has no +load method
1319 if (!method) return;
1322 _objc_inform("LOAD: class '%s' scheduled for +load", cls->name);
1325 if (loadable_classes_used == loadable_classes_allocated) {
1326 loadable_classes_allocated = loadable_classes_allocated*2 + 16;
1328 _realloc_internal(loadable_classes,
1329 loadable_classes_allocated *
1330 sizeof(struct loadable_class));
1333 loadable_classes[loadable_classes_used].cls = cls;
1334 loadable_classes[loadable_classes_used].method = method;
1335 loadable_classes_used++;
1339 /***********************************************************************
1340 * add_category_to_loadable_list
1341 * Category cat's parent class exists and the category has been attached
1342 * to its class. Schedule this category for +load after its parent class
1343 * becomes connected and has its own +load method called.
1344 **********************************************************************/
1345 static void add_category_to_loadable_list(struct objc_category *cat)
1348 struct objc_method_list *mlist;
1350 mlist = cat->class_methods;
1352 method = lookupNamedMethodInMethodList (mlist, "load");
1354 // Don't bother if cat has no +load method
1355 if (!method) return;
1358 _objc_inform("LOAD: category '%s(%s)' scheduled for +load",
1359 cat->class_name, cat->category_name);
1362 if (loadable_categories_used == loadable_categories_allocated) {
1363 loadable_categories_allocated = loadable_categories_allocated*2 + 16;
1364 loadable_categories =
1365 _realloc_internal(loadable_categories,
1366 loadable_categories_allocated *
1367 sizeof(struct loadable_category));
1370 loadable_categories[loadable_categories_used].cat = cat;
1371 loadable_categories[loadable_categories_used].method = method;
1372 loadable_categories_used++;
1376 /***********************************************************************
1377 * remove_class_from_loadable_list
1378 * Class cls may have been loadable before, but it is now no longer
1379 * loadable (because its image is being unmapped).
1380 **********************************************************************/
1381 static void remove_class_from_loadable_list(struct objc_class *cls)
1383 if (loadable_classes) {
1385 for (i = 0; i < loadable_classes_used; i++) {
1386 if (loadable_classes[i].cls == cls) {
1387 loadable_classes[i].cls = NULL;
1389 _objc_inform("LOAD: class '%s' unscheduled for +load", cls->name);
1398 /***********************************************************************
1399 * remove_category_from_loadable_list
1400 * Category cat may have been loadable before, but it is now no longer
1401 * loadable (because its image is being unmapped).
1402 **********************************************************************/
1403 static void remove_category_from_loadable_list(struct objc_category *cat)
1405 if (loadable_categories) {
1407 for (i = 0; i < loadable_categories_used; i++) {
1408 if (loadable_categories[i].cat == cat) {
1409 loadable_categories[i].cat = NULL;
1411 _objc_inform("LOAD: category '%s(%s)' unscheduled for +load",
1412 cat->class_name, cat->category_name);
1421 /***********************************************************************
1423 * Call all pending class +load methods.
1424 * If new classes become loadable, +load is NOT called for them.
1426 * Called only by call_load_methods().
1427 **********************************************************************/
1428 static void call_class_loads(void)
1432 // Detach current loadable list.
1433 struct loadable_class *classes = loadable_classes;
1434 int used = loadable_classes_used;
1435 loadable_classes = NULL;
1436 loadable_classes_allocated = 0;
1437 loadable_classes_used = 0;
1439 // Call all +loads for the detached list.
1440 for (i = 0; i < used; i++) {
1441 struct objc_class *cls = classes[i].cls;
1442 IMP load_method = classes[i].method;
1446 _objc_inform("LOAD: +[%s load]\n", cls->name);
1448 (*load_method) ((id) cls, @selector(load));
1451 // Destroy the detached list.
1452 if (classes) _free_internal(classes);
1456 /***********************************************************************
1457 * call_category_loads
1458 * Call some pending category +load methods.
1459 * The parent class of the +load-implementing categories has all of
1460 * its categories attached, in case some are lazily waiting for +initalize.
1461 * Don't call +load unless the parent class is connected.
1462 * If new categories become loadable, +load is NOT called, and they
1463 * are added to the end of the loadable list, and we return TRUE.
1464 * Return FALSE if no new categories became loadable.
1466 * Called only by call_load_methods().
1467 **********************************************************************/
1468 static BOOL call_category_loads(void)
1471 BOOL new_categories_added = NO;
1473 // Detach current loadable list.
1474 struct loadable_category *cats = loadable_categories;
1475 int used = loadable_categories_used;
1476 int allocated = loadable_categories_allocated;
1477 loadable_categories = NULL;
1478 loadable_categories_allocated = 0;
1479 loadable_categories_used = 0;
1481 // Call all +loads for the detached list.
1482 for (i = 0; i < used; i++) {
1483 struct objc_category *cat = cats[i].cat;
1484 IMP load_method = cats[i].method;
1485 struct objc_class *cls;
1488 cls = objc_getClass(cat->class_name);
1489 if (cls && class_is_connected(cls)) {
1491 _objc_inform("LOAD: +[%s(%s) load]\n",
1492 cls->name, cat->category_name);
1494 (*load_method) ((id) cls, @selector(load));
1499 // Compact detached list (order-preserving)
1501 for (i = 0; i < used; i++) {
1503 cats[i-shift] = cats[i];
1510 // Copy any new +load candidates from the new list to the detached list.
1511 new_categories_added = (loadable_categories_used > 0);
1512 for (i = 0; i < loadable_categories_used; i++) {
1513 if (used == allocated) {
1514 allocated = allocated*2 + 16;
1515 cats = _realloc_internal(cats, allocated *
1516 sizeof(struct loadable_category));
1518 cats[used++] = loadable_categories[i];
1521 // Destroy the new list.
1522 if (loadable_categories) _free_internal(loadable_categories);
1524 // Reattach the (now augmented) detached list.
1525 // But if there's nothing left to load, destroy the list.
1527 loadable_categories = cats;
1528 loadable_categories_used = used;
1529 loadable_categories_allocated = allocated;
1531 if (cats) _free_internal(cats);
1532 loadable_categories = NULL;
1533 loadable_categories_used = 0;
1534 loadable_categories_allocated = 0;
1538 if (loadable_categories_used != 0) {
1539 _objc_inform("LOAD: %d categories still waiting for +load\n",
1540 loadable_categories_used);
1544 return new_categories_added;
1548 /***********************************************************************
1550 * Call all pending class and category +load methods.
1551 * Class +load methods are called superclass-first.
1552 * Category +load methods are not called until after the parent class's +load.
1554 * This method must be RE-ENTRANT, because a +load could trigger
1555 * more image mapping. In addition, the superclass-first ordering
1556 * must be preserved in the face of re-entrant calls. Therefore,
1557 * only the OUTERMOST call of this function will do anything, and
1558 * that call will handle all loadable classes, even those generated
1559 * while it was running.
1561 * The sequence below preserves +load ordering in the face of
1562 * image loading during a +load, and make sure that no
1563 * +load method is forgotten because it was added during
1566 * 1. Repeatedly call class +loads until there aren't any more
1567 * 2. Call category +loads ONCE.
1568 * 3. Run more +loads if:
1569 * (a) there are more classes to load, OR
1570 * (b) there are some potential category +loads that have
1571 * still never been attempted.
1572 * Category +loads are only run once to ensure "parent class first"
1573 * ordering, even if a category +load triggers a new loadable class
1574 * and a new loadable category attached to that class.
1576 * fixme this is not thread-safe, but neither is the rest of image mapping.
1577 **********************************************************************/
1578 static void call_load_methods(void)
1580 static pthread_t load_method_thread NOBSS = NULL;
1581 BOOL more_categories;
1583 if (load_method_thread) {
1584 // +loads are already being called. Do nothing, but complain
1585 // if it looks like multithreaded use of this thread-unsafe code.
1587 if (! pthread_equal(load_method_thread, pthread_self())) {
1588 _objc_inform("WARNING: multi-threaded library loading detected "
1589 "(implementation is not thread-safe)");
1594 // Nobody else is calling +loads, so we should do it ourselves.
1595 load_method_thread = pthread_self();
1598 // 1. Repeatedly call class +loads until there aren't any more
1599 while (loadable_classes_used > 0) {
1603 // 2. Call category +loads ONCE
1604 more_categories = call_category_loads();
1606 // 3. Run more +loads if there are classes OR more untried categories
1607 } while (loadable_classes_used > 0 || more_categories);
1609 load_method_thread = NULL;
1613 /***********************************************************************
1614 * really_connect_class
1615 * Connect cls to superclass supercls unconditionally.
1616 * Also adjust the class hash tables and handle +load and pended subclasses.
1618 * This should be called from connect_class() ONLY.
1619 **********************************************************************/
1620 static void really_connect_class(struct objc_class *cls,
1621 struct objc_class *supercls)
1623 struct objc_class *oldCls;
1624 struct objc_class *meta = cls->isa;
1626 // Wire the classes together.
1628 cls->super_class = supercls;
1629 meta->super_class = supercls->isa;
1630 meta->isa = supercls->isa->isa;
1632 cls->super_class = NULL; // superclass of root class is NULL
1633 meta->super_class = cls; // superclass of root metaclass is root class
1634 meta->isa = meta; // metaclass of root metaclass is root metaclass
1637 OBJC_LOCK(&classLock);
1639 // Update hash tables.
1640 NXHashRemove(unconnected_class_hash, cls);
1641 oldCls = NXHashInsert(class_hash, cls);
1643 // Delete unconnected_class_hash if it is now empty.
1644 if (NXCountHashTable(unconnected_class_hash) == 0) {
1645 NXFreeHashTable(unconnected_class_hash);
1646 unconnected_class_hash = NULL;
1649 OBJC_UNLOCK(&classLock);
1651 // Warn if the new class has the same name as a previously-installed class.
1652 // The new class is kept and the old class is discarded.
1654 const header_info *oldHeader = _headerForClass(oldCls);
1655 const header_info *newHeader = _headerForClass(cls);
1656 const char *oldName = _nameForHeader(oldHeader->mhdr);
1657 const char *newName = _nameForHeader(newHeader->mhdr);
1659 _objc_inform ("Both %s and %s have implementations of class %s.",
1660 oldName, newName, oldCls->name);
1661 _objc_inform ("Using implementation from %s.", newName);
1664 // Prepare for +load and connect newly-connectable subclasses
1665 add_class_to_loadable_list(cls);
1666 resolve_subclasses_of_class(cls);
1668 // GC debugging: make sure all classes with -dealloc also have -finalize
1669 if (CheckFinalizers) {
1670 extern IMP findIMPInClass(Class cls, SEL sel);
1671 if (findIMPInClass(cls, sel_getUid("dealloc")) &&
1672 ! findIMPInClass(cls, sel_getUid("finalize")))
1674 _objc_inform("GC: class '%s' implements -dealloc but not -finalize", cls->name);
1678 // Debugging: if this class has ivars, make sure this class's ivars don't
1679 // overlap with its super's. This catches some broken fragile base classes.
1680 // Do not use super->instance_size vs. self->ivar[0] to check this.
1681 // Ivars may be packed across instance_size boundaries.
1682 if (DebugFragileSuperclasses && cls->ivars && cls->ivars->ivar_count) {
1683 struct objc_class *ivar_cls = supercls;
1685 // Find closest superclass that has some ivars, if one exists.
1687 (!ivar_cls->ivars || ivar_cls->ivars->ivar_count == 0))
1689 ivar_cls = ivar_cls->super_class;
1693 // Compare superclass's last ivar to this class's first ivar
1694 struct objc_ivar *super_ivar =
1695 &ivar_cls->ivars->ivar_list[ivar_cls->ivars->ivar_count - 1];
1696 struct objc_ivar *self_ivar =
1697 &cls->ivars->ivar_list[0];
1699 // fixme could be smarter about super's ivar size
1700 if (self_ivar->ivar_offset <= super_ivar->ivar_offset) {
1701 _objc_inform("WARNING: ivars of superclass '%s' and "
1702 "subclass '%s' overlap; superclass may have "
1703 "changed since subclass was compiled",
1704 ivar_cls->name, cls->name);
1711 /***********************************************************************
1713 * Connect class cls to its superclasses, if possible.
1714 * If cls becomes connected, move it from unconnected_class_hash
1715 * to connected_class_hash.
1716 * Returns TRUE if cls is connected.
1717 * Returns FALSE if cls could not be connected for some reason
1718 * (missing superclass or still-unconnected superclass)
1719 **********************************************************************/
1720 static BOOL connect_class(struct objc_class *cls)
1722 if (class_is_connected(cls)) {
1723 // This class is already connected to its superclass.
1727 else if (cls->super_class == NULL) {
1728 // This class is a root class.
1729 // Connect it to itself.
1731 if (PrintConnecting) {
1732 _objc_inform("CONNECT: class '%s' now connected (root class)",
1736 really_connect_class(cls, NULL);
1740 // This class is not a root class and is not yet connected.
1741 // Connect it if its superclass and root class are already connected.
1742 // Otherwise, add this class to the to-be-connected list,
1743 // pending the completion of its superclass and root class.
1745 // At this point, cls->super_class and cls->isa->isa are still STRINGS
1746 char *supercls_name = (char *)cls->super_class;
1747 struct objc_class *supercls;
1749 // YES unconnected, YES class handler
1750 if (NULL == (supercls = look_up_class(supercls_name, YES, YES))) {
1751 // Superclass does not exist yet.
1752 // pendClassInstallation will handle duplicate pends of this class
1753 pendClassInstallation(cls, supercls_name);
1755 if (PrintConnecting) {
1756 _objc_inform("CONNECT: class '%s' NOT connected (missing super)", cls->name);
1761 if (! connect_class(supercls)) {
1762 // Superclass exists but is not yet connected.
1763 // pendClassInstallation will handle duplicate pends of this class
1764 pendClassInstallation(cls, supercls_name);
1766 if (PrintConnecting) {
1767 _objc_inform("CONNECT: class '%s' NOT connected (unconnected super)", cls->name);
1772 // Superclass exists and is connected.
1773 // Connect this class to the superclass.
1775 if (PrintConnecting) {
1776 _objc_inform("CONNECT: class '%s' now connected", cls->name);
1779 really_connect_class(cls, supercls);
1785 /***********************************************************************
1786 * _objc_read_classes_from_image.
1787 * Read classes from the given image, perform assorted minor fixups,
1788 * Does not connect classes to superclasses.
1789 * Does attach pended categories to the classes.
1790 * Adds all classes to unconnected_class_hash. class_hash is unchanged.
1791 **********************************************************************/
1792 static void _objc_read_classes_from_image(header_info *hi)
1797 int isBundle = (hi->mhdr->filetype == MH_BUNDLE);
1799 if (_objcHeaderIsReplacement(hi)) {
1800 // Ignore any classes in this image
1804 // class_hash starts small, enough only for libobjc itself.
1805 // If other Objective-C libraries are found, immediately resize
1806 // class_hash, assuming that Foundation and AppKit are about
1807 // to add lots of classes.
1808 OBJC_LOCK(&classLock);
1809 if (hi->mhdr != &_mh_dylib_header && _NXHashCapacity(class_hash) < 1024) {
1810 _NXHashRehashToCapacity(class_hash, 1024);
1812 OBJC_UNLOCK(&classLock);
1814 // Major loop - process all modules in the image
1816 for (midx = 0; midx < hi->mod_count; midx += 1)
1818 // Skip module containing no classes
1819 if (mods[midx].symtab == NULL)
1822 // Minor loop - process all the classes in given module
1823 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
1825 struct objc_class * newCls;
1827 // Locate the class description pointer
1828 newCls = mods[midx].symtab->defs[index];
1830 // Classes loaded from Mach-O bundles can be unloaded later.
1831 // Nothing uses this class yet, so _class_setInfo is not needed.
1832 if (isBundle) newCls->info |= CLS_FROM_BUNDLE;
1833 if (isBundle) newCls->isa->info |= CLS_FROM_BUNDLE;
1835 // Use common static empty cache instead of NULL
1836 if (newCls->cache == NULL)
1837 newCls->cache = (Cache) &emptyCache;
1838 if (newCls->isa->cache == NULL)
1839 newCls->isa->cache = (Cache) &emptyCache;
1841 // Set metaclass version
1842 newCls->isa->version = mods[midx].version;
1844 // methodLists is NULL or a single list, not an array
1845 newCls->info |= CLS_NO_METHOD_ARRAY;
1846 newCls->isa->info |= CLS_NO_METHOD_ARRAY;
1848 // Install into unconnected_class_hash
1849 OBJC_LOCK(&classLock);
1850 if (!unconnected_class_hash) {
1851 unconnected_class_hash =
1852 NXCreateHashTableFromZone(classHashPrototype, 128, NULL,
1853 _objc_internal_zone());
1855 NXHashInsert(unconnected_class_hash, newCls);
1856 OBJC_UNLOCK(&classLock);
1858 // Fix up pended class refs to this class, if any
1859 resolve_references_to_class(newCls);
1861 // Attach pended categories for this class, if any
1862 resolve_categories_for_class(newCls);
1868 /***********************************************************************
1869 * _objc_connect_classes_from_image.
1870 * Connect the classes in the given image to their superclasses,
1871 * or register them for later connection if any superclasses are missing.
1872 **********************************************************************/
1873 static void _objc_connect_classes_from_image(header_info *hi)
1878 BOOL replacement = _objcHeaderIsReplacement(hi);
1880 // Major loop - process all modules in the image
1882 for (midx = 0; midx < hi->mod_count; midx += 1)
1884 // Skip module containing no classes
1885 if (mods[midx].symtab == NULL)
1888 // Minor loop - process all the classes in given module
1889 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
1891 struct objc_class *cls = mods[midx].symtab->defs[index];
1892 if (! replacement) {
1893 BOOL connected = connect_class(cls);
1894 if (connected && callbackFunction) {
1895 (*callbackFunction)(cls, 0);
1898 // Replacement image - fix up super_class only (#3704817)
1899 const char *super_name = (const char *) cls->super_class;
1900 if (super_name) cls->super_class = objc_getClass(super_name);
1907 /***********************************************************************
1908 * _objc_map_class_refs_for_image. Convert the class ref entries from
1909 * a class name string pointer to a class pointer. If the class does
1910 * not yet exist, the reference is added to a list of pending references
1911 * to be fixed up at a later date.
1912 **********************************************************************/
1913 static void _objc_map_class_refs_for_image (header_info * hi)
1915 struct objc_class * * cls_refs;
1919 // Locate class refs in image
1920 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
1923 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
1925 // Process each class ref
1926 for (index = 0; index < size; index += 1)
1929 struct objc_class * cls;
1931 // Get ref to convert from name string to class pointer
1932 ref = (const char *) cls_refs[index];
1934 // Get pointer to class of this name
1935 // YES unconnected, YES class loader
1936 cls = look_up_class(ref, YES, YES);
1938 // Referenced class exists. Fix up the reference.
1939 cls_refs[index] = cls;
1941 // Referenced class does not exist yet. Insert a placeholder
1942 // class and fix up the reference later.
1943 pendClassReference (&cls_refs[index], ref);
1944 cls_refs[index] = _objc_getNonexistentClass ();
1950 /***********************************************************************
1951 * _objc_remove_pending_class_refs_in_image
1952 * Delete any pending class ref fixups for class refs in the given image,
1953 * because the image is about to be unloaded.
1954 **********************************************************************/
1955 static void _objc_remove_pending_class_refs_in_image(header_info *hi)
1957 struct objc_class **cls_refs, **cls_refs_end;
1960 if (!pendingClassRefsMap) return;
1962 // Locate class refs in this image
1963 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
1966 cls_refs = (struct objc_class **) ((uintptr_t)cls_refs + hi->image_slide);
1967 cls_refs_end = (struct objc_class **)(size + (uintptr_t)cls_refs);
1969 // Search the pending class ref table for class refs in this range.
1970 // The class refs may have already been stomped with nonexistentClass,
1971 // so there's no way to recover the original class name.
1974 PendingClassRef *pending;
1975 NXMapState state = NXInitMapState(pendingClassRefsMap);
1976 while(NXNextMapState(pendingClassRefsMap, &state,
1977 (const void **)&key, (const void **)&pending))
1979 for ( ; pending != NULL; pending = pending->next) {
1980 if (pending->ref >= cls_refs && pending->ref < cls_refs_end) {
1981 pending->ref = NULL;
1988 /***********************************************************************
1989 * map_selrefs. Register each selector in the specified array. If a
1990 * given selector is already registered, update this array to point to
1991 * the registered selector string.
1992 * If copy is TRUE, all selector data is always copied. This is used
1993 * for registering selectors from unloadable bundles, so the selector
1994 * can still be used after the bundle's data segment is unmapped.
1995 * Returns YES if dst was written to, NO if it was unchanged.
1996 **********************************************************************/
1997 static inline BOOL map_selrefs(SEL *src, SEL *dst, size_t size, BOOL copy)
2000 unsigned int cnt = size / sizeof(SEL);
2005 // Process each selector
2006 for (index = 0; index < cnt; index += 1)
2010 // Lookup pointer to uniqued string
2011 sel = sel_registerNameNoLock((const char *) src[index], copy);
2013 // Replace this selector with uniqued one (avoid
2014 // modifying the VM page if this would be a NOP)
2015 if (dst[index] != sel) {
2027 /***********************************************************************
2028 * map_method_descs. For each method in the specified method list,
2029 * replace the name pointer with a uniqued selector.
2030 * If copy is TRUE, all selector data is always copied. This is used
2031 * for registering selectors from unloadable bundles, so the selector
2032 * can still be used after the bundle's data segment is unmapped.
2033 **********************************************************************/
2034 static void map_method_descs (struct objc_method_description_list * methods, BOOL copy)
2040 // Process each method
2041 for (index = 0; index < methods->count; index += 1)
2043 struct objc_method_description * method;
2046 // Get method entry to fix up
2047 method = &methods->list[index];
2049 // Lookup pointer to uniqued string
2050 sel = sel_registerNameNoLock((const char *) method->name, copy);
2052 // Replace this selector with uniqued one (avoid
2053 // modifying the VM page if this would be a NOP)
2054 if (method->name != sel)
2061 /***********************************************************************
2063 **********************************************************************/
2064 @interface Protocol(RuntimePrivate)
2065 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
2068 /***********************************************************************
2069 * _objc_fixup_protocol_objects_for_image. For each protocol in the
2070 * specified image, selectorize the method names and call +_fixup.
2071 **********************************************************************/
2072 static void _objc_fixup_protocol_objects_for_image (header_info * hi)
2075 OBJC_PROTOCOL_PTR protos;
2077 int isBundle = hi->mhdr->filetype == MH_BUNDLE;
2079 // Locate protocols in the image
2080 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
2084 // Apply the slide bias
2085 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
2087 // Process each protocol
2088 for (index = 0; index < size; index += 1)
2090 // Selectorize the instance methods
2091 if (protos[index] OBJC_PROTOCOL_DEREF instance_methods)
2092 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF instance_methods, isBundle);
2094 // Selectorize the class methods
2095 if (protos[index] OBJC_PROTOCOL_DEREF class_methods)
2096 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF class_methods, isBundle);
2099 // Invoke Protocol class method to fix up the protocol
2100 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
2103 /***********************************************************************
2104 * _objc_headerStart. Return what headers we know about.
2105 **********************************************************************/
2106 header_info * _objc_headerStart ()
2109 // Take advatage of our previous work
2113 void _objc_bindModuleContainingList() {
2114 /* We define this for backwards binary compat with things which should not
2115 * have been using it (cough OmniWeb), but now it does nothing for them.
2120 /***********************************************************************
2122 **********************************************************************/
2124 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
2125 #define HINFO_SIZE 16
2127 static int HeaderInfoCounter NOBSS = 0;
2128 static header_info HeaderInfoTable[HINFO_SIZE] NOBSS = { {0} };
2130 static header_info * _objc_addHeader(const struct mach_header *header)
2133 uintptr_t mod_unslid;
2134 uint32_t info_size = 0;
2135 uintptr_t image_info_unslid;
2136 const struct segment_command *objc_segment;
2138 header_info *result;
2140 // Locate the __OBJC segment
2141 objc_segment = getsegbynamefromheader(header, SEG_OBJC);
2142 if (!objc_segment) return NULL;
2144 // Locate some sections in the __OBJC segment
2145 mod_unslid = (uintptr_t)_getObjcModules(header, &mod_count);
2146 if (!mod_unslid) return NULL;
2147 image_info_unslid = (uintptr_t)_getObjcImageInfo(header, &info_size);
2149 // Calculate vm slide.
2150 slide = _getImageSlide(header);
2153 // Find or allocate a header_info entry.
2154 if (HeaderInfoCounter < HINFO_SIZE) {
2155 result = &HeaderInfoTable[HeaderInfoCounter++];
2157 result = _malloc_internal(sizeof(header_info));
2160 // Set up the new header_info entry.
2161 result->mhdr = header;
2162 result->mod_ptr = (Module)(mod_unslid + slide);
2163 result->mod_count = mod_count;
2164 result->image_slide = slide;
2165 result->objcSegmentHeader = objc_segment;
2166 if (image_info_unslid) {
2167 result->info = (objc_image_info *)(image_info_unslid + slide);
2169 result->info = NULL;
2172 // Make sure every copy of objc_image_info in this image is the same.
2173 // This means same version and same bitwise contents.
2175 objc_image_info *start = result->info;
2176 objc_image_info *end =
2177 (objc_image_info *)(info_size + (uint8_t *)start);
2178 objc_image_info *info = start;
2179 while (info < end) {
2180 // version is byte size, except for version 0
2181 size_t struct_size = info->version;
2182 if (struct_size == 0) struct_size = 2 * sizeof(uint32_t);
2183 if (info->version != start->version ||
2184 0 != memcmp(info, start, struct_size))
2186 _objc_fatal("'%s' has inconsistently-compiled Objective-C "
2187 "code. Please recompile all code in it.",
2188 _nameForHeader(header));
2190 info = (objc_image_info *)(struct_size + (uint8_t *)info);
2194 // Add the header to the header list.
2195 // The header is appended to the list, to preserve the bottom-up order.
2196 result->next = NULL;
2199 FirstHeader = LastHeader = result;
2202 // list is not empty, but LastHeader is invalid - recompute it
2203 LastHeader = FirstHeader;
2204 while (LastHeader->next) LastHeader = LastHeader->next;
2206 // LastHeader is now valid
2207 LastHeader->next = result;
2208 LastHeader = result;
2215 /***********************************************************************
2216 * _objc_RemoveHeader
2217 * Remove the given header from the header list.
2218 * FirstHeader is updated.
2219 * LastHeader is set to NULL. Any code that uses LastHeader must
2220 * detect this NULL and recompute LastHeader by traversing the list.
2221 **********************************************************************/
2222 static void _objc_removeHeader(header_info *hi)
2226 for (hiP = &FirstHeader; *hiP != NULL; hiP = &(**hiP).next) {
2228 header_info *deadHead = *hiP;
2230 // Remove from the linked list (updating FirstHeader if necessary).
2231 *hiP = (**hiP).next;
2233 // Update LastHeader if necessary.
2234 if (LastHeader == deadHead) {
2235 LastHeader = NULL; // will be recomputed next time it's used
2238 // Free the memory, unless it was in the static HeaderInfoTable.
2239 if (deadHead < HeaderInfoTable ||
2240 deadHead >= HeaderInfoTable + HINFO_SIZE)
2242 _free_internal(deadHead);
2251 /***********************************************************************
2253 * Check whether the executable supports or requires GC, and make sure
2254 * all already-loaded libraries support the executable's GC mode.
2255 * Returns TRUE if the executable wants GC on.
2256 **********************************************************************/
2257 static BOOL check_wants_gc(void)
2259 // GC is off in Tiger.
2262 const header_info *hi;
2265 // Environment variables can override the following.
2267 _objc_inform("GC: forcing GC ON because OBJC_FORCE_GC is set");
2270 else if (ForceNoGC) {
2271 _objc_inform("GC: forcing GC OFF because OBJC_FORCE_NO_GC is set");
2275 // Find the executable and check its GC bits.
2276 // If the executable cannot be found, default to NO.
2277 // (The executable will not be found if the executable contains
2278 // no Objective-C code.)
2280 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
2281 if (hi->mhdr->filetype == MH_EXECUTE) {
2282 appWantsGC = _objcHeaderSupportsGC(hi) ? YES : NO;
2284 _objc_inform("GC: executable '%s' %s GC",
2285 _nameForHeader(hi->mhdr),
2286 appWantsGC ? "supports" : "does not support");
2295 /***********************************************************************
2296 * verify_gc_readiness
2297 * if we want gc, verify that every header describes files compiled
2298 * and presumably ready for gc.
2299 ************************************************************************/
2301 static void verify_gc_readiness(BOOL wantsGC, header_info *hi)
2305 // Find the libraries and check their GC bits against the app's request
2306 for (; hi != NULL; hi = hi->next) {
2307 if (hi->mhdr->filetype == MH_EXECUTE) {
2310 else if (hi->mhdr == &_mh_dylib_header) {
2311 // libobjc itself works with anything even though it is not
2312 // compiled with -fobjc-gc (fixme should it be?)
2314 else if (wantsGC && ! _objcHeaderSupportsGC(hi)) {
2315 // App wants GC but library does not support it - bad
2316 _objc_inform("'%s' was not compiled with -fobjc-gc, but "
2317 "the application requires GC",
2318 _nameForHeader(hi->mhdr));
2323 _objc_inform("GC: library '%s' %s GC", _nameForHeader(hi->mhdr),
2324 _objcHeaderSupportsGC(hi) ? "supports" : "does not support");
2329 // GC state is not consistent.
2330 // Kill the process unless one of the forcing flags is set.
2331 if (!ForceGC && !ForceNoGC) {
2332 _objc_fatal("*** GC capability of application and some libraries did not match");
2338 /***********************************************************************
2339 * _objc_fixup_selector_refs. Register all of the selectors in each
2340 * image, and fix them all up.
2342 * If the image is a dylib (not a bundle or an executable), and contains
2343 * at least one full aligned page of selector refs, this function uses
2344 * the shared range functions to try to recycle already-written memory
2345 * from other processes.
2346 **********************************************************************/
2347 static void _objc_fixup_selector_refs (const header_info * hi)
2351 vm_address_t local_sels;
2352 vm_size_t local_size;
2356 // Fix up message refs
2357 local_sels = (vm_address_t) _getObjcMessageRefs ((headerType *) hi->mhdr, &count);
2358 local_size = count * sizeof(SEL);
2361 vm_address_t aligned_start, aligned_end;
2363 local_sels = local_sels + hi->image_slide;
2364 aligned_start = round_page(local_sels);
2365 aligned_end = trunc_page(local_sels + local_size);
2367 if (aligned_start >= aligned_end ||
2368 hi->mhdr->filetype == MH_BUNDLE ||
2369 hi->mhdr->filetype == MH_EXECUTE)
2371 // Less than a page of sels, OR bundle or executable - fix in place
2373 map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size,
2374 hi->mhdr->filetype == MH_BUNDLE);
2377 _objc_inform("SHARING: NONE [%p..%p) (%d pages) for %s",
2378 local_sels, local_sels+local_size,
2379 (aligned_end > aligned_start ?
2380 (aligned_end-aligned_start) / vm_page_size : 0),
2381 _nameForHeader(hi->mhdr));
2385 // At least one page of sels - try to use sharing
2386 vm_range_t remote_range;
2389 _objc_inform("SHARING: looking for range [%p..%p) ...",
2390 aligned_start, aligned_end);
2393 remote_range = get_shared_range(aligned_start, aligned_end);
2395 if (remote_range.address != 0) {
2396 // Sharing succeeded - fix using remote_range
2399 // local_sels..aligned_start (unshared)
2400 map_selrefs((SEL *)local_sels, (SEL *)local_sels,
2401 aligned_start - local_sels, NO);
2402 // aligned_start..aligned_end (shared)
2404 map_selrefs((SEL *)aligned_start, (SEL *)remote_range.address,
2405 aligned_end - aligned_start, NO);
2406 // aligned_end..local_sels+local_size (unshared)
2407 map_selrefs((SEL *)aligned_end, (SEL *)aligned_end,
2408 local_sels+local_size - aligned_end, NO);
2410 install_shared_range(remote_range, aligned_start);
2413 _objc_inform("SHARING: %s [%p..%p) (%d pages) for %s",
2414 stomped ? "TRIED" : "USING",
2415 local_sels, local_sels+local_size,
2416 (aligned_end-aligned_start) / vm_page_size,
2417 _nameForHeader(hi->mhdr));
2421 // Sharing failed, including first process -
2422 // fix in place and then offer to share
2424 map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size, NO);
2426 offer_shared_range(aligned_start, aligned_end);
2429 _objc_inform("SHARING: OFFER [%p..%p) (%d pages) for %s",
2430 local_sels, local_sels+local_size,
2431 (aligned_end-aligned_start) / vm_page_size,
2432 _nameForHeader(hi->mhdr));
2440 /***********************************************************************
2441 * objc_setConfiguration
2442 * Read environment variables that affect the runtime.
2443 * Also print environment variable help, if requested.
2444 **********************************************************************/
2445 static void objc_setConfiguration() {
2446 int PrintHelp = (getenv("OBJC_HELP") != NULL);
2447 int PrintOptions = (getenv("OBJC_PRINT_OPTIONS") != NULL);
2450 _objc_inform("OBJC_HELP: describe Objective-C runtime environment variables");
2452 _objc_inform("OBJC_HELP is set");
2454 _objc_inform("OBJC_PRINT_OPTIONS: list which options are set");
2457 _objc_inform("OBJC_PRINT_OPTIONS is set");
2460 #define OPTION(var, env, help) \
2461 if ( var == -1 ) { \
2462 var = getenv(#env) != NULL; \
2463 if (PrintHelp) _objc_inform(#env ": " help); \
2464 if (PrintOptions && var) _objc_inform(#env " is set"); \
2467 OPTION(PrintImages, OBJC_PRINT_IMAGES,
2468 "log image and library names as the runtime loads them");
2469 OPTION(PrintConnecting, OBJC_PRINT_CONNECTION,
2470 "log progress of class and category connections");
2471 OPTION(PrintLoading, OBJC_PRINT_LOAD_METHODS,
2472 "log class and category +load methods as they are called");
2473 OPTION(PrintRTP, OBJC_PRINT_RTP,
2474 "log initialization of the Objective-C runtime pages");
2475 OPTION(PrintGC, OBJC_PRINT_GC,
2476 "log some GC operations");
2477 OPTION(PrintSharing, OBJC_PRINT_SHARING,
2478 "log cross-process memory sharing");
2479 OPTION(PrintCxxCtors, OBJC_PRINT_CXX_CTORS,
2480 "log calls to C++ ctors and dtors for instance variables");
2482 OPTION(DebugUnload, OBJC_DEBUG_UNLOAD,
2483 "warn about poorly-behaving bundles when unloaded");
2484 OPTION(DebugFragileSuperclasses, OBJC_DEBUG_FRAGILE_SUPERCLASSES,
2485 "warn about subclasses that may have been broken by subsequent changes to superclasses");
2487 OPTION(UseInternalZone, OBJC_USE_INTERNAL_ZONE,
2488 "allocate runtime data in a dedicated malloc zone");
2489 OPTION(AllowInterposing, OBJC_ALLOW_INTERPOSING,
2490 "allow function interposing of objc_msgSend()");
2492 OPTION(ForceGC, OBJC_FORCE_GC,
2493 "force GC ON, even if the executable wants it off");
2494 OPTION(ForceNoGC, OBJC_FORCE_NO_GC,
2495 "force GC OFF, even if the executable wants it on");
2496 OPTION(CheckFinalizers, OBJC_CHECK_FINALIZERS,
2497 "warn about classes that implement -dealloc but not -finalize");
2502 /***********************************************************************
2503 * objc_setMultithreaded.
2504 **********************************************************************/
2505 void objc_setMultithreaded (BOOL flag)
2507 // Nothing here. Thread synchronization in the runtime is always active.
2512 /***********************************************************************
2513 * _objc_pthread_destroyspecific
2514 * Destructor for objc's per-thread data.
2515 * arg shouldn't be NULL, but we check anyway.
2516 **********************************************************************/
2517 extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
2518 void _objc_pthread_destroyspecific(void *arg)
2520 _objc_pthread_data *data = (_objc_pthread_data *)arg;
2522 _destroyInitializingClassList(data->initializingClasses);
2524 // add further cleanup here...
2526 _free_internal(data);
2531 /***********************************************************************
2533 * Former library initializer. This function is now merely a placeholder
2534 * for external callers. All runtime initialization has now been moved
2536 **********************************************************************/
2537 void _objcInit(void)
2543 /***********************************************************************
2545 * Process the given images which are being mapped in by dyld.
2546 * All class registration and fixups are performed (or deferred pending
2547 * discovery of missing superclasses etc), and +load methods are called.
2549 * info[] is in bottom-up order i.e. libobjc will be earlier in the
2550 * array than any library that links to libobjc.
2551 **********************************************************************/
2552 static void map_images(const struct dyld_image_info infoList[],
2555 static BOOL firstTime = YES;
2556 static BOOL wantsGC NOBSS = NO;
2558 header_info *firstNewHeader = NULL;
2561 // Perform first-time initialization if necessary.
2562 // This function is called before ordinary library initializers.
2564 pthread_key_create(&_objc_pthread_key, _objc_pthread_destroyspecific);
2565 objc_setConfiguration(); // read environment variables
2566 _objc_init_class_hash (); // create class_hash
2567 // grab selectors for which @selector() doesn't work
2568 cxx_construct_sel = sel_registerName(cxx_construct_name);
2569 cxx_destruct_sel = sel_registerName(cxx_destruct_name);
2573 _objc_inform("IMAGES: processing %u newly-mapped images...\n", infoCount);
2577 // Find all images with an __OBJC segment.
2578 // firstNewHeader is set the the first one, and the header_info
2579 // linked list following firstNewHeader is the rest.
2580 for (i = 0; i < infoCount; i++) {
2581 const struct mach_header *mhdr = infoList[i].imageLoadAddress;
2583 hInfo = _objc_addHeader(mhdr);
2585 // no objc data in this entry
2587 _objc_inform("IMAGES: image '%s' contains no __OBJC segment\n",
2588 infoList[i].imageFilePath);
2593 if (!firstNewHeader) firstNewHeader = hInfo;
2596 _objc_inform("IMAGES: loading image for %s%s%s%s\n",
2597 _nameForHeader(mhdr),
2598 mhdr->filetype == MH_BUNDLE ? " (bundle)" : "",
2599 _objcHeaderIsReplacement(hInfo) ? " (replacement)":"",
2600 _objcHeaderSupportsGC(hInfo) ? " (supports GC)":"");
2604 // Perform one-time runtime initialization that must be deferred until
2605 // the executable itself is found. This needs to be done before
2606 // further initialization.
2607 // (The executable may not be present in this infoList if the
2608 // executable does not contain Objective-C code but Objective-C
2609 // is dynamically loaded later. In that case, check_wants_gc()
2610 // will do the right thing.)
2612 wantsGC = check_wants_gc();
2613 verify_gc_readiness(wantsGC, FirstHeader);
2614 // TIGER DEVELOPMENT ONLY
2615 // REQUIRE A SPECIAL NON-SHIPPING FILE TO ENABLE GC
2617 // make sure that the special file is there before proceeding with GC
2618 struct stat ignored;
2619 wantsGC = stat("/autozone", &ignored) != -1;
2620 if (!wantsGC && PrintGC)
2621 _objc_inform("GC: disabled, lacking /autozone file");
2624 gc_init(wantsGC); // needs executable for GC decision
2625 rtp_init(); // needs GC decision first
2627 verify_gc_readiness(wantsGC, firstNewHeader);
2631 // Initialize everything. Parts of this order are important for
2632 // correctness or performance.
2634 // Read classes from all images.
2635 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2636 _objc_read_classes_from_image(hInfo);
2639 // Read categories from all images.
2640 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2641 _objc_read_categories_from_image(hInfo);
2644 // Connect classes from all images.
2645 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2646 _objc_connect_classes_from_image(hInfo);
2649 // Fix up class refs, selector refs, and protocol objects from all images.
2650 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2651 _objc_map_class_refs_for_image(hInfo);
2652 _objc_fixup_selector_refs(hInfo);
2653 _objc_fixup_protocol_objects_for_image(hInfo);
2656 // Close any shared range file left open during selector uniquing
2657 clear_shared_range_file_cache();
2661 // Call pending +load methods.
2662 // Note that this may in turn cause map_images() to be called again.
2663 call_load_methods();
2667 /***********************************************************************
2669 * Process the given images which are about to be unmapped by dyld.
2670 * Currently we assume only MH_BUNDLE images are unmappable, and
2671 * print warnings about anything else.
2672 **********************************************************************/
2673 static void unmap_images(const struct dyld_image_info infoList[],
2679 _objc_inform("IMAGES: processing %u newly-unmapped images...\n", infoCount);
2682 for (i = 0; i < infoCount; i++) {
2683 const struct mach_header *mhdr = infoList[i].imageLoadAddress;
2685 if (mhdr->filetype == MH_BUNDLE) {
2686 _objc_unmap_image(mhdr);
2688 // currently only MH_BUNDLEs can be unmapped safely
2690 _objc_inform("IMAGES: unmapped image '%s' was not a Mach-O bundle; ignoring\n", infoList[i].imageFilePath);
2697 /***********************************************************************
2698 * _objc_notify_images
2699 * Callback from dyld informing objc of images to be added or removed.
2700 * This function is never called directly. Instead, a section
2701 * __OBJC,__image_notify contains a function pointer to this, and dyld
2702 * discovers it from there.
2703 **********************************************************************/
2705 void _objc_notify_images(enum dyld_image_mode mode, uint32_t infoCount,
2706 const struct dyld_image_info infoList[])
2708 if (mode == dyld_image_adding) {
2709 map_images(infoList, infoCount);
2710 } else if (mode == dyld_image_removing) {
2711 unmap_images(infoList, infoCount);
2716 /***********************************************************************
2717 * _objc_remove_classes_in_image
2718 * Remove all classes in the given image from the runtime, because
2719 * the image is about to be unloaded.
2720 * Things to clean up:
2722 * unconnected_class_hash
2723 * pending subclasses list (only if class is still unconnected)
2724 * loadable class list
2725 * class's method caches
2726 * class refs in all other images
2727 **********************************************************************/
2728 static void _objc_remove_classes_in_image(header_info *hi)
2734 OBJC_LOCK(&classLock);
2736 // Major loop - process all modules in the image
2738 for (midx = 0; midx < hi->mod_count; midx += 1)
2740 // Skip module containing no classes
2741 if (mods[midx].symtab == NULL)
2744 // Minor loop - process all the classes in given module
2745 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
2747 struct objc_class * cls;
2749 // Locate the class description pointer
2750 cls = mods[midx].symtab->defs[index];
2752 // Remove from loadable class list, if present
2753 remove_class_from_loadable_list(cls);
2755 // Remove from unconnected_class_hash and pending subclasses
2756 if (unconnected_class_hash && NXHashMember(unconnected_class_hash, cls)) {
2757 NXHashRemove(unconnected_class_hash, cls);
2758 if (pendingSubclassesMap) {
2759 // Find this class in its superclass's pending list
2760 char *supercls_name = (char *)cls->super_class;
2761 PendingSubclass *pending =
2762 NXMapGet(pendingSubclassesMap, supercls_name);
2763 for ( ; pending != NULL; pending = pending->next) {
2764 if (pending->subclass == cls) {
2765 pending->subclass = Nil;
2772 // Remove from class_hash
2773 NXHashRemove(class_hash, cls);
2775 // Free method list array (from objcTweakMethodListPointerForClass)
2776 // These blocks might be from user code; don't use free_internal
2777 if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) {
2778 free(cls->methodLists);
2780 if (cls->isa->methodLists && !(cls->isa->info & CLS_NO_METHOD_ARRAY)) {
2781 free(cls->isa->methodLists);
2784 // Free method caches, if any
2785 if (cls->cache && cls->cache != &emptyCache) {
2786 _free_internal(cls->cache);
2788 if (cls->isa->cache && cls->isa->cache != &emptyCache) {
2789 _free_internal(cls->isa->cache);
2795 // Search all other images for class refs that point back to this range.
2796 // Un-fix and re-pend any such class refs.
2798 // Get the location of the dying image's __OBJC segment
2799 uintptr_t seg = hi->objcSegmentHeader->vmaddr + hi->image_slide;
2800 size_t seg_size = hi->objcSegmentHeader->filesize;
2802 header_info *other_hi;
2803 for (other_hi = FirstHeader; other_hi != NULL; other_hi = other_hi->next) {
2804 struct objc_class **other_refs;
2806 if (other_hi == hi) continue; // skip the image being unloaded
2808 // Locate class refs in the other image
2809 other_refs = _getObjcClassRefs((headerType *)other_hi->mhdr, &size);
2810 if (!other_refs) continue;
2811 other_refs = (struct objc_class **)((uintptr_t)other_refs + other_hi->image_slide);
2813 // Process each class ref
2814 for (index = 0; index < size; index++) {
2815 if ((uintptr_t)(other_refs[index]) >= seg &&
2816 (uintptr_t)(other_refs[index]) < seg+seg_size)
2818 pendClassReference(&other_refs[index],other_refs[index]->name);
2819 other_refs[index] = _objc_getNonexistentClass ();
2824 OBJC_UNLOCK(&classLock);
2828 /***********************************************************************
2829 * _objc_remove_categories_in_image
2830 * Remove all categories in the given image from the runtime, because
2831 * the image is about to be unloaded.
2832 * Things to clean up:
2833 * unresolved category list
2834 * loadable category list
2835 **********************************************************************/
2836 static void _objc_remove_categories_in_image(header_info *hi)
2841 // Major loop - process all modules in the header
2844 for (midx = 0; midx < hi->mod_count; midx++) {
2847 Symtab symtab = mods[midx].symtab;
2849 // Nothing to do for a module without a symbol table
2850 if (symtab == NULL) continue;
2852 // Total entries in symbol table (class entries followed
2853 // by category entries)
2854 total = symtab->cls_def_cnt + symtab->cat_def_cnt;
2856 // Minor loop - check all categories from given module
2857 for (index = symtab->cls_def_cnt; index < total; index++) {
2858 struct objc_category *cat = symtab->defs[index];
2860 // Clean up loadable category list
2861 remove_category_from_loadable_list(cat);
2863 // Clean up category_hash
2864 if (category_hash) {
2865 _objc_unresolved_category *cat_entry =
2866 NXMapGet(category_hash, cat->class_name);
2867 for ( ; cat_entry != NULL; cat_entry = cat_entry->next) {
2868 if (cat_entry->cat == cat) {
2869 cat_entry->cat = NULL;
2879 /***********************************************************************
2881 * Various paranoid debugging checks that look for poorly-behaving
2882 * unloadable bundles.
2883 * Called by _objc_unmap_image when OBJC_UNLOAD_DEBUG is set.
2884 **********************************************************************/
2885 static void unload_paranoia(header_info *hi)
2887 // Get the location of the dying image's __OBJC segment
2888 uintptr_t seg = hi->objcSegmentHeader->vmaddr + hi->image_slide;
2889 size_t seg_size = hi->objcSegmentHeader->filesize;
2891 _objc_inform("UNLOAD DEBUG: unloading image '%s' [%p..%p]",
2892 _nameForHeader(hi->mhdr), seg, seg+seg_size);
2894 OBJC_LOCK(&classLock);
2896 // Make sure the image contains no categories on surviving classes.
2901 // Major loop - process all modules in the header
2904 for (midx = 0; midx < hi->mod_count; midx++) {
2907 Symtab symtab = mods[midx].symtab;
2909 // Nothing to do for a module without a symbol table
2910 if (symtab == NULL) continue;
2912 // Total entries in symbol table (class entries followed
2913 // by category entries)
2914 total = symtab->cls_def_cnt + symtab->cat_def_cnt;
2916 // Minor loop - check all categories from given module
2917 for (index = symtab->cls_def_cnt; index < total; index++) {
2918 struct objc_category *cat = symtab->defs[index];
2919 struct objc_class query;
2921 query.name = cat->class_name;
2922 if (NXHashMember(class_hash, &query)) {
2923 _objc_inform("UNLOAD DEBUG: dying image contains category '%s(%s)' on surviving class '%s'!", cat->class_name, cat->category_name, cat->class_name);
2929 // Make sure no surviving class is in the dying image.
2930 // Make sure no surviving class has a superclass in the dying image.
2931 // fixme check method implementations too
2933 struct objc_class *cls;
2936 state = NXInitHashState(class_hash);
2937 while (NXNextHashState(class_hash, &state, (void **)&cls)) {
2938 if ((vm_address_t)cls >= seg &&
2939 (vm_address_t)cls < seg+seg_size)
2941 _objc_inform("UNLOAD DEBUG: dying image contains surviving class '%s'!", cls->name);
2944 if ((vm_address_t)cls->super_class >= seg &&
2945 (vm_address_t)cls->super_class < seg+seg_size)
2947 _objc_inform("UNLOAD DEBUG: dying image contains superclass '%s' of surviving class '%s'!", cls->super_class->name, cls->name);
2952 OBJC_UNLOCK(&classLock);
2956 /***********************************************************************
2957 * _objc_unmap_image.
2958 * Destroy any Objective-C data for the given image, which is about to
2959 * be unloaded by dyld.
2960 * Note: not thread-safe, but image loading isn't either.
2961 **********************************************************************/
2962 static void _objc_unmap_image(const headerType *mh)
2966 // Find the runtime's header_info struct for the image
2967 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
2968 if (hi->mhdr == mh) break;
2970 if (hi == NULL) return; // no objc data for this image
2973 _objc_inform("IMAGES: unloading image for %s%s%s%s\n",
2975 mh->filetype == MH_BUNDLE ? " (bundle)" : "",
2976 _objcHeaderIsReplacement(hi) ? " (replacement)" : "",
2977 _objcHeaderSupportsGC(hi) ? " (supports GC)" : "");
2981 // Remove image's classes from the class list and free auxiliary data.
2982 // Remove image's unresolved or loadable categories and free auxiliary data
2983 // Remove image's unresolved class refs.
2984 _objc_remove_classes_in_image(hi);
2985 _objc_remove_categories_in_image(hi);
2986 _objc_remove_pending_class_refs_in_image(hi);
2988 // Perform various debugging checks if requested.
2989 if (DebugUnload) unload_paranoia(hi);
2991 // Remove header_info from header list
2992 _objc_removeHeader(hi);
2996 /***********************************************************************
2997 * _objc_setNilReceiver
2998 **********************************************************************/
2999 id _objc_setNilReceiver(id newNilReceiver)
3003 oldNilReceiver = _objc_nilReceiver;
3004 _objc_nilReceiver = newNilReceiver;
3006 return oldNilReceiver;
3009 /***********************************************************************
3010 * _objc_getNilReceiver
3011 **********************************************************************/
3012 id _objc_getNilReceiver(void)
3014 return _objc_nilReceiver;
3018 /***********************************************************************
3019 * _objc_setClassLoader
3020 * Similar to objc_setClassHandler, but objc_classLoader is used for
3021 * both objc_getClass() and objc_lookupClass(), and objc_classLoader
3022 * pre-empts objc_classHandler.
3023 **********************************************************************/
3024 void _objc_setClassLoader(BOOL (*newClassLoader)(const char *))
3026 _objc_classLoader = newClassLoader;
3030 #if defined(__ppc__)
3032 /**********************************************************************
3034 * Writes at entry a PPC branch instruction sequence that branches to target.
3035 * The sequence written will be 1 or 4 instructions long.
3036 * Returns the number of instructions written.
3037 **********************************************************************/
3038 __private_extern__ size_t objc_write_branch(void *entry, void *target)
3040 unsigned *address = (unsigned *)entry; // location to store the 32 bit PPC instructions
3041 intptr_t destination = (intptr_t)target; // destination as an absolute address
3042 intptr_t displacement = (intptr_t)destination - (intptr_t)address; // destination as a branch relative offset
3044 // Test to see if either the displacement or destination is within the +/- 2^25 range needed
3045 // for a simple PPC branch instruction. Shifting the high bit of the displacement (or destination)
3046 // left 6 bits and then 6 bits arithmetically to the right does a sign extend of the 26th bit. If
3047 // that result is equivalent to the original value, then the displacement (or destination) will fit
3048 // into a simple branch. Otherwise a four instruction branch sequence is required.
3049 if (((displacement << 6) >> 6) == displacement) {
3050 // use a relative branch with the displacement
3051 address[0] = 0x48000000 | (displacement & 0x03fffffc); // b *+displacement
3052 // issued 1 instruction
3054 } else if (((destination << 6) >> 6) == destination) {
3055 // use an absolute branch with the destination
3056 address[0] = 0x48000000 | (destination & 0x03fffffc) | 2; // ba destination (2 is the absolute flag)
3057 // issued 1 instruction
3060 // The four instruction branch sequence requires that the destination be loaded
3061 // into a register, moved to the CTR register then branch using the contents
3062 // of the CTR register.
3063 unsigned lo = destination & 0xffff;
3064 unsigned hi = (destination >> 16) & 0xffff;
3066 address[0] = 0x3d800000 | hi; // lis r12,hi ; load the hi half of destination
3067 address[1] = 0x618c0000 | lo; // ori r12,r12,lo ; merge in the lo half of destination
3068 address[2] = 0x7d8903a6; // mtctr ; move destination to the CTR register
3069 address[3] = 0x4e800420; // bctr ; branch to destination
3070 // issued 4 instructions
3079 /**********************************************************************
3081 * Securely open a file from a world-writable directory (like /tmp)
3082 * If the file does not exist, it will be atomically created with mode 0600
3083 * If the file exists, it must be, and remain after opening:
3084 * 1. a regular file (in particular, not a symlink)
3086 * 3. permissions 0600
3087 * 4. link count == 1
3088 * Returns a file descriptor or -1. Errno may or may not be set on error.
3089 **********************************************************************/
3090 __private_extern__ int secure_open(const char *filename, int flags, uid_t euid)
3097 if (flags & O_TRUNC) {
3098 // Don't truncate the file until after it is open and verified.
3102 if (flags & O_CREAT) {
3103 // Don't create except when we're ready for it
3109 if (lstat(filename, &ls) < 0) {
3110 if (errno == ENOENT && create) {
3111 // No such file - create it
3112 fd = open(filename, flags | O_CREAT | O_EXCL, 0600);
3114 // File was created successfully.
3115 // New file does not need to be truncated.
3118 // File creation failed.
3122 // lstat failed, or user doesn't want to create the file
3126 // lstat succeeded - verify attributes and open
3127 if (S_ISREG(ls.st_mode) && // regular file?
3128 ls.st_nlink == 1 && // link count == 1?
3129 ls.st_uid == euid && // owned by euid?
3130 (ls.st_mode & ALLPERMS) == (S_IRUSR | S_IWUSR)) // mode 0600?
3132 // Attributes look ok - open it and check attributes again
3133 fd = open(filename, flags, 0000);
3135 // File is open - double-check attributes
3136 if (0 == fstat(fd, &fs) &&
3137 fs.st_nlink == ls.st_nlink && // link count == 1?
3138 fs.st_uid == ls.st_uid && // owned by euid?
3139 fs.st_mode == ls.st_mode && // regular file, 0600?
3140 fs.st_ino == ls.st_ino && // same inode as before?
3141 fs.st_dev == ls.st_dev) // same device as before?
3143 // File is open and OK
3144 if (truncate) ftruncate(fd, 0);
3147 // Opened file looks funny - close it
3156 // Unopened file looks funny - don't open it
3163 /**********************************************************************
3164 * Shared range support:
3166 * Some libraries contain many pages worth of selector references.
3167 * In most processes, these libraries get loaded at the same addresses,
3168 * so the selectors are uniqued to the same values. To save memory,
3169 * the runtime tries to share these memory pages across processes.
3171 * A file /tmp/objc_sharing_<arch>_<euid> records memory ranges and process
3172 * IDs. When a set of selector refs is to be uniqued, this file is checked
3173 * for a matching memory range being shared by another process. If
3174 * such a range is found:
3175 * 1. map the sharing process's memory somewhere into this address space
3176 * 2. read from the real selector refs and write into the mapped memory.
3177 * 3. vm_copy from the mapped memory to the real selector refs location
3178 * 4. deallocate the mapped memory
3180 * The mapped memory is merely used as a guess. Correct execution is
3181 * guaranteed no matter what values the mapped memory actually contains.
3182 * If the mapped memory really matches the values needed in this process,
3183 * the mapped memory will be unchanged. If the mapped memory doesn't match,
3184 * or contains random values, it will be fixed up to the correct values.
3185 * The memory is shared whenever the guess happens to be correct.
3187 * The file of shared ranges is imprecise. Processes may die leaving
3188 * their entries in the file. A PID may be recycled to some process that
3189 * does not use Objective-C. The sharing mechanism is robust in the face
3190 * of these failures. Bad shared memory is simply fixed up. No shared
3191 * memory means the selectors are fixed in place. If an entry in the
3192 * file is found to be unusable, the process that finds it will instead
3193 * offer to share its own memory, replacing the bad entry in the file.
3195 * Individual entries in the file are written atomically, but the file is
3196 * otherwise unsynchronized. At worst, a sharing opportunity may be missed
3197 * because two new entries are written simultaneously in the same place.
3198 **********************************************************************/
3201 struct remote_range_t {
3207 // Cache for the last shared range file used, and its EUID.
3208 static pthread_mutex_t sharedRangeLock = PTHREAD_MUTEX_INITIALIZER;
3209 static uid_t sharedRangeEUID = 0;
3210 static FILE * sharedRangeFile = NULL;
3211 static BOOL sharedRangeFileInUse = NO;
3214 /**********************************************************************
3215 * open_shared_range_file
3216 * Open the shared range file "/tmp/objc_sharing_<arch>_<euid>" in
3218 * The returned file should be closed with close_shared_range_file().
3219 **********************************************************************/
3220 static FILE *open_shared_range_file(BOOL create)
3223 #if defined(__ppc__) || defined(ppc)
3225 #elif defined(__ppc64__) || defined(ppc64)
3227 #elif defined(__i386__) || defined(i386)
3230 # error "unknown architecture"
3232 char filename[18 + sizeof(arch) + 1 + 3*sizeof(uid_t) + 1];
3237 // Never share when superuser
3241 _objc_inform("SHARING: superuser never shares");
3246 // Return cached file if it matches and it's not still being used
3247 pthread_mutex_lock(&sharedRangeLock);
3248 if (!sharedRangeFileInUse && euid == sharedRangeEUID) {
3249 file = sharedRangeFile;
3250 sharedRangeFileInUse = YES;
3251 pthread_mutex_unlock(&sharedRangeLock);
3255 pthread_mutex_unlock(&sharedRangeLock);
3257 // Open /tmp/objc_sharing_<euid>
3258 snprintf(filename,sizeof(filename), "/tmp/objc_sharing_%s_%u", arch, euid);
3259 fd = secure_open(filename, O_RDWR | (create ? O_CREAT : 0), euid);
3261 file = fdopen(fd, "r+");
3265 // Cache this file if there's no already-open file cached
3266 pthread_mutex_lock(&sharedRangeLock);
3267 if (!sharedRangeFileInUse) {
3268 sharedRangeFile = file;
3269 sharedRangeEUID = euid;
3270 sharedRangeFileInUse = YES;
3272 pthread_mutex_unlock(&sharedRangeLock);
3275 // open() or fdopen() failed
3277 _objc_inform("SHARING: bad or missing sharing file '%s': %s",
3278 filename, errno ? strerror(errno) :
3279 "potential security violation");
3287 /**********************************************************************
3288 * close_shared_range_file
3289 * Close a file opened with open_shared_range_file.
3290 * The file may actually be kept open and cached for a future
3291 * open_shared_range_file call. If so, clear_shared_range_file_cache()
3292 * can be used to really close the file.
3293 **********************************************************************/
3294 static void close_shared_range_file(FILE *file)
3296 // Flush any writes in case the file is kept open.
3299 pthread_mutex_lock(&sharedRangeLock);
3300 if (file == sharedRangeFile && sharedRangeFileInUse) {
3301 // This file is the cached shared file.
3302 // Leave the file open and cached, but no longer in use.
3303 sharedRangeFileInUse = NO;
3305 // This is not the cached file.
3308 pthread_mutex_unlock(&sharedRangeLock);
3312 /**********************************************************************
3313 * clear_shared_range_file_cache
3314 * Really close any file left open by close_shared_range_file.
3315 * This is called by map_images() after loading multiple images, each
3316 * of which may have used the shared range file.
3317 **********************************************************************/
3318 static void clear_shared_range_file_cache(void)
3320 pthread_mutex_lock(&sharedRangeLock);
3321 if (sharedRangeFile && !sharedRangeFileInUse) {
3322 fclose(sharedRangeFile);
3323 sharedRangeFile = NULL;
3324 sharedRangeEUID = 0;
3325 sharedRangeFileInUse = 0;
3327 pthread_mutex_unlock(&sharedRangeLock);
3331 /**********************************************************************
3333 * Try to find a shared range matching addresses [aligned_start..aligned_end).
3334 * If a range is found, it is mapped into this process and returned.
3335 * If no range is found, or the found range could not be mapped for
3336 * some reason, the range {0, 0} is returned.
3337 * aligned_start and aligned_end must be page-aligned.
3338 **********************************************************************/
3339 static vm_range_t get_shared_range(vm_address_t aligned_start,
3340 vm_address_t aligned_end)
3342 struct remote_range_t remote;
3349 // Open shared range file, but don't create it
3350 file = open_shared_range_file(NO);
3351 if (!file) return result;
3353 // Search for the desired memory range
3354 while (1 == fread(&remote, sizeof(remote), 1, file)) {
3355 if (remote.pid != 0 &&
3356 remote.range.address == aligned_start &&
3357 remote.range.size == aligned_end - aligned_start)
3359 // Found a match in the file - try to grab the memory
3360 mach_port_name_t remote_task;
3361 vm_prot_t cur_prot, max_prot;
3362 vm_address_t local_addr;
3365 // Find the task offering the memory
3366 kr = task_for_pid(mach_task_self(), remote.pid, &remote_task);
3367 if (kr != KERN_SUCCESS) {
3370 _objc_inform("SHARING: no task for pid %d: %s",
3371 remote.pid, mach_error_string(kr));
3376 // Map the memory into our process
3378 kr = vm_remap(mach_task_self(), &local_addr, remote.range.size,
3379 0 /*alignment*/, 1 /*anywhere*/,
3380 remote_task, remote.range.address,
3381 1 /*copy*/, &cur_prot, &max_prot, VM_INHERIT_NONE);
3382 mach_port_deallocate(mach_task_self(), remote_task);
3384 if (kr != KERN_SUCCESS) {
3385 // couldn't map memory
3387 _objc_inform("SHARING: vm_remap from pid %d failed: %s",
3388 remote.pid, mach_error_string(kr));
3393 if (!(cur_prot & VM_PROT_READ) || !(cur_prot & VM_PROT_WRITE)) {
3394 // Received memory is not mapped read/write - don't use it
3395 // fixme try to change permissions? check max_prot?
3397 _objc_inform("SHARING: memory from pid %d not read/write",
3400 vm_deallocate(mach_task_self(), local_addr, remote.range.size);
3405 result.address = local_addr;
3406 result.size = remote.range.size;
3410 close_shared_range_file(file);
3415 /**********************************************************************
3416 * offer_shared_range
3417 * Offer memory range [aligned_start..aligned_end) in this process
3418 * to other Objective-C-using processes.
3419 * If some other entry in the shared range list matches this range,
3420 * is is overwritten with this process's PID. (Thus any stale PIDs are
3422 * If the shared range file could not be updated for any reason, this
3423 * function fails silently.
3424 * aligned_start and aligned_end must be page-aligned.
3425 **********************************************************************/
3426 static void offer_shared_range(vm_address_t aligned_start,
3427 vm_address_t aligned_end)
3429 struct remote_range_t remote;
3430 struct remote_range_t local;
3435 local.range.address = aligned_start;
3436 local.range.size = aligned_end - aligned_start;
3437 local.pid = getpid();
3439 // Open shared range file, creating if necessary
3440 file = open_shared_range_file(YES);
3443 // Find an existing entry for this range, if any
3444 while (1 == fread(&remote, sizeof(remote), 1, file)) {
3445 if (remote.pid != 0 &&
3446 remote.range.address == aligned_start &&
3447 remote.range.size == aligned_end - aligned_start)
3449 // Found a match - overwrite it
3450 err = fseek(file, -sizeof(remote), SEEK_CUR);
3457 // No existing entry - write at the end of the file
3458 err = fseek(file, 0, SEEK_END);
3462 fwrite(&local, sizeof(local), 1, file);
3465 close_shared_range_file(file);
3469 /**********************************************************************
3470 * install_shared_range
3471 * Install a shared range received from get_shared_range() into
3472 * its final resting place.
3473 * If possible, the memory is copied using virtual memory magic rather
3474 * than actual data writes. dst always gets updated values, even if
3475 * virtual memory magic is not possible.
3476 * The shared range is always deallocated.
3477 * src and dst must be page-aligned.
3478 **********************************************************************/
3479 static void install_shared_range(vm_range_t src, vm_address_t dst)
3483 // Copy from src to dst
3484 kr = vm_copy(mach_task_self(), src.address, src.size, dst);
3485 if (kr != KERN_SUCCESS) {
3486 // VM copy failed. Use non-VM copy.
3488 _objc_inform("SHARING: vm_copy failed: %s", mach_error_string(kr));
3490 memmove((void *)dst, (void *)src.address, src.size);
3493 // Unmap the shared range at src
3494 vm_deallocate(mach_task_self(), src.address, src.size);