]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-runtime.m
86036ef5d1b764dca878e12b5b3c4f46d8de5c91
[apple/objc4.git] / runtime / objc-runtime.m
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * 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
12 * this file.
13 *
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
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /***********************************************************************
25 * objc-runtime.m
26 * Copyright 1988-1996, NeXT Software, Inc.
27 * Author: s. naroff
28 *
29 **********************************************************************/
30
31 /***********************************************************************
32 * Imports.
33 **********************************************************************/
34
35
36 #include <mach-o/ldsyms.h>
37 #include <mach-o/dyld.h>
38 #include <mach/vm_statistics.h>
39
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>
44 #import "maptable.h"
45 #import "objc-private.h"
46 #import <objc/Object.h>
47 #import <objc/Protocol.h>
48
49 #include <sys/time.h>
50 #include <sys/resource.h>
51
52 OBJC_EXPORT Class _objc_getNonexistentClass(void);
53
54
55 OBJC_EXPORT Class getOriginalClassForPosingClass(Class);
56
57
58 /***********************************************************************
59 * Constants and macros internal to this module.
60 **********************************************************************/
61
62 /* Turn on support for literal string objects. */
63 #define LITERAL_STRING_OBJECTS
64
65 /***********************************************************************
66 * Types internal to this module.
67 **********************************************************************/
68
69 typedef struct _objc_unresolved_category
70 {
71 struct _objc_unresolved_category * next;
72 struct objc_category * cat;
73 long version;
74 int bindme;
75 } _objc_unresolved_category;
76
77 typedef struct _PendingClass
78 {
79 struct objc_class * * ref;
80 struct objc_class * classToSetUp;
81 const char * nameof_superclass;
82 int version;
83 struct _PendingClass * next;
84 } PendingClass;
85
86 /***********************************************************************
87 * Exports.
88 **********************************************************************/
89
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);
93
94 // Function to call when message sent to nil object.
95 void (*_objc_msgNil)(id, SEL) = NULL;
96
97 // Function called after class has been fixed up (MACH only)
98 void (*callbackFunction)(Class, const char *) = 0;
99
100 // Prototype for function passed to
101 typedef void (*NilObjectMsgCallback) (id nilObject, SEL selector);
102
103 // Lock for class hashtable
104 OBJC_DECLARE_LOCK (classLock);
105
106 // Condition for logging load progress
107 static int LaunchingDebug = -1;
108
109 /***********************************************************************
110 * Function prototypes internal to this module.
111 **********************************************************************/
112
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);
137
138 /***********************************************************************
139 * Static data internal to this module.
140 **********************************************************************/
141
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;
144
145 // Hash table of classes
146 static NXHashTable * class_hash = 0;
147 static NXHashTablePrototype classHashPrototype =
148 {
149 (unsigned (*) (const void *, const void *)) classHash,
150 (int (*)(const void *, const void *, const void *)) classIsEqual,
151 NXNoEffectFree, 0
152 };
153
154 // Function pointer objc_getClass calls through when class is not found
155 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
156
157 // Category and class registries
158 static NXMapTable * category_hash = NULL;
159
160
161 static int Postpone_install_relationships = 0;
162
163 static NXMapTable * pendingClassRefsMap = 0;
164
165 /***********************************************************************
166 * objc_dump_class_hash. Log names of all known classes.
167 **********************************************************************/
168 void objc_dump_class_hash (void)
169 {
170 NXHashTable * table;
171 unsigned count;
172 struct objc_class * * data;
173 NXHashState state;
174
175 table = class_hash;
176 count = 0;
177 state = NXInitHashState (table);
178 while (NXNextHashState (table, &state, (void **) &data))
179 printf ("class %d: %s\n", ++count, (*data)->name);
180 }
181
182 /***********************************************************************
183 * classHash.
184 **********************************************************************/
185 static unsigned classHash (void * info,
186 struct objc_class * data)
187 {
188 // Nil classes hash to zero
189 if (!data)
190 return 0;
191
192 // Call through to real hash function
193 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
194 }
195
196 /***********************************************************************
197 * classIsEqual. Returns whether the class names match. If we ever
198 * check more than the name, routines like objc_lookUpClass have to
199 * change as well.
200 **********************************************************************/
201 static int classIsEqual (void * info,
202 struct objc_class * name,
203 struct objc_class * cls)
204 {
205 // Standard string comparison
206 return ((name->name[0] == cls->name[0]) &&
207 (strcmp (name->name, cls->name) == 0));
208 }
209
210 /***********************************************************************
211 * _objc_init_class_hash. Return the class lookup table, create it if
212 * necessary.
213 **********************************************************************/
214 void _objc_init_class_hash (void)
215 {
216 // Do nothing if class hash table already exists
217 if (class_hash)
218 return;
219
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,
226 1024,
227 nil,
228 _objc_create_zone ());
229 }
230
231 /***********************************************************************
232 * objc_getClassList. Return the known classes.
233 **********************************************************************/
234 int objc_getClassList(Class *buffer, int bufferLen) {
235 NXHashState state;
236 struct objc_class * class;
237 int cnt, num;
238
239 OBJC_LOCK(&classLock);
240 num = NXCountHashTable(class_hash);
241 if (NULL == buffer) {
242 OBJC_UNLOCK(&classLock);
243 return num;
244 }
245 cnt = 0;
246 state = NXInitHashState(class_hash);
247 while (cnt < num && NXNextHashState(class_hash, &state, (void **)&class)) {
248 buffer[cnt++] = class;
249 }
250 OBJC_UNLOCK(&classLock);
251 return num;
252 }
253
254 /***********************************************************************
255 * objc_getClasses. Return class lookup table.
256 *
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)
261 {
262 // Return the class lookup hash table
263 return class_hash;
264 }
265
266 /***********************************************************************
267 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
268 **********************************************************************/
269 static int _objc_defaultClassHandler (const char * clsName)
270 {
271 // Return zero so objc_getClass doesn't bother re-searching
272 return 0;
273 }
274
275 /***********************************************************************
276 * objc_setClassHandler. Set objc_classHandler to the specified value.
277 *
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 *))
284 {
285 objc_classHandler = userSuppliedHandler;
286 }
287
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)
296 {
297 struct objc_class cls;
298 id ret;
299
300 // Synchronize access to hash table
301 OBJC_LOCK (&classLock);
302
303 // Check the hash table
304 cls.name = aClassName;
305 ret = (id) NXHashGet (class_hash, &cls);
306 OBJC_UNLOCK (&classLock);
307
308 // If not found, go call objc_classHandler and try again
309 if (!ret && (*objc_classHandler)(aClassName))
310 {
311 OBJC_LOCK (&classLock);
312 ret = (id) NXHashGet (class_hash, &cls);
313 OBJC_UNLOCK (&classLock);
314 }
315
316 return ret;
317 }
318
319 /***********************************************************************
320 * objc_lookUpClass. Return the id of the named class.
321 *
322 * Formerly objc_getClassWithoutWarning ()
323 **********************************************************************/
324 id objc_lookUpClass (const char * aClassName)
325 {
326 struct objc_class cls;
327 id ret;
328
329 // Synchronize access to hash table
330 OBJC_LOCK (&classLock);
331
332 // Check the hash table
333 cls.name = aClassName;
334 ret = (id) NXHashGet (class_hash, &cls);
335
336 // Desynchronize
337 OBJC_UNLOCK (&classLock);
338 return ret;
339 }
340
341 /***********************************************************************
342 * objc_getMetaClass. Return the id of the meta class the named class.
343 **********************************************************************/
344 id objc_getMetaClass (const char * aClassName)
345 {
346 struct objc_class * cls;
347
348 cls = objc_getClass (aClassName);
349 if (!cls)
350 {
351 _objc_inform ("class `%s' not linked into application", aClassName);
352 return Nil;
353 }
354
355 return cls->isa;
356 }
357
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)
363 {
364 // Synchronize access to hash table
365 OBJC_LOCK (&classLock);
366
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)
372 {
373 ((struct objc_class *)cls)->cache = (Cache) &emptyCache;
374 ((struct objc_class *)cls)->info = CLS_CLASS;
375 }
376
377 if (((struct objc_class *)cls)->isa->cache == NULL)
378 {
379 ((struct objc_class *)cls)->isa->cache = (Cache) &emptyCache;
380 ((struct objc_class *)cls)->isa->info = CLS_META;
381 }
382
383 // Add the class to the table
384 (void) NXHashInsert (class_hash, cls);
385
386 // Desynchronize
387 OBJC_UNLOCK (&classLock);
388 }
389
390 /***********************************************************************
391 * _objcTweakMethodListPointerForClass.
392 **********************************************************************/
393 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
394 {
395 struct objc_method_list * originalList;
396 const int initialEntries = 4;
397 int mallocSize;
398 struct objc_method_list ** ptr;
399
400 // Remember existing list
401 originalList = (struct objc_method_list *) cls->methodLists;
402
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);
406
407 // Insert the existing list into the array
408 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
409 ptr[0] = originalList;
410
411 // Replace existing list with array
412 ((struct objc_class *)cls)->methodLists = ptr;
413 ((struct objc_class *)cls)->info |= CLS_METHOD_ARRAY;
414
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);
418 }
419
420 /***********************************************************************
421 * _objc_insertMethods.
422 **********************************************************************/
423 void _objc_insertMethods (struct objc_method_list * mlist,
424 struct objc_method_list *** list)
425 {
426 struct objc_method_list ** ptr;
427 volatile struct objc_method_list ** tempList;
428 int endIndex;
429 int oldSize;
430 int newSize;
431
432 // Locate unused entry for insertion point
433 ptr = *list;
434 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
435 ptr += 1;
436
437 // If array is full, double it
438 if (*ptr == END_OF_METHODS_LIST)
439 {
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
444
445 // Replace existing array with copy twice its size
446 tempList = (struct objc_method_list **) malloc_zone_realloc ((void *) _objc_create_zone (),
447 (void *) *list,
448 (size_t) newSize);
449 *list = tempList;
450
451 // Zero out addition part of new array
452 bzero (&((*list)[endIndex]), newSize - oldSize);
453
454 // Place new end marker
455 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
456
457 // Insertion point corresponds to old array end
458 ptr = &((*list)[endIndex]);
459 }
460
461 // Right shift existing entries by one
462 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
463
464 // Insert at method list at beginning of array
465 **list = mlist;
466 }
467
468 /***********************************************************************
469 * _objc_removeMethods.
470 **********************************************************************/
471 void _objc_removeMethods (struct objc_method_list * mlist,
472 struct objc_method_list *** list)
473 {
474 struct objc_method_list ** ptr;
475
476 // Locate list in the array
477 ptr = *list;
478 while (*ptr != mlist) {
479 // fix for radar # 2538790
480 if ( *ptr == END_OF_METHODS_LIST ) return;
481 ptr += 1;
482 }
483
484 // Remove this entry
485 *ptr = 0;
486
487 // Left shift the following entries
488 while (*(++ptr) != END_OF_METHODS_LIST)
489 *(ptr-1) = *ptr;
490 *(ptr-1) = 0;
491 }
492
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)
498 {
499 // Augment instance methods
500 if (category->instance_methods)
501 _objc_insertMethods (category->instance_methods, &cls->methodLists);
502
503 // Augment class methods
504 if (category->class_methods)
505 _objc_insertMethods (category->class_methods, &cls->isa->methodLists);
506
507 // Augment protocols
508 if ((version >= 5) && category->protocols)
509 {
510 if (cls->isa->version >= 5)
511 {
512 category->protocols->next = cls->protocols;
513 cls->protocols = category->protocols;
514 cls->isa->protocols = category->protocols;
515 }
516 else
517 {
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);
520 }
521 }
522 }
523
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.
527 *
528 **********************************************************************/
529 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
530 {
531 // Install the category's methods into its intended class
532 _objc_add_category (cls, category, version);
533
534 // Flush caches so category's methods can get called
535 _objc_flush_caches (cls);
536 }
537
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)
545 {
546 _objc_unresolved_category * cat;
547 _objc_unresolved_category * next;
548
549 // Nothing to do if there are no categories at all
550 if (!category_hash)
551 return;
552
553 // Locate and remove first element in category list
554 // associated with this class
555 cat = NXMapRemove (category_hash, cls->name);
556
557 // Traverse the list of categories, if any, registered for this class
558 while (cat)
559 {
560 if (cat->bindme) {
561 _objc_bindModuleContainingCategory(cat->cat);
562 }
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);
567
568 // Delink and reclaim this registration
569 next = cat->next;
570 free (cat);
571 cat = next;
572 }
573 }
574
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,
583 long version,
584 int bindme)
585 {
586 _objc_unresolved_category * new_cat;
587 _objc_unresolved_category * old;
588 struct objc_class *theClass;
589
590
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))
598 {
599 if (bindme) {
600 _objc_bindModuleContainingCategory(cat);
601 }
602 _objc_add_category_flush_caches (theClass, cat, version);
603 return;
604 }
605
606 // Create category lookup table if needed
607 if (!category_hash)
608 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
609 128,
610 _objc_create_zone ());
611
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);
615
616 // Register the category to be fixed up later
617 new_cat = malloc_zone_malloc (_objc_create_zone (),
618 sizeof(_objc_unresolved_category));
619 new_cat->next = old;
620 new_cat->cat = cat;
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);
624 }
625
626 /***********************************************************************
627 * _objc_add_categories_from_image.
628 **********************************************************************/
629 static void _objc_add_categories_from_image (header_info * hi)
630 {
631 Module mods;
632 unsigned int midx;
633 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
634
635 // Major loop - process all modules in the header
636 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
637
638 trace(0xb120, hi->mod_count, 0, 0);
639
640 for (midx = 0; midx < hi->mod_count; midx += 1)
641 {
642 unsigned int index;
643 unsigned int total;
644
645 // Nothing to do for a module without a symbol table
646 if (mods[midx].symtab == NULL)
647 continue;
648
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;
653
654
655 trace(0xb123, midx, mods[midx].symtab->cat_def_cnt, 0);
656
657 // Minor loop - register all categories from given module
658 for (index = mods[midx].symtab->cls_def_cnt; index < total; index += 1)
659 {
660 _objc_register_category(mods[midx].symtab->defs[index], mods[midx].version, isDynamic);
661 }
662
663 trace(0xb124, midx, 0, 0);
664 }
665
666 trace(0xb12f, 0, 0, 0);
667 }
668
669 /***********************************************************************
670 * _headerForClass.
671 **********************************************************************/
672 static const header_info * _headerForClass (struct objc_class * cls)
673 {
674 const struct segment_command * objcSeg;
675 unsigned int size;
676 unsigned long vmaddrPlus;
677 header_info * hInfo;
678
679 // Check all headers in the vector
680 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
681 {
682 // Locate header data, if any
683 objcSeg = _getObjcHeaderData ((headerType *) hInfo->mhdr, &size);
684 if (!objcSeg)
685 continue;
686
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)))
691 return hInfo;
692 }
693
694 // Not found
695 return 0;
696 }
697
698 /***********************************************************************
699 * _nameForHeader.
700 **********************************************************************/
701 const char * _nameForHeader (const headerType * header)
702 {
703 return _getObjcHeaderName ((headerType *) header);
704 }
705
706 /***********************************************************************
707 * checkForPendingClassReferences. Complete any fixups registered for
708 * this class.
709 **********************************************************************/
710 static void _objc_checkForPendingClassReferences (struct objc_class * cls)
711 {
712 PendingClass * pending;
713
714 // Nothing to do if there are no pending classes
715 if (!pendingClassRefsMap)
716 return;
717
718 // Get pending list for this class
719 pending = NXMapGet (pendingClassRefsMap, cls->name);
720 if (!pending)
721 return;
722
723 // Remove the list from the table
724 (void) NXMapRemove (pendingClassRefsMap, cls->name);
725
726 // Process all elements in the list
727 while (pending)
728 {
729 PendingClass * next;
730
731 // Remember follower for loop
732 next = pending->next;
733
734 // Fill in a pointer to Class
735 // (satisfies caller of objc_pendClassReference)
736 if (pending->ref)
737 *pending->ref = objc_getClass (cls->name);
738
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)
745 {
746 struct objc_class * fixCls;
747
748 // Locate the Class to be fixed up
749 fixCls = pending->classToSetUp;
750
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;
754
755 // Fix up class pointers, version, and cache pointers
756 _class_install_relationships (fixCls, pending->version);
757 }
758
759 // Reclaim the element
760 free (pending);
761
762 // Move on
763 pending = next;
764 }
765 }
766
767 /***********************************************************************
768 * newPending. Allocate and zero a PendingClass structure.
769 **********************************************************************/
770 static inline PendingClass * newPending (void)
771 {
772 PendingClass * pending;
773
774 pending = (PendingClass *) malloc_zone_calloc (_objc_create_zone (), 1, sizeof(PendingClass));
775
776 return pending;
777 }
778
779 /***********************************************************************
780 * pendingClassRefsMapTable. Return a pointer to the lookup table for
781 * pending classes.
782 **********************************************************************/
783 static inline NXMapTable * pendingClassRefsMapTable (void)
784 {
785 // Allocate table if needed
786 if (!pendingClassRefsMap)
787 pendingClassRefsMap = NXCreateMapTableFromZone (NXStrValueMapPrototype, 10, _objc_create_zone ());
788
789 // Return table pointer
790 return pendingClassRefsMap;
791 }
792
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
796 * name.
797 **********************************************************************/
798 void objc_pendClassReference (const char * className,
799 struct objc_class * * ref)
800 {
801 NXMapTable * table;
802 PendingClass * pending;
803
804 // Create and/or locate pending class lookup table
805 table = pendingClassRefsMapTable ();
806
807 // Create entry containing the class reference
808 pending = newPending ();
809 pending->ref = ref;
810
811 // Link new entry into head of list of entries for this class
812 pending->next = NXMapGet (pendingClassRefsMap, className);
813
814 // (Re)place entry list in the table
815 (void) NXMapInsert (table, className, pending);
816 }
817
818 /***********************************************************************
819 * objc_pendClassInstallation. Register the specified class to have its
820 * super class pointers filled in later because the superclass is not
821 * yet found.
822 **********************************************************************/
823 void objc_pendClassInstallation (struct objc_class *cls, int version)
824 {
825 NXMapTable * table;
826 PendingClass * pending;
827
828 // Create and/or locate pending class lookup table
829 table = pendingClassRefsMapTable ();
830
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;
836
837 // Link new entry into head of list of entries for this class
838 pending->next = NXMapGet (pendingClassRefsMap, cls->super_class);
839
840 // (Re)place entry list in the table
841 (void) NXMapInsert (table, cls->super_class, pending);
842 }
843
844 /***********************************************************************
845 * _objc_add_classes_from_image. Install all classes contained in the
846 * specified image.
847 **********************************************************************/
848 static void _objc_add_classes_from_image(NXHashTable *clsHash, header_info *hi)
849 {
850 unsigned int index;
851 unsigned int midx;
852 Module mods;
853 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
854
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)
858 {
859 // Skip module containing no classes
860 if (mods[midx].symtab == NULL)
861 continue;
862
863 // Minor loop - process all the classes in given module
864 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
865 {
866 struct objc_class * oldCls;
867 struct objc_class * newCls;
868
869 // Locate the class description pointer
870 newCls = mods[midx].symtab->defs[index];
871
872 // remember to bind the module on initialization
873 if (isDynamic)
874 newCls->info |= CLS_NEED_BIND ;
875
876 // Convert old style method list to the new style
877 _objcTweakMethodListPointerForClass (newCls);
878
879 oldCls = NXHashInsert (clsHash, newCls);
880
881 // Non-Nil oldCls is a class that NXHashInsert just
882 // bumped from table because it has the same name
883 // as newCls
884 if (oldCls)
885 {
886 const header_info * oldHeader;
887 const header_info * newHeader;
888 const char * oldName;
889 const char * newName;
890
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);
899
900 // Use the chosen class
901 // NOTE: Isn't this a NOP?
902 newCls = objc_lookUpClass (oldCls->name);
903 }
904
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;
909
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!!
914
915 // we defer this work until the class is initialized.
916 //_objc_resolve_categories_for_class (newCls);
917
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);
925
926 }
927 }
928 }
929
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)
935 {
936 unsigned int size;
937 OBJC_CONSTANT_STRING_PTR section;
938 struct objc_class * constantStringClass;
939 unsigned int index;
940
941 // Locate section holding string objects
942 section = _getObjcStringObjects ((headerType *) hi->mhdr, &size);
943 if (!section || !size)
944 return;
945 section = (OBJC_CONSTANT_STRING_PTR) ((unsigned long) section + hi->image_slide);
946
947 // Luckily NXConstantString is the same size as NSConstantString
948 constantStringClass = objc_getClass ("NSConstantString");
949
950 // Process each string object in the section
951 for (index = 0; index < size; index += 1)
952 {
953 struct objc_class * * isaptr;
954
955 isaptr = (struct objc_class * *) OBJC_CONSTANT_STRING_DEREF section[index];
956 if (*isaptr == 0)
957 *isaptr = constantStringClass;
958 }
959 }
960
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)
968 {
969 struct objc_class * * cls_refs;
970 unsigned int size;
971 unsigned int index;
972
973 // Locate class refs in image
974 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
975 if (!cls_refs)
976 return;
977 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
978
979 // Process each class ref
980 for (index = 0; index < size; index += 1)
981 {
982 const char * ref;
983 struct objc_class * cls;
984
985 // Get ref to convert from name string to class pointer
986 ref = (const char *) cls_refs[index];
987
988 // Get pointer to class of this name
989 cls = (struct objc_class *)objc_lookUpClass (ref);
990
991 // If class isn't there yet, use pending mechanism
992 if (!cls)
993 {
994 // Register this ref to be set later
995 objc_pendClassReference (ref, &cls_refs[index]);
996
997 // Use place-holder class
998 cls_refs[index] = _objc_getNonexistentClass ();
999 }
1000
1001 // Replace name string pointer with class pointer
1002 else
1003 cls_refs[index] = cls;
1004 }
1005 }
1006
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)
1013 {
1014 unsigned int index;
1015
1016 // Process each selector
1017 for (index = 0; index < cnt; index += 1)
1018 {
1019 SEL sel;
1020
1021 // Lookup pointer to uniqued string
1022 sel = sel_registerNameNoCopy ((const char *) sels[index]);
1023
1024 // Replace this selector with uniqued one (avoid
1025 // modifying the VM page if this would be a NOP)
1026 if (sels[index] != sel)
1027 sels[index] = sel;
1028 }
1029 }
1030
1031
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)
1037 {
1038 unsigned int index;
1039
1040 // Process each method
1041 for (index = 0; index < methods->count; index += 1)
1042 {
1043 struct objc_method_description * method;
1044 SEL sel;
1045
1046 // Get method entry to fix up
1047 method = &methods->list[index];
1048
1049 // Lookup pointer to uniqued string
1050 sel = sel_registerNameNoCopy ((const char *) method->name);
1051
1052 // Replace this selector with uniqued one (avoid
1053 // modifying the VM page if this would be a NOP)
1054 if (method->name != sel)
1055 method->name = sel;
1056 }
1057 }
1058
1059 /***********************************************************************
1060 * _fixup.
1061 **********************************************************************/
1062 @interface Protocol(RuntimePrivate)
1063 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
1064 @end
1065
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)
1071 {
1072 unsigned int size;
1073 OBJC_PROTOCOL_PTR protos;
1074 unsigned int index;
1075
1076 // Locate protocals in the image
1077 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
1078 if (!protos)
1079 return;
1080
1081 // Apply the slide bias
1082 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
1083
1084 // Process each protocol
1085 for (index = 0; index < size; index += 1)
1086 {
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);
1090
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);
1094 }
1095
1096 // Invoke Protocol class method to fix up the protocol
1097 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
1098 }
1099
1100 /***********************************************************************
1101 * _objc_headerStart. Return what headers we know about.
1102 **********************************************************************/
1103 header_info * _objc_headerStart ()
1104 {
1105
1106 // Take advatage of our previous work
1107 return FirstHeader;
1108 }
1109
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.
1113 */
1114 }
1115
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)
1119 * Radar 2701686
1120 ***********************************************************************/
1121 static void _objc_bind_symbol(const char *name)
1122 {
1123 int i;
1124 static header_info *lastHeader = NULL;
1125 header_info *hInfo;
1126 const headerType *imageHeader = lastHeader ? lastHeader->mhdr : NULL;
1127
1128 // Ideally we would have a way to not even process a symbol in a module
1129 // we've already visited
1130
1131
1132 // First assume there is some locality and search where we last found a symbol
1133 if ( imageHeader
1134 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1135 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1136 {
1137 // Found
1138 return;
1139 }
1140
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)
1144 {
1145 imageHeader = hInfo->mhdr;
1146 if ( hInfo != lastHeader
1147 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1148 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1149 {
1150 // found
1151 lastHeader = hInfo;
1152 return;
1153 }
1154 }
1155 // die now, or later ??
1156 // _objc_fatal("could not find %s", name);
1157 }
1158
1159 /***********************************************************************
1160 * _objc_bindModuleContainingCategory. Bind the module containing the
1161 * category.
1162 **********************************************************************/
1163 static void _objc_bindModuleContainingCategory (Category cat)
1164 {
1165 char * class_name;
1166 char * category_name;
1167 char * name;
1168 char tmp_buf[128];
1169 unsigned int name_len;
1170
1171 // Bind ".objc_category_name_<classname>_<categoryname>",
1172 // where <classname> is the class name with the leading
1173 // '%'s stripped.
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);
1179 else
1180 name = tmp_buf;
1181 while (*class_name == '%')
1182 class_name += 1;
1183 strcpy (name, ".objc_category_name_");
1184 strcat (name, class_name);
1185 strcat (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 )
1190 free(name);
1191 }
1192
1193 /***********************************************************************
1194 * _objc_bindModuleContainingClass. Bind the module containing the
1195 * class.
1196 * This is done lazily, just after initializing the class (if needed)
1197 **********************************************************************/
1198
1199 void _objc_bindModuleContainingClass (struct objc_class * cls) {
1200 char * name;
1201 const char * class_name;
1202 char tmp_buf[128];
1203 unsigned int name_len;
1204
1205 // Use the real class behind the poser
1206 if (CLS_GETINFO (cls, CLS_POSING))
1207 cls = getOriginalClassForPosingClass (cls);
1208 class_name = cls->name;
1209
1210 name_len = strlen(class_name) + 20;
1211 if ( name_len > 128 )
1212 name = malloc(name_len);
1213 else
1214 name = tmp_buf;
1215
1216 while (*class_name == '%')
1217 class_name += 1;
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 )
1223 free(name);
1224 }
1225
1226
1227 /***********************************************************************
1228 * _objc_addHeader.
1229 *
1230 **********************************************************************/
1231
1232 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
1233 #define HINFO_SIZE 16
1234
1235 static int HeaderInfoCounter = 0;
1236 static header_info HeaderInfoTable[HINFO_SIZE] = { {0} };
1237
1238 static header_info * _objc_addHeader(const headerType *header, unsigned long vmaddr_slide)
1239 {
1240 int mod_count;
1241 Module mod_ptr = _getObjcModules ((headerType *) header, &mod_count);
1242 header_info *result;
1243
1244 // if there is no objc data - ignore this entry!
1245 if (mod_ptr == NULL) {
1246 return NULL;
1247 }
1248
1249 if (HeaderInfoCounter < HINFO_SIZE) {
1250 // avoid mallocs for the common case
1251 result = &HeaderInfoTable[HeaderInfoCounter++];
1252 }
1253 else {
1254 result = malloc_zone_malloc(_objc_create_zone(), sizeof(header_info));
1255 }
1256
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;
1262
1263 // chain it on
1264 // (a simple lock here would go a long way towards thread safety)
1265 result->next = FirstHeader;
1266 FirstHeader = result;
1267
1268 return result;
1269 }
1270
1271 /**********************************************************************
1272 * _objc_fatalHeader
1273 *
1274 * If we have it we're in trouble
1275 **************************************************************************/
1276 void _objc_fatalHeader(const headerType *header)
1277 {
1278 header_info *hInfo;
1279
1280 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next) {
1281 if (hInfo->mhdr == header) {
1282 _objc_fatal("cannot unmap an image containing ObjC data");
1283 }
1284 }
1285 }
1286
1287 /***********************************************************************
1288 * libraryNameForMachHeader.
1289 **********************************************************************/
1290 static const char * libraryNameForMachHeader (const headerType * themh)
1291 {
1292 unsigned long index;
1293 unsigned long imageCount;
1294 headerType * mh;
1295
1296 // Search images for matching type
1297 imageCount = _dyld_image_count ();
1298 for (index = 0; index < imageCount ; index += 1)
1299 {
1300 // Return name of image with matching type
1301 mh = _dyld_get_image_header (index);
1302 if (mh == themh)
1303 return _dyld_get_image_name (index);
1304 }
1305
1306 // Not found
1307 return 0;
1308 }
1309
1310 /***********************************************************************
1311 * _objc_fixup_selector_refs. Register all of the selectors in each
1312 * image, and fix them all up.
1313 *
1314 **********************************************************************/
1315 static void _objc_fixup_selector_refs (const header_info * hi)
1316 {
1317 unsigned int midx;
1318 unsigned int size;
1319 OBJC_PROTOCOL_PTR protos;
1320 Module mods;
1321 unsigned int index;
1322 SEL * messages_refs;
1323
1324 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
1325
1326 // Fix up message refs
1327 messages_refs = (SEL *) _getObjcMessageRefs ((headerType *) hi->mhdr, &size);
1328 if (messages_refs)
1329 {
1330 messages_refs = (SEL *) ((unsigned long) messages_refs + hi->image_slide);
1331 map_selrefs (messages_refs, size);
1332 }
1333 }
1334
1335
1336 /***********************************************************************
1337 * _objc_call_loads_for_image.
1338 **********************************************************************/
1339 static void _objc_call_loads_for_image (header_info * header)
1340 {
1341 struct objc_class * cls;
1342 struct objc_class * * pClass;
1343 Category * pCategory;
1344 IMP load_method;
1345 unsigned int nModules;
1346 unsigned int nClasses;
1347 unsigned int nCategories;
1348 struct objc_symtab * symtab;
1349 struct objc_module * module;
1350
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)
1354 {
1355 symtab = module->symtab;
1356 if (symtab == NULL)
1357 continue;
1358
1359 // Minor loop - call the +load from each class in the given module
1360 for (nClasses = symtab->cls_def_cnt, pClass = (Class *) symtab->defs;
1361 nClasses;
1362 nClasses -= 1, pClass += 1)
1363 {
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)
1368 {
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");
1372 if (load_method) {
1373 if (cls->info & CLS_NEED_BIND) {
1374 cls->info &= ~CLS_NEED_BIND;
1375 _objc_bindModuleContainingClass(cls);
1376 }
1377 (*load_method) ((id) cls, @selector(load));
1378 }
1379 }
1380 }
1381
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];
1386 nCategories;
1387 nCategories -= 1, pCategory += 1)
1388 {
1389 struct objc_method_list * methods;
1390
1391 methods = (*pCategory)->class_methods;
1392 if (methods)
1393 {
1394 load_method = class_lookupNamedMethodInMethodList (methods, "load");
1395 if (load_method) {
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));
1404 }
1405 }
1406 }
1407 }
1408 }
1409
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;
1417 }
1418 }
1419 /***********************************************************************
1420 * objc_setMultithreaded.
1421 **********************************************************************/
1422 void objc_setMultithreaded (BOOL flag)
1423 {
1424 if (flag == YES)
1425 _objc_multithread_mask = 0;
1426 else
1427 _objc_multithread_mask = (-1);
1428 }
1429 /***********************************************************************
1430 * _objcInit.
1431 * Library initializer called by dyld & from crt0
1432 **********************************************************************/
1433
1434 void _objcInit(void) {
1435 header_info *hInfo;
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
1439
1440 /* Protect against multiple invocations, as all library
1441 * initializers should. */
1442 if (0 != _done) return;
1443 _done = 1;
1444
1445 ptrace(0xb000, 0, 0, 0);
1446 trace(0xb000, 0, 0, 0);
1447
1448 // make sure CF is initialized before we go further;
1449 // someday this can be removed, as it'll probably be automatic
1450 __CFInitialize();
1451
1452 // Create the class lookup table
1453 _objc_init_class_hash ();
1454
1455 trace(0xb001, 0, 0, 0);
1456
1457 objc_setConfiguration(); // Get our configuration
1458
1459 trace(0xb003, 0, 0, 0);
1460
1461 // a pre-cheetah comment:
1462 // XXXXX BEFORE HERE *NO* PAGES ARE STOMPED ON;
1463
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.
1467
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.
1473
1474 // So we tell the map_image dyld callback to not do this part...
1475
1476 Postpone_install_relationships = 1;
1477
1478 // register for unmapping first so we can't miss any during load attempts
1479 _dyld_register_func_for_remove_image (&_objc_unmap_image);
1480
1481 // finally, register for images
1482 _dyld_register_func_for_add_image (&_objc_map_image);
1483
1484 // a pre-cheetah comment:
1485 // XXXXX BEFORE HERE *ALL* PAGES ARE STOMPED ON
1486
1487 Postpone_install_relationships = 0;
1488
1489 trace(0xb006, 0, 0, 0);
1490
1491 // Install relations on classes that were found
1492 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1493 {
1494 int nModules;
1495 int index;
1496 struct objc_module * module;
1497 struct objc_class * cls;
1498
1499 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1500 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1501 {
1502 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1503 {
1504 cls = (struct objc_class *) module->symtab->defs[index];
1505 _class_install_relationships (cls, module->version);
1506 }
1507
1508 module += 1;
1509 }
1510
1511 trace(0xb007, hInfo, hInfo->mod_count, 0);
1512
1513 }
1514
1515 trace(0xb008, 0, 0, 0);
1516
1517 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1518 {
1519 // Initialize the isa pointers of all NXConstantString objects
1520 (void)_objc_fixup_string_objects_for_image (hInfo);
1521
1522 // Convert class refs from name pointers to ids
1523 (void)_objc_map_class_refs_for_image (hInfo);
1524 }
1525
1526 trace(0xb00a, 0, 0, 0);
1527
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);
1532
1533 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1534 _objc_call_loads_for_image (hInfo);
1535
1536 ptrace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1537 trace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1538 }
1539
1540
1541 /***********************************************************************
1542 * _objc_map_image.
1543 **********************************************************************/
1544 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide)
1545 {
1546 static int dumpClasses = -1;
1547 header_info *hInfo;
1548 unsigned int size;
1549
1550 if ( dumpClasses == -1 ) {
1551 if ( getenv("OBJC_DUMP_CLASSES") ) dumpClasses = 1;
1552 else dumpClasses = 0;
1553 }
1554
1555 trace(0xb100, 0, 0, 0);
1556
1557 // Add this header to the chain
1558 hInfo = _objc_addHeader (mh, vmaddr_slide);
1559
1560 if (!hInfo) return;
1561
1562 if (LaunchingDebug) { _objc_syslog("objc_map_image for %s\n", _nameForHeader(mh)); }
1563
1564 trace(0xb101, 0, 0, 0);
1565
1566 // Register any categories and/or classes and/or selectors this image contains
1567 _objc_add_categories_from_image (hInfo);
1568
1569 trace(0xb103, 0, 0, 0);
1570
1571 _objc_add_classes_from_image (class_hash, hInfo);
1572
1573 trace(0xb104, 0, 0, 0);
1574
1575 _objc_fixup_selector_refs (hInfo);
1576
1577 trace(0xb105, 0, 0, 0);
1578
1579 // Log all known class names, if asked
1580 if ( dumpClasses )
1581 {
1582 printf ("classes...\n");
1583 objc_dump_class_hash ();
1584 }
1585
1586 if (!Postpone_install_relationships)
1587 {
1588 int nModules;
1589 int index;
1590 struct objc_module * module;
1591
1592 // Major loop - process each module
1593 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1594
1595 trace(0xb106, hInfo->mod_count, 0, 0);
1596
1597 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1598 {
1599 // Minor loop - process each class in a given module
1600 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1601 {
1602 struct objc_class * cls;
1603
1604 // Locate the class description
1605 cls = (struct objc_class *) module->symtab->defs[index];
1606
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))
1610 {
1611 _class_install_relationships (cls, module->version);
1612 if (callbackFunction)
1613 (*callbackFunction) (cls, 0);
1614 }
1615 else
1616 {
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 ();
1622 }
1623 }
1624
1625 // Move on
1626 module += 1;
1627 }
1628
1629 trace(0xb108, 0, 0, 0);
1630
1631 // Initialize the isa pointers of all NXConstantString objects
1632 _objc_fixup_string_objects_for_image (hInfo);
1633
1634 trace(0xb109, 0, 0, 0);
1635
1636 // Convert class refs from name pointers to ids
1637 _objc_map_class_refs_for_image (hInfo);
1638
1639 trace(0xb10a, 0, 0, 0);
1640
1641 // Selectorize the method names and +_fixup each of
1642 // protocols in the image
1643 _objc_fixup_protocol_objects_for_image (hInfo);
1644
1645 trace(0xb10b, 0, 0, 0);
1646
1647 // Call +load on all classes and categorized classes
1648 _objc_call_loads_for_image (hInfo);
1649
1650 trace(0xb10c, 0, 0, 0);
1651 }
1652
1653 trace(0xb10f, 0, 0, 0);
1654 }
1655
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);
1663 }
1664
1665 /***********************************************************************
1666 * objc_setNilObjectMsgHandler.
1667 **********************************************************************/
1668 void objc_setNilObjectMsgHandler (NilObjectMsgCallback nilObjMsgCallback)
1669 {
1670 _objc_msgNil = nilObjMsgCallback;
1671 }
1672
1673 /***********************************************************************
1674 * objc_getNilObjectMsgHandler.
1675 **********************************************************************/
1676 NilObjectMsgCallback objc_getNilObjectMsgHandler (void)
1677 {
1678 return _objc_msgNil;
1679 }
1680
1681