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 // Mask which specifies whether we are multi-threaded or not.
91 // A value of (-1) means single-threaded, 0 means multi-threaded.
92 int _objc_multithread_mask = (-1);
94 // Function to call when message sent to nil object.
95 void (*_objc_msgNil)(id, SEL) = NULL;
97 // Function called after class has been fixed up (MACH only)
98 void (*callbackFunction)(Class, const char *) = 0;
100 // Prototype for function passed to
101 typedef void (*NilObjectMsgCallback) (id nilObject, SEL selector);
103 // Lock for class hashtable
104 OBJC_DECLARE_LOCK (classLock);
106 // Condition for logging load progress
107 static int LaunchingDebug = -1;
109 /***********************************************************************
110 * Function prototypes internal to this module.
111 **********************************************************************/
113 static unsigned classHash (void * info, struct objc_class * data);
114 static int classIsEqual (void * info, struct objc_class * name, struct objc_class * cls);
115 static int _objc_defaultClassHandler (const char * clsName);
116 static void _objcTweakMethodListPointerForClass (struct objc_class * cls);
117 static void _objc_add_category_flush_caches(struct objc_class * cls, struct objc_category * category, int version);
118 static void _objc_add_category(struct objc_class * cls, struct objc_category * category, int version);
119 static void _objc_register_category (struct objc_category * cat, long version, int bindme);
120 static void _objc_add_categories_from_image (header_info * hi);
121 static const header_info * _headerForClass (struct objc_class * cls);
122 static PendingClass * newPending (void);
123 static NXMapTable * pendingClassRefsMapTable (void);
124 static void _objc_add_classes_from_image (NXHashTable * clsHash, header_info * hi);
125 static void _objc_fixup_string_objects_for_image(header_info * hi);
126 static void _objc_map_class_refs_for_image (header_info * hi);
127 static void map_selrefs (SEL * sels, unsigned int cnt);
128 static void map_method_descs (struct objc_method_description_list * methods);
129 static void _objc_fixup_protocol_objects_for_image (header_info * hi);
130 static void _objc_bindModuleContainingCategory(Category cat);
131 static const char * libraryNameForMachHeader (const headerType * themh);
132 static void _objc_fixup_selector_refs (const header_info * hi);
133 static void _objc_call_loads_for_image (header_info * header);
134 static void _objc_checkForPendingClassReferences (struct objc_class * cls);
135 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide);
136 static void _objc_unmap_image(headerType *mh, unsigned long vmaddr_slide);
138 /***********************************************************************
139 * Static data internal to this module.
140 **********************************************************************/
142 // we keep a linked list of header_info's describing each image as told to us by dyld
143 static header_info * FirstHeader = 0;
145 // Hash table of classes
146 static NXHashTable * class_hash = 0;
147 static NXHashTablePrototype classHashPrototype =
149 (unsigned (*) (const void *, const void *)) classHash,
150 (int (*)(const void *, const void *, const void *)) classIsEqual,
154 // Function pointer objc_getClass calls through when class is not found
155 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
157 // Category and class registries
158 static NXMapTable * category_hash = NULL;
161 static int Postpone_install_relationships = 0;
163 static NXMapTable * pendingClassRefsMap = 0;
165 /***********************************************************************
166 * objc_dump_class_hash. Log names of all known classes.
167 **********************************************************************/
168 void objc_dump_class_hash (void)
172 struct objc_class * * data;
177 state = NXInitHashState (table);
178 while (NXNextHashState (table, &state, (void **) &data))
179 printf ("class %d: %s\n", ++count, (*data)->name);
182 /***********************************************************************
184 **********************************************************************/
185 static unsigned classHash (void * info,
186 struct objc_class * data)
188 // Nil classes hash to zero
192 // Call through to real hash function
193 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
196 /***********************************************************************
197 * classIsEqual. Returns whether the class names match. If we ever
198 * check more than the name, routines like objc_lookUpClass have to
200 **********************************************************************/
201 static int classIsEqual (void * info,
202 struct objc_class * name,
203 struct objc_class * cls)
205 // Standard string comparison
206 return ((name->name[0] == cls->name[0]) &&
207 (strcmp (name->name, cls->name) == 0));
210 /***********************************************************************
211 * _objc_init_class_hash. Return the class lookup table, create it if
213 **********************************************************************/
214 void _objc_init_class_hash (void)
216 // Do nothing if class hash table already exists
220 // Provide a generous initial capacity to cut down on rehashes
221 // at launch time. A smallish Foundation+AppKit program will have
222 // about 520 classes. Larger apps (like IB or WOB) have more like
223 // 800 classes. Some customers have massive quantities of classes.
224 // Foundation-only programs aren't likely to notice the ~6K loss.
225 class_hash = NXCreateHashTableFromZone (classHashPrototype,
228 _objc_create_zone ());
231 /***********************************************************************
232 * objc_getClassList. Return the known classes.
233 **********************************************************************/
234 int objc_getClassList(Class *buffer, int bufferLen) {
236 struct objc_class * class;
239 OBJC_LOCK(&classLock);
240 num = NXCountHashTable(class_hash);
241 if (NULL == buffer) {
242 OBJC_UNLOCK(&classLock);
246 state = NXInitHashState(class_hash);
247 while (cnt < num && NXNextHashState(class_hash, &state, (void **)&class)) {
248 buffer[cnt++] = class;
250 OBJC_UNLOCK(&classLock);
254 /***********************************************************************
255 * objc_getClasses. Return class lookup table.
257 * NOTE: This function is very dangerous, since you cannot safely use
258 * the hashtable without locking it, and the lock is private!
259 **********************************************************************/
260 void * objc_getClasses (void)
262 // Return the class lookup hash table
266 /***********************************************************************
267 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
268 **********************************************************************/
269 static int _objc_defaultClassHandler (const char * clsName)
271 // Return zero so objc_getClass doesn't bother re-searching
275 /***********************************************************************
276 * objc_setClassHandler. Set objc_classHandler to the specified value.
278 * NOTE: This should probably deal with userSuppliedHandler being NULL,
279 * because the objc_classHandler caller does not check... it would bus
280 * error. It would make sense to handle NULL by restoring the default
281 * handler. Is anyone hacking with this, though?
282 **********************************************************************/
283 void objc_setClassHandler (int (*userSuppliedHandler) (const char *))
285 objc_classHandler = userSuppliedHandler;
288 /***********************************************************************
289 * objc_getClass. Return the id of the named class. If the class does
290 * not exist, call the objc_classHandler routine with the class name.
291 * If the objc_classHandler returns a non-zero value, try once more to
292 * find the class. Default objc_classHandler always returns zero.
293 * objc_setClassHandler is how someone can install a non-default routine.
294 **********************************************************************/
295 id objc_getClass (const char * aClassName)
297 struct objc_class cls;
300 // Synchronize access to hash table
301 OBJC_LOCK (&classLock);
303 // Check the hash table
304 cls.name = aClassName;
305 ret = (id) NXHashGet (class_hash, &cls);
306 OBJC_UNLOCK (&classLock);
308 // If not found, go call objc_classHandler and try again
309 if (!ret && (*objc_classHandler)(aClassName))
311 OBJC_LOCK (&classLock);
312 ret = (id) NXHashGet (class_hash, &cls);
313 OBJC_UNLOCK (&classLock);
319 /***********************************************************************
320 * objc_lookUpClass. Return the id of the named class.
322 * Formerly objc_getClassWithoutWarning ()
323 **********************************************************************/
324 id objc_lookUpClass (const char * aClassName)
326 struct objc_class cls;
329 // Synchronize access to hash table
330 OBJC_LOCK (&classLock);
332 // Check the hash table
333 cls.name = aClassName;
334 ret = (id) NXHashGet (class_hash, &cls);
337 OBJC_UNLOCK (&classLock);
341 /***********************************************************************
342 * objc_getMetaClass. Return the id of the meta class the named class.
343 **********************************************************************/
344 id objc_getMetaClass (const char * aClassName)
346 struct objc_class * cls;
348 cls = objc_getClass (aClassName);
351 _objc_inform ("class `%s' not linked into application", aClassName);
358 /***********************************************************************
359 * objc_addClass. Add the specified class to the table of known classes,
360 * after doing a little verification and fixup.
361 **********************************************************************/
362 void objc_addClass (Class cls)
364 // Synchronize access to hash table
365 OBJC_LOCK (&classLock);
367 // Make sure both the class and the metaclass have caches!
368 // Clear all bits of the info fields except CLS_CLASS and CLS_META.
369 // Normally these bits are already clear but if someone tries to cons
370 // up their own class on the fly they might need to be cleared.
371 if (((struct objc_class *)cls)->cache == NULL)
373 ((struct objc_class *)cls)->cache = (Cache) &emptyCache;
374 ((struct objc_class *)cls)->info = CLS_CLASS;
377 if (((struct objc_class *)cls)->isa->cache == NULL)
379 ((struct objc_class *)cls)->isa->cache = (Cache) &emptyCache;
380 ((struct objc_class *)cls)->isa->info = CLS_META;
383 // Add the class to the table
384 (void) NXHashInsert (class_hash, cls);
387 OBJC_UNLOCK (&classLock);
390 /***********************************************************************
391 * _objcTweakMethodListPointerForClass.
392 **********************************************************************/
393 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
395 struct objc_method_list * originalList;
396 const int initialEntries = 4;
398 struct objc_method_list ** ptr;
400 // Remember existing list
401 originalList = (struct objc_method_list *) cls->methodLists;
403 // Allocate and zero a method list array
404 mallocSize = sizeof(struct objc_method_list *) * initialEntries;
405 ptr = (struct objc_method_list **) malloc_zone_calloc (_objc_create_zone (), 1, mallocSize);
407 // Insert the existing list into the array
408 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
409 ptr[0] = originalList;
411 // Replace existing list with array
412 ((struct objc_class *)cls)->methodLists = ptr;
413 ((struct objc_class *)cls)->info |= CLS_METHOD_ARRAY;
415 // Do the same thing to the meta-class
416 if (((((struct objc_class *)cls)->info & CLS_CLASS) != 0) && cls->isa)
417 _objcTweakMethodListPointerForClass (cls->isa);
420 /***********************************************************************
421 * _objc_insertMethods.
422 **********************************************************************/
423 void _objc_insertMethods (struct objc_method_list * mlist,
424 struct objc_method_list *** list)
426 struct objc_method_list ** ptr;
427 volatile struct objc_method_list ** tempList;
432 // Locate unused entry for insertion point
434 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
437 // If array is full, double it
438 if (*ptr == END_OF_METHODS_LIST)
440 // Calculate old and new dimensions
441 endIndex = ptr - *list;
442 oldSize = (endIndex + 1) * sizeof(void *);
443 newSize = oldSize + sizeof(struct objc_method_list *); // only increase by 1
445 // Replace existing array with copy twice its size
446 tempList = (struct objc_method_list **) malloc_zone_realloc ((void *) _objc_create_zone (),
451 // Zero out addition part of new array
452 bzero (&((*list)[endIndex]), newSize - oldSize);
454 // Place new end marker
455 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
457 // Insertion point corresponds to old array end
458 ptr = &((*list)[endIndex]);
461 // Right shift existing entries by one
462 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
464 // Insert at method list at beginning of array
468 /***********************************************************************
469 * _objc_removeMethods.
470 **********************************************************************/
471 void _objc_removeMethods (struct objc_method_list * mlist,
472 struct objc_method_list *** list)
474 struct objc_method_list ** ptr;
476 // Locate list in the array
478 while (*ptr != mlist) {
479 // fix for radar # 2538790
480 if ( *ptr == END_OF_METHODS_LIST ) return;
487 // Left shift the following entries
488 while (*(++ptr) != END_OF_METHODS_LIST)
493 /***********************************************************************
494 * _objc_add_category. Install the specified category's methods and
495 * protocols into the class it augments.
496 **********************************************************************/
497 static inline void _objc_add_category(struct objc_class *cls, struct objc_category *category, int version)
499 // Augment instance methods
500 if (category->instance_methods)
501 _objc_insertMethods (category->instance_methods, &cls->methodLists);
503 // Augment class methods
504 if (category->class_methods)
505 _objc_insertMethods (category->class_methods, &cls->isa->methodLists);
508 if ((version >= 5) && category->protocols)
510 if (cls->isa->version >= 5)
512 category->protocols->next = cls->protocols;
513 cls->protocols = category->protocols;
514 cls->isa->protocols = category->protocols;
518 _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
519 _objc_inform ("class `%s' must be recompiled\n", category->class_name);
524 /***********************************************************************
525 * _objc_add_category_flush_caches. Install the specified category's methods into
526 * the class it augments, and flush the class' method cache.
528 **********************************************************************/
529 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
531 // Install the category's methods into its intended class
532 _objc_add_category (cls, category, version);
534 // Flush caches so category's methods can get called
535 _objc_flush_caches (cls);
538 /***********************************************************************
539 * _objc_resolve_categories_for_class. Install all categories intended
540 * for the specified class, in reverse order from the order in which we
541 * found the categories in the image.
542 * This is done as lazily as we can.
543 **********************************************************************/
544 void _objc_resolve_categories_for_class (struct objc_class * cls)
546 _objc_unresolved_category * cat;
547 _objc_unresolved_category * next;
549 // Nothing to do if there are no categories at all
553 // Locate and remove first element in category list
554 // associated with this class
555 cat = NXMapRemove (category_hash, cls->name);
557 // Traverse the list of categories, if any, registered for this class
561 _objc_bindModuleContainingCategory(cat->cat);
563 // Install the category
564 // use the non-flush-cache version since we are only
565 // called from the class intialization code
566 _objc_add_category (cls, cat->cat, cat->version);
568 // Delink and reclaim this registration
575 /***********************************************************************
576 * _objc_register_category. Add the specified category to the registry
577 * of categories to be installed later (once we know for sure which
578 * classes we have). If there are multiple categories on a given class,
579 * they will be processed in reverse order from the order in which they
580 * were found in the image.
581 **********************************************************************/
582 static void _objc_register_category (struct objc_category * cat,
586 _objc_unresolved_category * new_cat;
587 _objc_unresolved_category * old;
588 struct objc_class *theClass;
591 // If the category's class exists, just add the category
592 // We could check to see if its initted, and if not, defer this
593 // work until _objc_resolve_categories_for_class for all cases
594 // The only trick then is whether we need to bind it. This
595 // might be doable if we store an obscured pointer so that we
596 // avoid touching the memory... [BG 5/2001 still in think mode]
597 if (theClass = objc_lookUpClass (cat->class_name))
600 _objc_bindModuleContainingCategory(cat);
602 _objc_add_category_flush_caches (theClass, cat, version);
606 // Create category lookup table if needed
608 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
610 _objc_create_zone ());
612 // Locate an existing category, if any, for the class. This is linked
613 // after the new entry, so list is LIFO.
614 old = NXMapGet (category_hash, cat->class_name);
616 // Register the category to be fixed up later
617 new_cat = malloc_zone_malloc (_objc_create_zone (),
618 sizeof(_objc_unresolved_category));
621 new_cat->version = version;
622 new_cat->bindme = bindme; // could use a bit in the next pointer instead of a whole word
623 (void) NXMapInsert (category_hash, cat->class_name , new_cat);
626 /***********************************************************************
627 * _objc_add_categories_from_image.
628 **********************************************************************/
629 static void _objc_add_categories_from_image (header_info * hi)
633 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
635 // Major loop - process all modules in the header
636 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
638 trace(0xb120, hi->mod_count, 0, 0);
640 for (midx = 0; midx < hi->mod_count; midx += 1)
645 // Nothing to do for a module without a symbol table
646 if (mods[midx].symtab == NULL)
649 // Total entries in symbol table (class entries followed
650 // by category entries)
651 total = mods[midx].symtab->cls_def_cnt +
652 mods[midx].symtab->cat_def_cnt;
655 trace(0xb123, midx, mods[midx].symtab->cat_def_cnt, 0);
657 // Minor loop - register all categories from given module
658 for (index = mods[midx].symtab->cls_def_cnt; index < total; index += 1)
660 _objc_register_category(mods[midx].symtab->defs[index], mods[midx].version, isDynamic);
663 trace(0xb124, midx, 0, 0);
666 trace(0xb12f, 0, 0, 0);
669 /***********************************************************************
671 **********************************************************************/
672 static const header_info * _headerForClass (struct objc_class * cls)
674 const struct segment_command * objcSeg;
676 unsigned long vmaddrPlus;
679 // Check all headers in the vector
680 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
682 // Locate header data, if any
683 objcSeg = _getObjcHeaderData ((headerType *) hInfo->mhdr, &size);
687 // Is the class in this header?
688 vmaddrPlus = (unsigned long) objcSeg->vmaddr + hInfo->image_slide;
689 if ((vmaddrPlus <= (unsigned long) cls) &&
690 ((unsigned long) cls < (vmaddrPlus + size)))
698 /***********************************************************************
700 **********************************************************************/
701 const char * _nameForHeader (const headerType * header)
703 return _getObjcHeaderName ((headerType *) header);
706 /***********************************************************************
707 * checkForPendingClassReferences. Complete any fixups registered for
709 **********************************************************************/
710 static void _objc_checkForPendingClassReferences (struct objc_class * cls)
712 PendingClass * pending;
714 // Nothing to do if there are no pending classes
715 if (!pendingClassRefsMap)
718 // Get pending list for this class
719 pending = NXMapGet (pendingClassRefsMap, cls->name);
723 // Remove the list from the table
724 (void) NXMapRemove (pendingClassRefsMap, cls->name);
726 // Process all elements in the list
731 // Remember follower for loop
732 next = pending->next;
734 // Fill in a pointer to Class
735 // (satisfies caller of objc_pendClassReference)
737 *pending->ref = objc_getClass (cls->name);
739 // Fill in super, isa, cache, and version for the class
740 // and its meta-class
741 // (satisfies caller of objc_pendClassInstallation)
742 // NOTE: There must be no more than one of these for
743 // any given classToSetUp
744 if (pending->classToSetUp)
746 struct objc_class * fixCls;
748 // Locate the Class to be fixed up
749 fixCls = pending->classToSetUp;
751 // Set up super class fields with names to be replaced by pointers
752 fixCls->super_class = (struct objc_class *) pending->nameof_superclass;
753 fixCls->isa->super_class = (struct objc_class *) pending->nameof_superclass;
755 // Fix up class pointers, version, and cache pointers
756 _class_install_relationships (fixCls, pending->version);
759 // Reclaim the element
767 /***********************************************************************
768 * newPending. Allocate and zero a PendingClass structure.
769 **********************************************************************/
770 static inline PendingClass * newPending (void)
772 PendingClass * pending;
774 pending = (PendingClass *) malloc_zone_calloc (_objc_create_zone (), 1, sizeof(PendingClass));
779 /***********************************************************************
780 * pendingClassRefsMapTable. Return a pointer to the lookup table for
782 **********************************************************************/
783 static inline NXMapTable * pendingClassRefsMapTable (void)
785 // Allocate table if needed
786 if (!pendingClassRefsMap)
787 pendingClassRefsMap = NXCreateMapTableFromZone (NXStrValueMapPrototype, 10, _objc_create_zone ());
789 // Return table pointer
790 return pendingClassRefsMap;
793 /***********************************************************************
794 * objc_pendClassReference. Register the specified class pointer (ref)
795 * to be filled in later with a pointer to the class having the specified
797 **********************************************************************/
798 void objc_pendClassReference (const char * className,
799 struct objc_class * * ref)
802 PendingClass * pending;
804 // Create and/or locate pending class lookup table
805 table = pendingClassRefsMapTable ();
807 // Create entry containing the class reference
808 pending = newPending ();
811 // Link new entry into head of list of entries for this class
812 pending->next = NXMapGet (pendingClassRefsMap, className);
814 // (Re)place entry list in the table
815 (void) NXMapInsert (table, className, pending);
818 /***********************************************************************
819 * objc_pendClassInstallation. Register the specified class to have its
820 * super class pointers filled in later because the superclass is not
822 **********************************************************************/
823 void objc_pendClassInstallation (struct objc_class *cls, int version)
826 PendingClass * pending;
828 // Create and/or locate pending class lookup table
829 table = pendingClassRefsMapTable ();
831 // Create entry referring to this class
832 pending = newPending ();
833 pending->classToSetUp = cls;
834 pending->nameof_superclass = (const char *) cls->super_class;
835 pending->version = version;
837 // Link new entry into head of list of entries for this class
838 pending->next = NXMapGet (pendingClassRefsMap, cls->super_class);
840 // (Re)place entry list in the table
841 (void) NXMapInsert (table, cls->super_class, pending);
844 /***********************************************************************
845 * _objc_add_classes_from_image. Install all classes contained in the
847 **********************************************************************/
848 static void _objc_add_classes_from_image(NXHashTable *clsHash, header_info *hi)
853 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
855 // Major loop - process all modules in the image
856 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
857 for (midx = 0; midx < hi->mod_count; midx += 1)
859 // Skip module containing no classes
860 if (mods[midx].symtab == NULL)
863 // Minor loop - process all the classes in given module
864 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
866 struct objc_class * oldCls;
867 struct objc_class * newCls;
869 // Locate the class description pointer
870 newCls = mods[midx].symtab->defs[index];
872 // remember to bind the module on initialization
874 newCls->info |= CLS_NEED_BIND ;
876 // Convert old style method list to the new style
877 _objcTweakMethodListPointerForClass (newCls);
879 oldCls = NXHashInsert (clsHash, newCls);
881 // Non-Nil oldCls is a class that NXHashInsert just
882 // bumped from table because it has the same name
886 const header_info * oldHeader;
887 const header_info * newHeader;
888 const char * oldName;
889 const char * newName;
891 // Log the duplication
892 oldHeader = _headerForClass (oldCls);
893 newHeader = _headerForClass (newCls);
894 oldName = _nameForHeader (oldHeader->mhdr);
895 newName = _nameForHeader (newHeader->mhdr);
896 _objc_inform ("Both %s and %s have implementations of class %s.",
897 oldName, newName, oldCls->name);
898 _objc_inform ("Using implementation from %s.", newName);
900 // Use the chosen class
901 // NOTE: Isn't this a NOP?
902 newCls = objc_lookUpClass (oldCls->name);
905 // Unless newCls was a duplicate, and we chose the
906 // existing one instead, set the version in the meta-class
907 if (newCls != oldCls)
908 newCls->isa->version = mods[midx].version;
910 // Install new categories intended for this class
911 // NOTE: But, if we displaced an existing "isEqual"
912 // class, the categories have already been installed
913 // on an old class and are gone from the registry!!
915 // we defer this work until the class is initialized.
916 //_objc_resolve_categories_for_class (newCls);
918 // Resolve (a) pointers to the named class, and/or
919 // (b) the super_class, cache, and version
920 // fields of newCls and its meta-class
921 // NOTE: But, if we displaced an existing "isEqual"
922 // class, this has already been done... with an
923 // old-now-"unused" class!!
924 _objc_checkForPendingClassReferences (newCls);
930 /***********************************************************************
931 * _objc_fixup_string_objects_for_image. Initialize the isa pointers
932 * of all NSConstantString objects.
933 **********************************************************************/
934 static void _objc_fixup_string_objects_for_image (header_info * hi)
937 OBJC_CONSTANT_STRING_PTR section;
938 struct objc_class * constantStringClass;
941 // Locate section holding string objects
942 section = _getObjcStringObjects ((headerType *) hi->mhdr, &size);
943 if (!section || !size)
945 section = (OBJC_CONSTANT_STRING_PTR) ((unsigned long) section + hi->image_slide);
947 // Luckily NXConstantString is the same size as NSConstantString
948 constantStringClass = objc_getClass ("NSConstantString");
950 // Process each string object in the section
951 for (index = 0; index < size; index += 1)
953 struct objc_class * * isaptr;
955 isaptr = (struct objc_class * *) OBJC_CONSTANT_STRING_DEREF section[index];
957 *isaptr = constantStringClass;
961 /***********************************************************************
962 * _objc_map_class_refs_for_image. Convert the class ref entries from
963 * a class name string pointer to a class pointer. If the class does
964 * not yet exist, the reference is added to a list of pending references
965 * to be fixed up at a later date.
966 **********************************************************************/
967 static void _objc_map_class_refs_for_image (header_info * hi)
969 struct objc_class * * cls_refs;
973 // Locate class refs in image
974 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
977 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
979 // Process each class ref
980 for (index = 0; index < size; index += 1)
983 struct objc_class * cls;
985 // Get ref to convert from name string to class pointer
986 ref = (const char *) cls_refs[index];
988 // Get pointer to class of this name
989 cls = (struct objc_class *)objc_lookUpClass (ref);
991 // If class isn't there yet, use pending mechanism
994 // Register this ref to be set later
995 objc_pendClassReference (ref, &cls_refs[index]);
997 // Use place-holder class
998 cls_refs[index] = _objc_getNonexistentClass ();
1001 // Replace name string pointer with class pointer
1003 cls_refs[index] = cls;
1007 /***********************************************************************
1008 * map_selrefs. Register each selector in the specified array. If a
1009 * given selector is already registered, update this array to point to
1010 * the registered selector string.
1011 **********************************************************************/
1012 static inline void map_selrefs(SEL *sels, unsigned int cnt)
1016 // Process each selector
1017 for (index = 0; index < cnt; index += 1)
1021 // Lookup pointer to uniqued string
1022 sel = sel_registerNameNoCopy ((const char *) sels[index]);
1024 // Replace this selector with uniqued one (avoid
1025 // modifying the VM page if this would be a NOP)
1026 if (sels[index] != sel)
1032 /***********************************************************************
1033 * map_method_descs. For each method in the specified method list,
1034 * replace the name pointer with a uniqued selector.
1035 **********************************************************************/
1036 static void map_method_descs (struct objc_method_description_list * methods)
1040 // Process each method
1041 for (index = 0; index < methods->count; index += 1)
1043 struct objc_method_description * method;
1046 // Get method entry to fix up
1047 method = &methods->list[index];
1049 // Lookup pointer to uniqued string
1050 sel = sel_registerNameNoCopy ((const char *) method->name);
1052 // Replace this selector with uniqued one (avoid
1053 // modifying the VM page if this would be a NOP)
1054 if (method->name != sel)
1059 /***********************************************************************
1061 **********************************************************************/
1062 @interface Protocol(RuntimePrivate)
1063 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
1066 /***********************************************************************
1067 * _objc_fixup_protocol_objects_for_image. For each protocol in the
1068 * specified image, selectorize the method names and call +_fixup.
1069 **********************************************************************/
1070 static void _objc_fixup_protocol_objects_for_image (header_info * hi)
1073 OBJC_PROTOCOL_PTR protos;
1076 // Locate protocals in the image
1077 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
1081 // Apply the slide bias
1082 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
1084 // Process each protocol
1085 for (index = 0; index < size; index += 1)
1087 // Selectorize the instance methods
1088 if (protos[index] OBJC_PROTOCOL_DEREF instance_methods)
1089 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF instance_methods);
1091 // Selectorize the class methods
1092 if (protos[index] OBJC_PROTOCOL_DEREF class_methods)
1093 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF class_methods);
1096 // Invoke Protocol class method to fix up the protocol
1097 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
1100 /***********************************************************************
1101 * _objc_headerStart. Return what headers we know about.
1102 **********************************************************************/
1103 header_info * _objc_headerStart ()
1106 // Take advatage of our previous work
1110 void _objc_bindModuleContainingList() {
1111 /* We define this for backwards binary compat with things which should not
1112 * have been using it (cough OmniWeb), but now it does nothing for them.
1116 /**********************************************************************
1117 * _objc_bind_symbol. Bind the module containing the symbol. Use 2-level namespace API
1118 * Only look in images that we know to have ObjC symbols (e.g. 9 for Mail 7/2001)
1120 ***********************************************************************/
1121 static void _objc_bind_symbol(const char *name)
1124 static header_info *lastHeader = NULL;
1126 const headerType *imageHeader = lastHeader ? lastHeader->mhdr : NULL;
1128 // Ideally we would have a way to not even process a symbol in a module
1129 // we've already visited
1132 // First assume there is some locality and search where we last found a symbol
1134 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1135 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1141 // Symbol wasn't found in the image we last searched
1142 // Search in all the images known to contain ObjcC
1143 for ( hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1145 imageHeader = hInfo->mhdr;
1146 if ( hInfo != lastHeader
1147 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1148 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1155 // die now, or later ??
1156 // _objc_fatal("could not find %s", name);
1159 /***********************************************************************
1160 * _objc_bindModuleContainingCategory. Bind the module containing the
1162 **********************************************************************/
1163 static void _objc_bindModuleContainingCategory (Category cat)
1166 char * category_name;
1169 unsigned int name_len;
1171 // Bind ".objc_category_name_<classname>_<categoryname>",
1172 // where <classname> is the class name with the leading
1174 class_name = cat->class_name;
1175 category_name = cat->category_name;
1176 name_len = strlen(class_name) + strlen(category_name) + 30;
1177 if ( name_len > 128 )
1178 name = malloc(name_len);
1181 while (*class_name == '%')
1183 strcpy (name, ".objc_category_name_");
1184 strcat (name, class_name);
1186 strcat (name, category_name);
1187 if (LaunchingDebug) { _objc_syslog("_objc_bindModuleContainingCategory for %s on %s", category_name, class_name); }
1188 _objc_bind_symbol(name);
1189 if ( name != tmp_buf )
1193 /***********************************************************************
1194 * _objc_bindModuleContainingClass. Bind the module containing the
1196 * This is done lazily, just after initializing the class (if needed)
1197 **********************************************************************/
1199 void _objc_bindModuleContainingClass (struct objc_class * cls) {
1201 const char * class_name;
1203 unsigned int name_len;
1205 // Use the real class behind the poser
1206 if (CLS_GETINFO (cls, CLS_POSING))
1207 cls = getOriginalClassForPosingClass (cls);
1208 class_name = cls->name;
1210 name_len = strlen(class_name) + 20;
1211 if ( name_len > 128 )
1212 name = malloc(name_len);
1216 while (*class_name == '%')
1218 strcpy (name, ".objc_class_name_");
1219 strcat (name, class_name);
1220 if (LaunchingDebug) { _objc_syslog("_objc_bindModuleContainingClass for %s", class_name); }
1221 _objc_bind_symbol(name);
1222 if ( name != tmp_buf )
1227 /***********************************************************************
1230 **********************************************************************/
1232 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
1233 #define HINFO_SIZE 16
1235 static int HeaderInfoCounter = 0;
1236 static header_info HeaderInfoTable[HINFO_SIZE] = { {0} };
1238 static header_info * _objc_addHeader(const headerType *header, unsigned long vmaddr_slide)
1241 Module mod_ptr = _getObjcModules ((headerType *) header, &mod_count);
1242 header_info *result;
1244 // if there is no objc data - ignore this entry!
1245 if (mod_ptr == NULL) {
1249 if (HeaderInfoCounter < HINFO_SIZE) {
1250 // avoid mallocs for the common case
1251 result = &HeaderInfoTable[HeaderInfoCounter++];
1254 result = malloc_zone_malloc(_objc_create_zone(), sizeof(header_info));
1257 // Set up the new vector entry
1258 result->mhdr = header;
1259 result->mod_ptr = mod_ptr;
1260 result->mod_count = mod_count;
1261 result->image_slide = vmaddr_slide;
1264 // (a simple lock here would go a long way towards thread safety)
1265 result->next = FirstHeader;
1266 FirstHeader = result;
1271 /**********************************************************************
1274 * If we have it we're in trouble
1275 **************************************************************************/
1276 void _objc_fatalHeader(const headerType *header)
1280 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next) {
1281 if (hInfo->mhdr == header) {
1282 _objc_fatal("cannot unmap an image containing ObjC data");
1287 /***********************************************************************
1288 * libraryNameForMachHeader.
1289 **********************************************************************/
1290 static const char * libraryNameForMachHeader (const headerType * themh)
1292 unsigned long index;
1293 unsigned long imageCount;
1296 // Search images for matching type
1297 imageCount = _dyld_image_count ();
1298 for (index = 0; index < imageCount ; index += 1)
1300 // Return name of image with matching type
1301 mh = _dyld_get_image_header (index);
1303 return _dyld_get_image_name (index);
1310 /***********************************************************************
1311 * _objc_fixup_selector_refs. Register all of the selectors in each
1312 * image, and fix them all up.
1314 **********************************************************************/
1315 static void _objc_fixup_selector_refs (const header_info * hi)
1319 OBJC_PROTOCOL_PTR protos;
1322 SEL * messages_refs;
1324 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
1326 // Fix up message refs
1327 messages_refs = (SEL *) _getObjcMessageRefs ((headerType *) hi->mhdr, &size);
1330 messages_refs = (SEL *) ((unsigned long) messages_refs + hi->image_slide);
1331 map_selrefs (messages_refs, size);
1336 /***********************************************************************
1337 * _objc_call_loads_for_image.
1338 **********************************************************************/
1339 static void _objc_call_loads_for_image (header_info * header)
1341 struct objc_class * cls;
1342 struct objc_class * * pClass;
1343 Category * pCategory;
1345 unsigned int nModules;
1346 unsigned int nClasses;
1347 unsigned int nCategories;
1348 struct objc_symtab * symtab;
1349 struct objc_module * module;
1351 // Major loop - process all modules named in header
1352 module = (struct objc_module *) ((unsigned long) header->mod_ptr + header->image_slide);
1353 for (nModules = header->mod_count; nModules; nModules -= 1, module += 1)
1355 symtab = module->symtab;
1359 // Minor loop - call the +load from each class in the given module
1360 for (nClasses = symtab->cls_def_cnt, pClass = (Class *) symtab->defs;
1362 nClasses -= 1, pClass += 1)
1364 struct objc_method_list **mlistp;
1365 cls = (struct objc_class *)*pClass;
1366 mlistp = get_base_method_list(cls->isa);
1367 if (cls->isa->methodLists && mlistp)
1369 // Look up the method manually (vs messaging the class) to bypass
1370 // +initialize and cache fill on class that is not even loaded yet
1371 load_method = class_lookupNamedMethodInMethodList (*mlistp, "load");
1373 if (cls->info & CLS_NEED_BIND) {
1374 cls->info &= ~CLS_NEED_BIND;
1375 _objc_bindModuleContainingClass(cls);
1377 (*load_method) ((id) cls, @selector(load));
1382 // Minor loop - call the +load from augmented class of
1383 // each category in the given module
1384 for (nCategories = symtab->cat_def_cnt,
1385 pCategory = (Category *) &symtab->defs[symtab->cls_def_cnt];
1387 nCategories -= 1, pCategory += 1)
1389 struct objc_method_list * methods;
1391 methods = (*pCategory)->class_methods;
1394 load_method = class_lookupNamedMethodInMethodList (methods, "load");
1396 // Strictly speaking we shouldn't need (and don't want) to get the class here
1397 // The side effect we're looking for is to load it if needed.
1398 // Since category +loads are rare we could spend some cycles finding out
1399 // if we have a "bindme" TBD and do it here, saving a class load.
1400 // But chances are the +load will cause class initialization anyway
1401 cls = objc_getClass ((*pCategory)->class_name);
1402 // the class & all categories are now bound in
1403 (*load_method) ((id) cls, @selector(load));
1410 /***********************************************************************
1411 * runtime configuration
1412 **********************************************************************/
1413 static void objc_setConfiguration() {
1414 if ( LaunchingDebug == -1 ) {
1415 // watch image loading and binding
1416 LaunchingDebug = getenv("LaunchingDebug") != NULL;
1419 /***********************************************************************
1420 * objc_setMultithreaded.
1421 **********************************************************************/
1422 void objc_setMultithreaded (BOOL flag)
1425 _objc_multithread_mask = 0;
1427 _objc_multithread_mask = (-1);
1429 /***********************************************************************
1431 * Library initializer called by dyld & from crt0
1432 **********************************************************************/
1434 void _objcInit(void) {
1436 static int _done = 0;
1437 extern void __CFInitialize(void);
1438 extern int ptrace(int, int, int, int); // a system call visible to sc_trace
1440 /* Protect against multiple invocations, as all library
1441 * initializers should. */
1442 if (0 != _done) return;
1445 ptrace(0xb000, 0, 0, 0);
1446 trace(0xb000, 0, 0, 0);
1448 // make sure CF is initialized before we go further;
1449 // someday this can be removed, as it'll probably be automatic
1452 // Create the class lookup table
1453 _objc_init_class_hash ();
1455 trace(0xb001, 0, 0, 0);
1457 objc_setConfiguration(); // Get our configuration
1459 trace(0xb003, 0, 0, 0);
1461 // a pre-cheetah comment:
1462 // XXXXX BEFORE HERE *NO* PAGES ARE STOMPED ON;
1464 // Register our image mapping routine with dyld so it
1465 // gets invoked when an image is added. This also invokes
1466 // the callback right now on any images already present.
1468 // The modules present in the application and the existing
1469 // mapped images are treated differently than a newly discovered
1470 // mapped image - we process all modules for classes before
1471 // trying to install_relationships (glue up their superclasses)
1472 // or trying to send them any +load methods.
1474 // So we tell the map_image dyld callback to not do this part...
1476 Postpone_install_relationships = 1;
1478 // register for unmapping first so we can't miss any during load attempts
1479 _dyld_register_func_for_remove_image (&_objc_unmap_image);
1481 // finally, register for images
1482 _dyld_register_func_for_add_image (&_objc_map_image);
1484 // a pre-cheetah comment:
1485 // XXXXX BEFORE HERE *ALL* PAGES ARE STOMPED ON
1487 Postpone_install_relationships = 0;
1489 trace(0xb006, 0, 0, 0);
1491 // Install relations on classes that were found
1492 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1496 struct objc_module * module;
1497 struct objc_class * cls;
1499 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1500 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1502 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1504 cls = (struct objc_class *) module->symtab->defs[index];
1505 _class_install_relationships (cls, module->version);
1511 trace(0xb007, hInfo, hInfo->mod_count, 0);
1515 trace(0xb008, 0, 0, 0);
1517 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1519 // Initialize the isa pointers of all NXConstantString objects
1520 (void)_objc_fixup_string_objects_for_image (hInfo);
1522 // Convert class refs from name pointers to ids
1523 (void)_objc_map_class_refs_for_image (hInfo);
1526 trace(0xb00a, 0, 0, 0);
1528 // For each image selectorize the method names and +_fixup each of
1529 // protocols in the image
1530 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1531 _objc_fixup_protocol_objects_for_image (hInfo);
1533 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1534 _objc_call_loads_for_image (hInfo);
1536 ptrace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1537 trace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1541 /***********************************************************************
1543 **********************************************************************/
1544 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide)
1546 static int dumpClasses = -1;
1550 if ( dumpClasses == -1 ) {
1551 if ( getenv("OBJC_DUMP_CLASSES") ) dumpClasses = 1;
1552 else dumpClasses = 0;
1555 trace(0xb100, 0, 0, 0);
1557 // Add this header to the chain
1558 hInfo = _objc_addHeader (mh, vmaddr_slide);
1562 if (LaunchingDebug) { _objc_syslog("objc_map_image for %s\n", _nameForHeader(mh)); }
1564 trace(0xb101, 0, 0, 0);
1566 // Register any categories and/or classes and/or selectors this image contains
1567 _objc_add_categories_from_image (hInfo);
1569 trace(0xb103, 0, 0, 0);
1571 _objc_add_classes_from_image (class_hash, hInfo);
1573 trace(0xb104, 0, 0, 0);
1575 _objc_fixup_selector_refs (hInfo);
1577 trace(0xb105, 0, 0, 0);
1579 // Log all known class names, if asked
1582 printf ("classes...\n");
1583 objc_dump_class_hash ();
1586 if (!Postpone_install_relationships)
1590 struct objc_module * module;
1592 // Major loop - process each module
1593 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1595 trace(0xb106, hInfo->mod_count, 0, 0);
1597 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1599 // Minor loop - process each class in a given module
1600 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1602 struct objc_class * cls;
1604 // Locate the class description
1605 cls = (struct objc_class *) module->symtab->defs[index];
1607 // If there is no superclass or the superclass can be found,
1608 // install this class, and invoke the expected callback
1609 if (!((struct objc_class *)cls)->super_class || objc_lookUpClass ((char *) ((struct objc_class *)cls)->super_class))
1611 _class_install_relationships (cls, module->version);
1612 if (callbackFunction)
1613 (*callbackFunction) (cls, 0);
1617 // Super class can not be found yet, arrange for this class to
1618 // be filled in later
1619 objc_pendClassInstallation (cls, module->version);
1620 ((struct objc_class *)cls)->super_class = _objc_getNonexistentClass ();
1621 ((struct objc_class *)cls)->isa->super_class = _objc_getNonexistentClass ();
1629 trace(0xb108, 0, 0, 0);
1631 // Initialize the isa pointers of all NXConstantString objects
1632 _objc_fixup_string_objects_for_image (hInfo);
1634 trace(0xb109, 0, 0, 0);
1636 // Convert class refs from name pointers to ids
1637 _objc_map_class_refs_for_image (hInfo);
1639 trace(0xb10a, 0, 0, 0);
1641 // Selectorize the method names and +_fixup each of
1642 // protocols in the image
1643 _objc_fixup_protocol_objects_for_image (hInfo);
1645 trace(0xb10b, 0, 0, 0);
1647 // Call +load on all classes and categorized classes
1648 _objc_call_loads_for_image (hInfo);
1650 trace(0xb10c, 0, 0, 0);
1653 trace(0xb10f, 0, 0, 0);
1656 /***********************************************************************
1657 * _objc_unmap_image.
1658 **********************************************************************/
1659 static void _objc_unmap_image(headerType *mh, unsigned long vmaddr_slide) {
1660 // we shouldn't have it if it didn't have objc data
1661 // if we do have it, do a fatal
1662 _objc_fatalHeader(mh);
1665 /***********************************************************************
1666 * objc_setNilObjectMsgHandler.
1667 **********************************************************************/
1668 void objc_setNilObjectMsgHandler (NilObjectMsgCallback nilObjMsgCallback)
1670 _objc_msgNil = nilObjMsgCallback;
1673 /***********************************************************************
1674 * objc_getNilObjectMsgHandler.
1675 **********************************************************************/
1676 NilObjectMsgCallback objc_getNilObjectMsgHandler (void)
1678 return _objc_msgNil;