2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /***********************************************************************
26 * Copyright 1988-1996, NeXT Software, Inc.
29 **********************************************************************/
31 /***********************************************************************
33 **********************************************************************/
36 #include <mach-o/ldsyms.h>
37 #include <mach-o/dyld.h>
38 #include <mach/vm_statistics.h>
40 // project headers first, otherwise we get the installed ones
41 #import "objc-class.h"
42 #import <objc/objc-runtime.h>
43 #import <objc/hashtable2.h>
45 #import "objc-private.h"
46 #import <objc/Object.h>
47 #import <objc/Protocol.h>
50 #include <sys/resource.h>
52 OBJC_EXPORT Class _objc_getNonexistentClass(void);
55 OBJC_EXPORT Class getOriginalClassForPosingClass(Class);
58 /***********************************************************************
59 * Constants and macros internal to this module.
60 **********************************************************************/
62 /* Turn on support for literal string objects. */
63 #define LITERAL_STRING_OBJECTS
65 /***********************************************************************
66 * Types internal to this module.
67 **********************************************************************/
69 typedef struct _objc_unresolved_category
71 struct _objc_unresolved_category * next;
72 struct objc_category * cat;
75 } _objc_unresolved_category;
77 typedef struct _PendingClass
79 struct objc_class * * ref;
80 struct objc_class * classToSetUp;
81 const char * nameof_superclass;
83 struct _PendingClass * next;
86 /***********************************************************************
88 **********************************************************************/
90 // Function to call when message sent to nil object.
91 void (*_objc_msgNil)(id, SEL) = NULL;
93 // Function called after class has been fixed up (MACH only)
94 void (*callbackFunction)(Class, const char *) = 0;
96 // Prototype for function passed to
97 typedef void (*NilObjectMsgCallback) (id nilObject, SEL selector);
99 // Lock for class hashtable
100 OBJC_DECLARE_LOCK (classLock);
102 // Condition for logging load progress
103 static int LaunchingDebug = -1;
105 // objc's key for pthread_getspecific
106 pthread_key_t _objc_pthread_key;
108 /***********************************************************************
109 * Function prototypes internal to this module.
110 **********************************************************************/
112 static unsigned classHash (void * info, struct objc_class * data);
113 static int classIsEqual (void * info, struct objc_class * name, struct objc_class * cls);
114 static int _objc_defaultClassHandler (const char * clsName);
115 static void _objcTweakMethodListPointerForClass (struct objc_class * cls);
116 static void _objc_add_category_flush_caches(struct objc_class * cls, struct objc_category * category, int version);
117 static void _objc_add_category(struct objc_class * cls, struct objc_category * category, int version);
118 static void _objc_register_category (struct objc_category * cat, long version, int bindme);
119 static void _objc_add_categories_from_image (header_info * hi);
120 static const header_info * _headerForClass (struct objc_class * cls);
121 static PendingClass * newPending (void);
122 static NXMapTable * pendingClassRefsMapTable (void);
123 static void _objc_add_classes_from_image (NXHashTable * clsHash, header_info * hi);
124 static void _objc_fixup_string_objects_for_image(header_info * hi);
125 static void _objc_map_class_refs_for_image (header_info * hi);
126 static void map_selrefs (SEL * sels, unsigned int cnt);
127 static void map_method_descs (struct objc_method_description_list * methods);
128 static void _objc_fixup_protocol_objects_for_image (header_info * hi);
129 static void _objc_bindModuleContainingCategory(Category cat);
130 static void _objc_fixup_selector_refs (const header_info * hi);
131 static void _objc_call_loads_for_image (header_info * header);
132 static void _objc_checkForPendingClassReferences (struct objc_class * cls);
133 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide);
134 static void _objc_unmap_image(headerType *mh, unsigned long vmaddr_slide);
136 /***********************************************************************
137 * Static data internal to this module.
138 **********************************************************************/
140 // we keep a linked list of header_info's describing each image as told to us by dyld
141 static header_info * FirstHeader = 0;
143 // Hash table of classes
144 static NXHashTable * class_hash = 0;
145 static NXHashTablePrototype classHashPrototype =
147 (unsigned (*) (const void *, const void *)) classHash,
148 (int (*)(const void *, const void *, const void *)) classIsEqual,
152 // Exported copy of class_hash variable (hook for debugging tools)
153 NXHashTable *_objc_debug_class_hash = NULL;
155 // Function pointer objc_getClass calls through when class is not found
156 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
158 // Category and class registries
159 static NXMapTable * category_hash = NULL;
162 static int Postpone_install_relationships = 0;
164 static NXMapTable * pendingClassRefsMap = 0;
166 /***********************************************************************
167 * objc_dump_class_hash. Log names of all known classes.
168 **********************************************************************/
169 void objc_dump_class_hash (void)
173 struct objc_class * data;
178 state = NXInitHashState (table);
179 while (NXNextHashState (table, &state, (void **) &data))
180 printf ("class %d: %s\n", ++count, data->name);
183 /***********************************************************************
185 **********************************************************************/
186 static unsigned classHash (void * info,
187 struct objc_class * data)
189 // Nil classes hash to zero
193 // Call through to real hash function
194 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
197 /***********************************************************************
198 * classIsEqual. Returns whether the class names match. If we ever
199 * check more than the name, routines like objc_lookUpClass have to
201 **********************************************************************/
202 static int classIsEqual (void * info,
203 struct objc_class * name,
204 struct objc_class * cls)
206 // Standard string comparison
207 return ((name->name[0] == cls->name[0]) &&
208 (strcmp (name->name, cls->name) == 0));
211 /***********************************************************************
212 * _objc_init_class_hash. Return the class lookup table, create it if
214 **********************************************************************/
215 void _objc_init_class_hash (void)
217 // Do nothing if class hash table already exists
221 // Provide a generous initial capacity to cut down on rehashes
222 // at launch time. A smallish Foundation+AppKit program will have
223 // about 520 classes. Larger apps (like IB or WOB) have more like
224 // 800 classes. Some customers have massive quantities of classes.
225 // Foundation-only programs aren't likely to notice the ~6K loss.
226 class_hash = NXCreateHashTableFromZone (classHashPrototype,
229 _objc_create_zone ());
230 _objc_debug_class_hash = class_hash;
233 /***********************************************************************
234 * objc_getClassList. Return the known classes.
235 **********************************************************************/
236 int objc_getClassList(Class *buffer, int bufferLen) {
238 struct objc_class * class;
241 OBJC_LOCK(&classLock);
242 num = NXCountHashTable(class_hash);
243 if (NULL == buffer) {
244 OBJC_UNLOCK(&classLock);
248 state = NXInitHashState(class_hash);
249 while (cnt < num && NXNextHashState(class_hash, &state, (void **)&class)) {
250 buffer[cnt++] = class;
252 OBJC_UNLOCK(&classLock);
256 /***********************************************************************
257 * objc_getClasses. Return class lookup table.
259 * NOTE: This function is very dangerous, since you cannot safely use
260 * the hashtable without locking it, and the lock is private!
261 **********************************************************************/
262 void * objc_getClasses (void)
264 // Return the class lookup hash table
268 /***********************************************************************
269 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
270 **********************************************************************/
271 static int _objc_defaultClassHandler (const char * clsName)
273 // Return zero so objc_getClass doesn't bother re-searching
277 /***********************************************************************
278 * objc_setClassHandler. Set objc_classHandler to the specified value.
280 * NOTE: This should probably deal with userSuppliedHandler being NULL,
281 * because the objc_classHandler caller does not check... it would bus
282 * error. It would make sense to handle NULL by restoring the default
283 * handler. Is anyone hacking with this, though?
284 **********************************************************************/
285 void objc_setClassHandler (int (*userSuppliedHandler) (const char *))
287 objc_classHandler = userSuppliedHandler;
290 /***********************************************************************
291 * objc_getClass. Return the id of the named class. If the class does
292 * not exist, call the objc_classHandler routine with the class name.
293 * If the objc_classHandler returns a non-zero value, try once more to
294 * find the class. Default objc_classHandler always returns zero.
295 * objc_setClassHandler is how someone can install a non-default routine.
296 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
297 **********************************************************************/
298 id objc_getClass (const char * aClassName)
300 struct objc_class cls;
303 // Synchronize access to hash table
304 OBJC_LOCK (&classLock);
306 // Check the hash table
307 cls.name = aClassName;
308 ret = (id) NXHashGet (class_hash, &cls);
309 OBJC_UNLOCK (&classLock);
311 // If not found, go call objc_classHandler and try again
312 if (!ret && (*objc_classHandler)(aClassName))
314 OBJC_LOCK (&classLock);
315 ret = (id) NXHashGet (class_hash, &cls);
316 OBJC_UNLOCK (&classLock);
322 /***********************************************************************
323 * objc_lookUpClass. Return the id of the named class.
325 * Formerly objc_getClassWithoutWarning ()
326 **********************************************************************/
327 id objc_lookUpClass (const char * aClassName)
329 struct objc_class cls;
332 // Synchronize access to hash table
333 OBJC_LOCK (&classLock);
335 // Check the hash table
336 cls.name = aClassName;
337 ret = (id) NXHashGet (class_hash, &cls);
340 OBJC_UNLOCK (&classLock);
344 /***********************************************************************
345 * objc_getMetaClass. Return the id of the meta class the named class.
346 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
347 **********************************************************************/
348 id objc_getMetaClass (const char * aClassName)
350 struct objc_class * cls;
352 cls = objc_getClass (aClassName);
355 _objc_inform ("class `%s' not linked into application", aClassName);
362 /***********************************************************************
363 * objc_addClass. Add the specified class to the table of known classes,
364 * after doing a little verification and fixup.
365 **********************************************************************/
366 void objc_addClass (Class cls)
368 // Synchronize access to hash table
369 OBJC_LOCK (&classLock);
371 // Make sure both the class and the metaclass have caches!
372 // Clear all bits of the info fields except CLS_CLASS and CLS_META.
373 // Normally these bits are already clear but if someone tries to cons
374 // up their own class on the fly they might need to be cleared.
375 if (((struct objc_class *)cls)->cache == NULL)
377 ((struct objc_class *)cls)->cache = (Cache) &emptyCache;
378 ((struct objc_class *)cls)->info = CLS_CLASS;
381 if (((struct objc_class *)cls)->isa->cache == NULL)
383 ((struct objc_class *)cls)->isa->cache = (Cache) &emptyCache;
384 ((struct objc_class *)cls)->isa->info = CLS_META;
387 // Add the class to the table
388 (void) NXHashInsert (class_hash, cls);
391 OBJC_UNLOCK (&classLock);
394 /***********************************************************************
395 * _objcTweakMethodListPointerForClass.
396 **********************************************************************/
397 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
399 struct objc_method_list * originalList;
400 const int initialEntries = 4;
402 struct objc_method_list ** ptr;
404 // Remember existing list
405 originalList = (struct objc_method_list *) cls->methodLists;
407 // Allocate and zero a method list array
408 mallocSize = sizeof(struct objc_method_list *) * initialEntries;
409 ptr = (struct objc_method_list **) malloc_zone_calloc (_objc_create_zone (), 1, mallocSize);
411 // Insert the existing list into the array
412 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
413 ptr[0] = originalList;
415 // Replace existing list with array
416 ((struct objc_class *)cls)->methodLists = ptr;
417 ((struct objc_class *)cls)->info |= CLS_METHOD_ARRAY;
419 // Do the same thing to the meta-class
420 if (((((struct objc_class *)cls)->info & CLS_CLASS) != 0) && cls->isa)
421 _objcTweakMethodListPointerForClass (cls->isa);
424 /***********************************************************************
425 * _objc_insertMethods.
426 **********************************************************************/
427 void _objc_insertMethods (struct objc_method_list * mlist,
428 struct objc_method_list *** list)
430 struct objc_method_list ** ptr;
431 volatile struct objc_method_list ** tempList;
436 // Locate unused entry for insertion point
438 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
441 // If array is full, double it
442 if (*ptr == END_OF_METHODS_LIST)
444 // Calculate old and new dimensions
445 endIndex = ptr - *list;
446 oldSize = (endIndex + 1) * sizeof(void *);
447 newSize = oldSize + sizeof(struct objc_method_list *); // only increase by 1
449 // Replace existing array with copy twice its size
450 tempList = (struct objc_method_list **) malloc_zone_realloc ((void *) _objc_create_zone (),
455 // Zero out addition part of new array
456 bzero (&((*list)[endIndex]), newSize - oldSize);
458 // Place new end marker
459 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
461 // Insertion point corresponds to old array end
462 ptr = &((*list)[endIndex]);
465 // Right shift existing entries by one
466 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
468 // Insert at method list at beginning of array
472 /***********************************************************************
473 * _objc_removeMethods.
474 **********************************************************************/
475 void _objc_removeMethods (struct objc_method_list * mlist,
476 struct objc_method_list *** list)
478 struct objc_method_list ** ptr;
480 // Locate list in the array
482 while (*ptr != mlist) {
483 // fix for radar # 2538790
484 if ( *ptr == END_OF_METHODS_LIST ) return;
491 // Left shift the following entries
492 while (*(++ptr) != END_OF_METHODS_LIST)
497 /***********************************************************************
498 * _objc_add_category. Install the specified category's methods and
499 * protocols into the class it augments.
500 **********************************************************************/
501 static inline void _objc_add_category(struct objc_class *cls, struct objc_category *category, int version)
503 // Augment instance methods
504 if (category->instance_methods)
505 _objc_insertMethods (category->instance_methods, &cls->methodLists);
507 // Augment class methods
508 if (category->class_methods)
509 _objc_insertMethods (category->class_methods, &cls->isa->methodLists);
512 if ((version >= 5) && category->protocols)
514 if (cls->isa->version >= 5)
516 category->protocols->next = cls->protocols;
517 cls->protocols = category->protocols;
518 cls->isa->protocols = category->protocols;
522 _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
523 _objc_inform ("class `%s' must be recompiled\n", category->class_name);
528 /***********************************************************************
529 * _objc_add_category_flush_caches. Install the specified category's methods into
530 * the class it augments, and flush the class' method cache.
532 **********************************************************************/
533 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
535 // Install the category's methods into its intended class
536 _objc_add_category (cls, category, version);
538 // Flush caches so category's methods can get called
539 _objc_flush_caches (cls);
542 /***********************************************************************
543 * _objc_resolve_categories_for_class. Install all categories intended
544 * for the specified class, in reverse order from the order in which we
545 * found the categories in the image.
546 * This is done as lazily as we can.
547 **********************************************************************/
548 void _objc_resolve_categories_for_class (struct objc_class * cls)
550 _objc_unresolved_category * cat;
551 _objc_unresolved_category * next;
553 // Nothing to do if there are no categories at all
557 // Locate and remove first element in category list
558 // associated with this class
559 cat = NXMapRemove (category_hash, cls->name);
561 // Traverse the list of categories, if any, registered for this class
565 _objc_bindModuleContainingCategory(cat->cat);
567 // Install the category
568 // use the non-flush-cache version since we are only
569 // called from the class intialization code
570 _objc_add_category (cls, cat->cat, cat->version);
572 // Delink and reclaim this registration
579 /***********************************************************************
580 * _objc_register_category. Add the specified category to the registry
581 * of categories to be installed later (once we know for sure which
582 * classes we have). If there are multiple categories on a given class,
583 * they will be processed in reverse order from the order in which they
584 * were found in the image.
585 **********************************************************************/
586 static void _objc_register_category (struct objc_category * cat,
590 _objc_unresolved_category * new_cat;
591 _objc_unresolved_category * old;
592 struct objc_class *theClass;
595 // If the category's class exists, just add the category
596 // We could check to see if its initted, and if not, defer this
597 // work until _objc_resolve_categories_for_class for all cases
598 // The only trick then is whether we need to bind it. This
599 // might be doable if we store an obscured pointer so that we
600 // avoid touching the memory... [BG 5/2001 still in think mode]
601 if (theClass = objc_lookUpClass (cat->class_name))
604 _objc_bindModuleContainingCategory(cat);
606 _objc_add_category_flush_caches (theClass, cat, version);
610 // Create category lookup table if needed
612 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
614 _objc_create_zone ());
616 // Locate an existing category, if any, for the class. This is linked
617 // after the new entry, so list is LIFO.
618 old = NXMapGet (category_hash, cat->class_name);
620 // Register the category to be fixed up later
621 new_cat = malloc_zone_malloc (_objc_create_zone (),
622 sizeof(_objc_unresolved_category));
625 new_cat->version = version;
626 new_cat->bindme = bindme; // could use a bit in the next pointer instead of a whole word
627 (void) NXMapInsert (category_hash, cat->class_name , new_cat);
630 /***********************************************************************
631 * _objc_add_categories_from_image.
632 **********************************************************************/
633 static void _objc_add_categories_from_image (header_info * hi)
637 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
639 // Major loop - process all modules in the header
640 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
642 trace(0xb120, hi->mod_count, 0, 0);
644 for (midx = 0; midx < hi->mod_count; midx += 1)
649 // Nothing to do for a module without a symbol table
650 if (mods[midx].symtab == NULL)
653 // Total entries in symbol table (class entries followed
654 // by category entries)
655 total = mods[midx].symtab->cls_def_cnt +
656 mods[midx].symtab->cat_def_cnt;
659 trace(0xb123, midx, mods[midx].symtab->cat_def_cnt, 0);
661 // Minor loop - register all categories from given module
662 for (index = mods[midx].symtab->cls_def_cnt; index < total; index += 1)
664 _objc_register_category(mods[midx].symtab->defs[index], mods[midx].version, isDynamic);
667 trace(0xb124, midx, 0, 0);
670 trace(0xb12f, 0, 0, 0);
673 /***********************************************************************
675 **********************************************************************/
676 static const header_info * _headerForClass (struct objc_class * cls)
678 const struct segment_command * objcSeg;
680 unsigned long vmaddrPlus;
683 // Check all headers in the vector
684 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
686 // Locate header data, if any
687 objcSeg = _getObjcHeaderData ((headerType *) hInfo->mhdr, &size);
691 // Is the class in this header?
692 vmaddrPlus = (unsigned long) objcSeg->vmaddr + hInfo->image_slide;
693 if ((vmaddrPlus <= (unsigned long) cls) &&
694 ((unsigned long) cls < (vmaddrPlus + size)))
702 /***********************************************************************
704 **********************************************************************/
705 const char * _nameForHeader (const headerType * header)
707 return _getObjcHeaderName ((headerType *) header);
710 /***********************************************************************
711 * checkForPendingClassReferences. Complete any fixups registered for
713 **********************************************************************/
714 static void _objc_checkForPendingClassReferences (struct objc_class * cls)
716 PendingClass * pending;
718 // Nothing to do if there are no pending classes
719 if (!pendingClassRefsMap)
722 // Get pending list for this class
723 pending = NXMapGet (pendingClassRefsMap, cls->name);
727 // Remove the list from the table
728 (void) NXMapRemove (pendingClassRefsMap, cls->name);
730 // Process all elements in the list
735 // Remember follower for loop
736 next = pending->next;
738 // Fill in a pointer to Class
739 // (satisfies caller of objc_pendClassReference)
741 *pending->ref = objc_getClass (cls->name);
743 // Fill in super, isa, cache, and version for the class
744 // and its meta-class
745 // (satisfies caller of objc_pendClassInstallation)
746 // NOTE: There must be no more than one of these for
747 // any given classToSetUp
748 if (pending->classToSetUp)
750 struct objc_class * fixCls;
752 // Locate the Class to be fixed up
753 fixCls = pending->classToSetUp;
755 // Set up super class fields with names to be replaced by pointers
756 fixCls->super_class = (struct objc_class *) pending->nameof_superclass;
757 fixCls->isa->super_class = (struct objc_class *) pending->nameof_superclass;
759 // Fix up class pointers, version, and cache pointers
760 _class_install_relationships (fixCls, pending->version);
763 // Reclaim the element
771 /***********************************************************************
772 * newPending. Allocate and zero a PendingClass structure.
773 **********************************************************************/
774 static inline PendingClass * newPending (void)
776 PendingClass * pending;
778 pending = (PendingClass *) malloc_zone_calloc (_objc_create_zone (), 1, sizeof(PendingClass));
783 /***********************************************************************
784 * pendingClassRefsMapTable. Return a pointer to the lookup table for
786 **********************************************************************/
787 static inline NXMapTable * pendingClassRefsMapTable (void)
789 // Allocate table if needed
790 if (!pendingClassRefsMap)
791 pendingClassRefsMap = NXCreateMapTableFromZone (NXStrValueMapPrototype, 10, _objc_create_zone ());
793 // Return table pointer
794 return pendingClassRefsMap;
797 /***********************************************************************
798 * objc_pendClassReference. Register the specified class pointer (ref)
799 * to be filled in later with a pointer to the class having the specified
801 **********************************************************************/
802 void objc_pendClassReference (const char * className,
803 struct objc_class * * ref)
806 PendingClass * pending;
808 // Create and/or locate pending class lookup table
809 table = pendingClassRefsMapTable ();
811 // Create entry containing the class reference
812 pending = newPending ();
815 // Link new entry into head of list of entries for this class
816 pending->next = NXMapGet (pendingClassRefsMap, className);
818 // (Re)place entry list in the table
819 (void) NXMapInsert (table, className, pending);
822 /***********************************************************************
823 * objc_pendClassInstallation. Register the specified class to have its
824 * super class pointers filled in later because the superclass is not
826 **********************************************************************/
827 void objc_pendClassInstallation (struct objc_class *cls, int version)
830 PendingClass * pending;
832 // Create and/or locate pending class lookup table
833 table = pendingClassRefsMapTable ();
835 // Create entry referring to this class
836 pending = newPending ();
837 pending->classToSetUp = cls;
838 pending->nameof_superclass = (const char *) cls->super_class;
839 pending->version = version;
841 // Link new entry into head of list of entries for this class
842 pending->next = NXMapGet (pendingClassRefsMap, cls->super_class);
844 // (Re)place entry list in the table
845 (void) NXMapInsert (table, cls->super_class, pending);
848 /***********************************************************************
849 * _objc_add_classes_from_image. Install all classes contained in the
851 **********************************************************************/
852 static void _objc_add_classes_from_image(NXHashTable *clsHash, header_info *hi)
857 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
859 // Major loop - process all modules in the image
860 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
861 for (midx = 0; midx < hi->mod_count; midx += 1)
863 // Skip module containing no classes
864 if (mods[midx].symtab == NULL)
867 // Minor loop - process all the classes in given module
868 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
870 struct objc_class * oldCls;
871 struct objc_class * newCls;
873 // Locate the class description pointer
874 newCls = mods[midx].symtab->defs[index];
876 // remember to bind the module on initialization
878 newCls->info |= CLS_NEED_BIND ;
880 // Convert old style method list to the new style
881 _objcTweakMethodListPointerForClass (newCls);
883 oldCls = NXHashInsert (clsHash, newCls);
885 // Non-Nil oldCls is a class that NXHashInsert just
886 // bumped from table because it has the same name
890 const header_info * oldHeader;
891 const header_info * newHeader;
892 const char * oldName;
893 const char * newName;
895 // Log the duplication
896 oldHeader = _headerForClass (oldCls);
897 newHeader = _headerForClass (newCls);
898 oldName = _nameForHeader (oldHeader->mhdr);
899 newName = _nameForHeader (newHeader->mhdr);
900 _objc_inform ("Both %s and %s have implementations of class %s.",
901 oldName, newName, oldCls->name);
902 _objc_inform ("Using implementation from %s.", newName);
904 // Use the chosen class
905 // NOTE: Isn't this a NOP?
906 newCls = objc_lookUpClass (oldCls->name);
909 // Unless newCls was a duplicate, and we chose the
910 // existing one instead, set the version in the meta-class
911 if (newCls != oldCls)
912 newCls->isa->version = mods[midx].version;
914 // Install new categories intended for this class
915 // NOTE: But, if we displaced an existing "isEqual"
916 // class, the categories have already been installed
917 // on an old class and are gone from the registry!!
919 // we defer this work until the class is initialized.
920 //_objc_resolve_categories_for_class (newCls);
922 // Resolve (a) pointers to the named class, and/or
923 // (b) the super_class, cache, and version
924 // fields of newCls and its meta-class
925 // NOTE: But, if we displaced an existing "isEqual"
926 // class, this has already been done... with an
927 // old-now-"unused" class!!
928 _objc_checkForPendingClassReferences (newCls);
934 /***********************************************************************
935 * _objc_fixup_string_objects_for_image. Initialize the isa pointers
936 * of all NSConstantString objects.
937 **********************************************************************/
938 static void _objc_fixup_string_objects_for_image (header_info * hi)
941 OBJC_CONSTANT_STRING_PTR section;
942 struct objc_class * constantStringClass;
945 // Locate section holding string objects
946 section = _getObjcStringObjects ((headerType *) hi->mhdr, &size);
947 if (!section || !size)
949 section = (OBJC_CONSTANT_STRING_PTR) ((unsigned long) section + hi->image_slide);
951 // Luckily NXConstantString is the same size as NSConstantString
952 constantStringClass = objc_getClass ("NSConstantString");
954 // Process each string object in the section
955 for (index = 0; index < size; index += 1)
957 struct objc_class * * isaptr;
959 isaptr = (struct objc_class * *) OBJC_CONSTANT_STRING_DEREF section[index];
961 *isaptr = constantStringClass;
965 /***********************************************************************
966 * _objc_map_class_refs_for_image. Convert the class ref entries from
967 * a class name string pointer to a class pointer. If the class does
968 * not yet exist, the reference is added to a list of pending references
969 * to be fixed up at a later date.
970 **********************************************************************/
971 static void _objc_map_class_refs_for_image (header_info * hi)
973 struct objc_class * * cls_refs;
977 // Locate class refs in image
978 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
981 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
983 // Process each class ref
984 for (index = 0; index < size; index += 1)
987 struct objc_class * cls;
989 // Get ref to convert from name string to class pointer
990 ref = (const char *) cls_refs[index];
992 // Get pointer to class of this name
993 cls = (struct objc_class *)objc_lookUpClass (ref);
995 // If class isn't there yet, use pending mechanism
998 // Register this ref to be set later
999 objc_pendClassReference (ref, &cls_refs[index]);
1001 // Use place-holder class
1002 cls_refs[index] = _objc_getNonexistentClass ();
1005 // Replace name string pointer with class pointer
1007 cls_refs[index] = cls;
1011 /***********************************************************************
1012 * map_selrefs. Register each selector in the specified array. If a
1013 * given selector is already registered, update this array to point to
1014 * the registered selector string.
1015 **********************************************************************/
1016 static inline void map_selrefs(SEL *sels, unsigned int cnt)
1020 // Process each selector
1021 for (index = 0; index < cnt; index += 1)
1025 // Lookup pointer to uniqued string
1026 sel = sel_registerNameNoCopy ((const char *) sels[index]);
1028 // Replace this selector with uniqued one (avoid
1029 // modifying the VM page if this would be a NOP)
1030 if (sels[index] != sel)
1036 /***********************************************************************
1037 * map_method_descs. For each method in the specified method list,
1038 * replace the name pointer with a uniqued selector.
1039 **********************************************************************/
1040 static void map_method_descs (struct objc_method_description_list * methods)
1044 // Process each method
1045 for (index = 0; index < methods->count; index += 1)
1047 struct objc_method_description * method;
1050 // Get method entry to fix up
1051 method = &methods->list[index];
1053 // Lookup pointer to uniqued string
1054 sel = sel_registerNameNoCopy ((const char *) method->name);
1056 // Replace this selector with uniqued one (avoid
1057 // modifying the VM page if this would be a NOP)
1058 if (method->name != sel)
1063 /***********************************************************************
1065 **********************************************************************/
1066 @interface Protocol(RuntimePrivate)
1067 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
1070 /***********************************************************************
1071 * _objc_fixup_protocol_objects_for_image. For each protocol in the
1072 * specified image, selectorize the method names and call +_fixup.
1073 **********************************************************************/
1074 static void _objc_fixup_protocol_objects_for_image (header_info * hi)
1077 OBJC_PROTOCOL_PTR protos;
1080 // Locate protocols in the image
1081 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
1085 // Apply the slide bias
1086 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
1088 // Process each protocol
1089 for (index = 0; index < size; index += 1)
1091 // Selectorize the instance methods
1092 if (protos[index] OBJC_PROTOCOL_DEREF instance_methods)
1093 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF instance_methods);
1095 // Selectorize the class methods
1096 if (protos[index] OBJC_PROTOCOL_DEREF class_methods)
1097 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF class_methods);
1100 // Invoke Protocol class method to fix up the protocol
1101 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
1104 /***********************************************************************
1105 * _objc_headerStart. Return what headers we know about.
1106 **********************************************************************/
1107 header_info * _objc_headerStart ()
1110 // Take advatage of our previous work
1114 void _objc_bindModuleContainingList() {
1115 /* We define this for backwards binary compat with things which should not
1116 * have been using it (cough OmniWeb), but now it does nothing for them.
1120 /**********************************************************************
1121 * _objc_bind_symbol. Bind the module containing the symbol. Use 2-level namespace API
1122 * Only look in images that we know to have ObjC symbols (e.g. 9 for Mail 7/2001)
1124 ***********************************************************************/
1125 static void _objc_bind_symbol(const char *name)
1127 static header_info *lastHeader = NULL;
1129 const headerType *imageHeader = lastHeader ? lastHeader->mhdr : NULL;
1131 // Ideally we would have a way to not even process a symbol in a module
1132 // we've already visited
1135 // First assume there is some locality and search where we last found a symbol
1137 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1138 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1144 // Symbol wasn't found in the image we last searched
1145 // Search in all the images known to contain ObjcC
1146 for ( hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1148 imageHeader = hInfo->mhdr;
1149 if ( hInfo != lastHeader
1150 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1151 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1158 // die now, or later ??
1159 // _objc_fatal("could not find %s", name);
1162 /***********************************************************************
1163 * _objc_bindModuleContainingCategory. Bind the module containing the
1165 **********************************************************************/
1166 static void _objc_bindModuleContainingCategory (Category cat)
1169 char * category_name;
1172 unsigned int name_len;
1174 // Bind ".objc_category_name_<classname>_<categoryname>",
1175 // where <classname> is the class name with the leading
1177 class_name = cat->class_name;
1178 category_name = cat->category_name;
1179 name_len = strlen(class_name) + strlen(category_name) + 30;
1180 if ( name_len > 128 )
1181 name = malloc(name_len);
1184 while (*class_name == '%')
1186 strcpy (name, ".objc_category_name_");
1187 strcat (name, class_name);
1189 strcat (name, category_name);
1190 if (LaunchingDebug) { _objc_syslog("_objc_bindModuleContainingCategory for %s on %s", category_name, class_name); }
1191 _objc_bind_symbol(name);
1192 if ( name != tmp_buf )
1196 /***********************************************************************
1197 * _objc_bindModuleContainingClass. Bind the module containing the
1199 * This is done lazily, just after initializing the class (if needed)
1200 **********************************************************************/
1202 void _objc_bindModuleContainingClass (struct objc_class * cls) {
1204 const char * class_name;
1206 unsigned int name_len;
1208 // Use the real class behind the poser
1209 if (CLS_GETINFO (cls, CLS_POSING))
1210 cls = getOriginalClassForPosingClass (cls);
1211 class_name = cls->name;
1213 name_len = strlen(class_name) + 20;
1214 if ( name_len > 128 )
1215 name = malloc(name_len);
1219 while (*class_name == '%')
1221 strcpy (name, ".objc_class_name_");
1222 strcat (name, class_name);
1223 if (LaunchingDebug) { _objc_syslog("_objc_bindModuleContainingClass for %s", class_name); }
1224 _objc_bind_symbol(name);
1225 if ( name != tmp_buf )
1230 /***********************************************************************
1231 * _objc_bindClassIfNeeded.
1232 * If the given class is still marked as needs-bind, bind the module
1234 * Called during _objc_call_loads_for_image just before sending +load,
1235 * and during class_initialize just before sending +initialize.
1236 **********************************************************************/
1237 void _objc_bindClassIfNeeded(struct objc_class *cls)
1239 // Clear NEED_BIND *after* binding to prevent race
1240 // This assumes that simultaneous binding of one module by two threads is ok.
1241 if (cls->info & CLS_NEED_BIND) {
1242 _objc_bindModuleContainingClass(cls);
1243 cls->info &= ~CLS_NEED_BIND;
1248 /***********************************************************************
1251 **********************************************************************/
1253 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
1254 #define HINFO_SIZE 16
1256 static int HeaderInfoCounter = 0;
1257 static header_info HeaderInfoTable[HINFO_SIZE] = { {0} };
1259 static header_info * _objc_addHeader(const headerType *header, unsigned long vmaddr_slide)
1262 Module mod_ptr = _getObjcModules ((headerType *) header, &mod_count);
1263 header_info *result;
1265 // if there is no objc data - ignore this entry!
1266 if (mod_ptr == NULL) {
1270 if (HeaderInfoCounter < HINFO_SIZE) {
1271 // avoid mallocs for the common case
1272 result = &HeaderInfoTable[HeaderInfoCounter++];
1275 result = malloc_zone_malloc(_objc_create_zone(), sizeof(header_info));
1278 // Set up the new vector entry
1279 result->mhdr = header;
1280 result->mod_ptr = mod_ptr;
1281 result->mod_count = mod_count;
1282 result->image_slide = vmaddr_slide;
1285 // (a simple lock here would go a long way towards thread safety)
1286 result->next = FirstHeader;
1287 FirstHeader = result;
1292 /**********************************************************************
1295 * If we have it we're in trouble
1296 **************************************************************************/
1297 static void _objc_fatalHeader(const headerType *header)
1301 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next) {
1302 if (hInfo->mhdr == header) {
1303 _objc_fatal("cannot unmap an image containing ObjC data");
1308 /***********************************************************************
1309 * _objc_fixup_selector_refs. Register all of the selectors in each
1310 * image, and fix them all up.
1312 **********************************************************************/
1313 static void _objc_fixup_selector_refs (const header_info * hi)
1317 SEL * messages_refs;
1319 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
1321 // Fix up message refs
1322 messages_refs = (SEL *) _getObjcMessageRefs ((headerType *) hi->mhdr, &size);
1325 messages_refs = (SEL *) ((unsigned long) messages_refs + hi->image_slide);
1326 map_selrefs (messages_refs, size);
1331 /***********************************************************************
1332 * _objc_call_loads_for_image.
1333 **********************************************************************/
1334 static void _objc_call_loads_for_image (header_info * header)
1336 struct objc_class * cls;
1337 struct objc_class * * pClass;
1338 Category * pCategory;
1340 unsigned int nModules;
1341 unsigned int nClasses;
1342 unsigned int nCategories;
1343 struct objc_symtab * symtab;
1344 struct objc_module * module;
1346 // Major loop - process all modules named in header
1347 module = (struct objc_module *) ((unsigned long) header->mod_ptr + header->image_slide);
1348 for (nModules = header->mod_count; nModules; nModules -= 1, module += 1)
1350 symtab = module->symtab;
1354 // Minor loop - call the +load from each class in the given module
1355 for (nClasses = symtab->cls_def_cnt, pClass = (Class *) symtab->defs;
1357 nClasses -= 1, pClass += 1)
1359 struct objc_method_list **mlistp;
1360 cls = (struct objc_class *)*pClass;
1361 mlistp = get_base_method_list(cls->isa);
1362 if (cls->isa->methodLists && mlistp)
1364 // Look up the method manually (vs messaging the class) to bypass
1365 // +initialize and cache fill on class that is not even loaded yet
1366 load_method = class_lookupNamedMethodInMethodList (*mlistp, "load");
1368 _objc_bindClassIfNeeded(cls);
1369 (*load_method) ((id) cls, @selector(load));
1374 // Minor loop - call the +load from augmented class of
1375 // each category in the given module
1376 for (nCategories = symtab->cat_def_cnt,
1377 pCategory = (Category *) &symtab->defs[symtab->cls_def_cnt];
1379 nCategories -= 1, pCategory += 1)
1381 struct objc_method_list * methods;
1383 methods = (*pCategory)->class_methods;
1386 load_method = class_lookupNamedMethodInMethodList (methods, "load");
1388 // Strictly speaking we shouldn't need (and don't want) to get the class here
1389 // The side effect we're looking for is to load it if needed.
1390 // Since category +loads are rare we could spend some cycles finding out
1391 // if we have a "bindme" TBD and do it here, saving a class load.
1392 // But chances are the +load will cause class initialization anyway
1393 cls = objc_getClass ((*pCategory)->class_name);
1394 // the class & all categories are now bound in
1395 (*load_method) ((id) cls, @selector(load));
1402 /***********************************************************************
1403 * runtime configuration
1404 **********************************************************************/
1405 static void objc_setConfiguration() {
1406 if ( LaunchingDebug == -1 ) {
1407 // watch image loading and binding
1408 LaunchingDebug = getenv("LaunchingDebug") != NULL;
1411 /***********************************************************************
1412 * objc_setMultithreaded.
1413 **********************************************************************/
1414 void objc_setMultithreaded (BOOL flag)
1416 // Nothing here. Thread synchronization in the runtime is always active.
1421 /***********************************************************************
1422 * _objc_pthread_destroyspecific
1423 * Destructor for objc's per-thread data.
1424 * arg shouldn't be NULL, but we check anyway.
1425 **********************************************************************/
1426 extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
1427 void _objc_pthread_destroyspecific(void *arg)
1429 _objc_pthread_data *data = (_objc_pthread_data *)arg;
1431 _destroyInitializingClassList(data->initializingClasses);
1433 // add further cleanup here...
1440 /***********************************************************************
1442 * Library initializer called by dyld & from crt0
1443 **********************************************************************/
1445 void _objcInit(void) {
1447 static int _done = 0;
1448 extern void __CFInitialize(void);
1449 extern int ptrace(int, int, int, int); // a system call visible to sc_trace
1451 /* Protect against multiple invocations, as all library
1452 * initializers should. */
1453 if (0 != _done) return;
1456 ptrace(0xb000, 0, 0, 0);
1457 trace(0xb000, 0, 0, 0);
1459 // make sure CF is initialized before we go further;
1460 // someday this can be removed, as it'll probably be automatic
1463 pthread_key_create(&_objc_pthread_key, _objc_pthread_destroyspecific);
1465 // Create the class lookup table
1466 _objc_init_class_hash ();
1468 trace(0xb001, 0, 0, 0);
1470 objc_setConfiguration(); // Get our configuration
1472 trace(0xb003, 0, 0, 0);
1474 // a pre-cheetah comment:
1475 // XXXXX BEFORE HERE *NO* PAGES ARE STOMPED ON;
1477 // Register our image mapping routine with dyld so it
1478 // gets invoked when an image is added. This also invokes
1479 // the callback right now on any images already present.
1481 // The modules present in the application and the existing
1482 // mapped images are treated differently than a newly discovered
1483 // mapped image - we process all modules for classes before
1484 // trying to install_relationships (glue up their superclasses)
1485 // or trying to send them any +load methods.
1487 // So we tell the map_image dyld callback to not do this part...
1489 Postpone_install_relationships = 1;
1491 // register for unmapping first so we can't miss any during load attempts
1492 _dyld_register_func_for_remove_image (&_objc_unmap_image);
1494 // finally, register for images
1495 _dyld_register_func_for_add_image (&_objc_map_image);
1497 // a pre-cheetah comment:
1498 // XXXXX BEFORE HERE *ALL* PAGES ARE STOMPED ON
1500 Postpone_install_relationships = 0;
1502 trace(0xb006, 0, 0, 0);
1504 // Install relations on classes that were found
1505 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1509 struct objc_module * module;
1510 struct objc_class * cls;
1512 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1513 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1515 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1517 cls = (struct objc_class *) module->symtab->defs[index];
1518 _class_install_relationships (cls, module->version);
1524 trace(0xb007, hInfo, hInfo->mod_count, 0);
1528 trace(0xb008, 0, 0, 0);
1530 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1532 // Initialize the isa pointers of all NXConstantString objects
1533 (void)_objc_fixup_string_objects_for_image (hInfo);
1535 // Convert class refs from name pointers to ids
1536 (void)_objc_map_class_refs_for_image (hInfo);
1539 trace(0xb00a, 0, 0, 0);
1541 // For each image selectorize the method names and +_fixup each of
1542 // protocols in the image
1543 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1544 _objc_fixup_protocol_objects_for_image (hInfo);
1546 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1547 _objc_call_loads_for_image (hInfo);
1549 ptrace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1550 trace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1554 /***********************************************************************
1556 **********************************************************************/
1557 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide)
1559 static int dumpClasses = -1;
1562 if ( dumpClasses == -1 ) {
1563 if ( getenv("OBJC_DUMP_CLASSES") ) dumpClasses = 1;
1564 else dumpClasses = 0;
1567 trace(0xb100, 0, 0, 0);
1569 // Add this header to the chain
1570 hInfo = _objc_addHeader (mh, vmaddr_slide);
1574 if (LaunchingDebug) { _objc_syslog("objc_map_image for %s\n", _nameForHeader(mh)); }
1576 trace(0xb101, 0, 0, 0);
1578 // Register any categories and/or classes and/or selectors this image contains
1579 _objc_add_categories_from_image (hInfo);
1581 trace(0xb103, 0, 0, 0);
1583 _objc_add_classes_from_image (class_hash, hInfo);
1585 trace(0xb104, 0, 0, 0);
1587 _objc_fixup_selector_refs (hInfo);
1589 trace(0xb105, 0, 0, 0);
1591 // Log all known class names, if asked
1594 printf ("classes...\n");
1595 objc_dump_class_hash ();
1598 if (!Postpone_install_relationships)
1602 struct objc_module * module;
1604 // Major loop - process each module
1605 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1607 trace(0xb106, hInfo->mod_count, 0, 0);
1609 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1611 // Minor loop - process each class in a given module
1612 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1614 struct objc_class * cls;
1616 // Locate the class description
1617 cls = (struct objc_class *) module->symtab->defs[index];
1619 // If there is no superclass or the superclass can be found,
1620 // install this class, and invoke the expected callback
1621 if (!((struct objc_class *)cls)->super_class || objc_lookUpClass ((char *) ((struct objc_class *)cls)->super_class))
1623 _class_install_relationships (cls, module->version);
1624 if (callbackFunction)
1625 (*callbackFunction) (cls, 0);
1629 // Super class can not be found yet, arrange for this class to
1630 // be filled in later
1631 objc_pendClassInstallation (cls, module->version);
1632 ((struct objc_class *)cls)->super_class = _objc_getNonexistentClass ();
1633 ((struct objc_class *)cls)->isa->super_class = _objc_getNonexistentClass ();
1641 trace(0xb108, 0, 0, 0);
1643 // Initialize the isa pointers of all NXConstantString objects
1644 _objc_fixup_string_objects_for_image (hInfo);
1646 trace(0xb109, 0, 0, 0);
1648 // Convert class refs from name pointers to ids
1649 _objc_map_class_refs_for_image (hInfo);
1651 trace(0xb10a, 0, 0, 0);
1653 // Selectorize the method names and +_fixup each of
1654 // protocols in the image
1655 _objc_fixup_protocol_objects_for_image (hInfo);
1657 trace(0xb10b, 0, 0, 0);
1659 // Call +load on all classes and categorized classes
1660 _objc_call_loads_for_image (hInfo);
1662 trace(0xb10c, 0, 0, 0);
1665 trace(0xb10f, 0, 0, 0);
1668 /***********************************************************************
1669 * _objc_unmap_image.
1670 **********************************************************************/
1671 static void _objc_unmap_image(headerType *mh, unsigned long vmaddr_slide) {
1672 // we shouldn't have it if it didn't have objc data
1673 // if we do have it, do a fatal
1674 _objc_fatalHeader(mh);
1677 /***********************************************************************
1678 * objc_setNilObjectMsgHandler.
1679 **********************************************************************/
1680 void objc_setNilObjectMsgHandler (NilObjectMsgCallback nilObjMsgCallback)
1682 _objc_msgNil = nilObjMsgCallback;
1685 /***********************************************************************
1686 * objc_getNilObjectMsgHandler.
1687 **********************************************************************/
1688 NilObjectMsgCallback objc_getNilObjectMsgHandler (void)
1690 return _objc_msgNil;