]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-runtime.m
objc4-222.tar.gz
[apple/objc4.git] / runtime / objc-runtime.m
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * 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 // Function to call when message sent to nil object.
91 void (*_objc_msgNil)(id, SEL) = NULL;
92
93 // Function called after class has been fixed up (MACH only)
94 void (*callbackFunction)(Class, const char *) = 0;
95
96 // Prototype for function passed to
97 typedef void (*NilObjectMsgCallback) (id nilObject, SEL selector);
98
99 // Lock for class hashtable
100 OBJC_DECLARE_LOCK (classLock);
101
102 // Condition for logging load progress
103 static int LaunchingDebug = -1;
104
105 // objc's key for pthread_getspecific
106 pthread_key_t _objc_pthread_key;
107
108 /***********************************************************************
109 * Function prototypes internal to this module.
110 **********************************************************************/
111
112 static unsigned classHash (void * info, struct objc_class * data);
113 static int classIsEqual (void * info, struct objc_class * name, struct objc_class * cls);
114 static int _objc_defaultClassHandler (const char * clsName);
115 static void _objcTweakMethodListPointerForClass (struct objc_class * cls);
116 static void _objc_add_category_flush_caches(struct objc_class * cls, struct objc_category * category, int version);
117 static void _objc_add_category(struct objc_class * cls, struct objc_category * category, int version);
118 static void _objc_register_category (struct objc_category * cat, long version, int bindme);
119 static void _objc_add_categories_from_image (header_info * hi);
120 static const header_info * _headerForClass (struct objc_class * cls);
121 static PendingClass * newPending (void);
122 static NXMapTable * pendingClassRefsMapTable (void);
123 static void _objc_add_classes_from_image (NXHashTable * clsHash, header_info * hi);
124 static void _objc_fixup_string_objects_for_image(header_info * hi);
125 static void _objc_map_class_refs_for_image (header_info * hi);
126 static void map_selrefs (SEL * sels, unsigned int cnt);
127 static void map_method_descs (struct objc_method_description_list * methods);
128 static void _objc_fixup_protocol_objects_for_image (header_info * hi);
129 static void _objc_bindModuleContainingCategory(Category cat);
130 static void _objc_fixup_selector_refs (const header_info * hi);
131 static void _objc_call_loads_for_image (header_info * header);
132 static void _objc_checkForPendingClassReferences (struct objc_class * cls);
133 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide);
134 static void _objc_unmap_image(headerType *mh, unsigned long vmaddr_slide);
135
136 /***********************************************************************
137 * Static data internal to this module.
138 **********************************************************************/
139
140 // we keep a linked list of header_info's describing each image as told to us by dyld
141 static header_info * FirstHeader = 0;
142
143 // Hash table of classes
144 static NXHashTable * class_hash = 0;
145 static NXHashTablePrototype classHashPrototype =
146 {
147 (unsigned (*) (const void *, const void *)) classHash,
148 (int (*)(const void *, const void *, const void *)) classIsEqual,
149 NXNoEffectFree, 0
150 };
151
152 // Exported copy of class_hash variable (hook for debugging tools)
153 NXHashTable *_objc_debug_class_hash = NULL;
154
155 // Function pointer objc_getClass calls through when class is not found
156 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
157
158 // Category and class registries
159 static NXMapTable * category_hash = NULL;
160
161
162 static int Postpone_install_relationships = 0;
163
164 static NXMapTable * pendingClassRefsMap = 0;
165
166 /***********************************************************************
167 * objc_dump_class_hash. Log names of all known classes.
168 **********************************************************************/
169 void objc_dump_class_hash (void)
170 {
171 NXHashTable * table;
172 unsigned count;
173 struct objc_class * data;
174 NXHashState state;
175
176 table = class_hash;
177 count = 0;
178 state = NXInitHashState (table);
179 while (NXNextHashState (table, &state, (void **) &data))
180 printf ("class %d: %s\n", ++count, data->name);
181 }
182
183 /***********************************************************************
184 * classHash.
185 **********************************************************************/
186 static unsigned classHash (void * info,
187 struct objc_class * data)
188 {
189 // Nil classes hash to zero
190 if (!data)
191 return 0;
192
193 // Call through to real hash function
194 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
195 }
196
197 /***********************************************************************
198 * classIsEqual. Returns whether the class names match. If we ever
199 * check more than the name, routines like objc_lookUpClass have to
200 * change as well.
201 **********************************************************************/
202 static int classIsEqual (void * info,
203 struct objc_class * name,
204 struct objc_class * cls)
205 {
206 // Standard string comparison
207 return ((name->name[0] == cls->name[0]) &&
208 (strcmp (name->name, cls->name) == 0));
209 }
210
211 /***********************************************************************
212 * _objc_init_class_hash. Return the class lookup table, create it if
213 * necessary.
214 **********************************************************************/
215 void _objc_init_class_hash (void)
216 {
217 // Do nothing if class hash table already exists
218 if (class_hash)
219 return;
220
221 // Provide a generous initial capacity to cut down on rehashes
222 // at launch time. A smallish Foundation+AppKit program will have
223 // about 520 classes. Larger apps (like IB or WOB) have more like
224 // 800 classes. Some customers have massive quantities of classes.
225 // Foundation-only programs aren't likely to notice the ~6K loss.
226 class_hash = NXCreateHashTableFromZone (classHashPrototype,
227 1024,
228 nil,
229 _objc_create_zone ());
230 _objc_debug_class_hash = class_hash;
231 }
232
233 /***********************************************************************
234 * objc_getClassList. Return the known classes.
235 **********************************************************************/
236 int objc_getClassList(Class *buffer, int bufferLen) {
237 NXHashState state;
238 struct objc_class * class;
239 int cnt, num;
240
241 OBJC_LOCK(&classLock);
242 num = NXCountHashTable(class_hash);
243 if (NULL == buffer) {
244 OBJC_UNLOCK(&classLock);
245 return num;
246 }
247 cnt = 0;
248 state = NXInitHashState(class_hash);
249 while (cnt < num && NXNextHashState(class_hash, &state, (void **)&class)) {
250 buffer[cnt++] = class;
251 }
252 OBJC_UNLOCK(&classLock);
253 return num;
254 }
255
256 /***********************************************************************
257 * objc_getClasses. Return class lookup table.
258 *
259 * NOTE: This function is very dangerous, since you cannot safely use
260 * the hashtable without locking it, and the lock is private!
261 **********************************************************************/
262 void * objc_getClasses (void)
263 {
264 // Return the class lookup hash table
265 return class_hash;
266 }
267
268 /***********************************************************************
269 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
270 **********************************************************************/
271 static int _objc_defaultClassHandler (const char * clsName)
272 {
273 // Return zero so objc_getClass doesn't bother re-searching
274 return 0;
275 }
276
277 /***********************************************************************
278 * objc_setClassHandler. Set objc_classHandler to the specified value.
279 *
280 * NOTE: This should probably deal with userSuppliedHandler being NULL,
281 * because the objc_classHandler caller does not check... it would bus
282 * error. It would make sense to handle NULL by restoring the default
283 * handler. Is anyone hacking with this, though?
284 **********************************************************************/
285 void objc_setClassHandler (int (*userSuppliedHandler) (const char *))
286 {
287 objc_classHandler = userSuppliedHandler;
288 }
289
290 /***********************************************************************
291 * objc_getClass. Return the id of the named class. If the class does
292 * not exist, call the objc_classHandler routine with the class name.
293 * If the objc_classHandler returns a non-zero value, try once more to
294 * find the class. Default objc_classHandler always returns zero.
295 * objc_setClassHandler is how someone can install a non-default routine.
296 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
297 **********************************************************************/
298 id objc_getClass (const char * aClassName)
299 {
300 struct objc_class cls;
301 id ret;
302
303 // Synchronize access to hash table
304 OBJC_LOCK (&classLock);
305
306 // Check the hash table
307 cls.name = aClassName;
308 ret = (id) NXHashGet (class_hash, &cls);
309 OBJC_UNLOCK (&classLock);
310
311 // If not found, go call objc_classHandler and try again
312 if (!ret && (*objc_classHandler)(aClassName))
313 {
314 OBJC_LOCK (&classLock);
315 ret = (id) NXHashGet (class_hash, &cls);
316 OBJC_UNLOCK (&classLock);
317 }
318
319 return ret;
320 }
321
322 /***********************************************************************
323 * objc_lookUpClass. Return the id of the named class.
324 *
325 * Formerly objc_getClassWithoutWarning ()
326 **********************************************************************/
327 id objc_lookUpClass (const char * aClassName)
328 {
329 struct objc_class cls;
330 id ret;
331
332 // Synchronize access to hash table
333 OBJC_LOCK (&classLock);
334
335 // Check the hash table
336 cls.name = aClassName;
337 ret = (id) NXHashGet (class_hash, &cls);
338
339 // Desynchronize
340 OBJC_UNLOCK (&classLock);
341 return ret;
342 }
343
344 /***********************************************************************
345 * objc_getMetaClass. Return the id of the meta class the named class.
346 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
347 **********************************************************************/
348 id objc_getMetaClass (const char * aClassName)
349 {
350 struct objc_class * cls;
351
352 cls = objc_getClass (aClassName);
353 if (!cls)
354 {
355 _objc_inform ("class `%s' not linked into application", aClassName);
356 return Nil;
357 }
358
359 return cls->isa;
360 }
361
362 /***********************************************************************
363 * objc_addClass. Add the specified class to the table of known classes,
364 * after doing a little verification and fixup.
365 **********************************************************************/
366 void objc_addClass (Class cls)
367 {
368 // Synchronize access to hash table
369 OBJC_LOCK (&classLock);
370
371 // Make sure both the class and the metaclass have caches!
372 // Clear all bits of the info fields except CLS_CLASS and CLS_META.
373 // Normally these bits are already clear but if someone tries to cons
374 // up their own class on the fly they might need to be cleared.
375 if (((struct objc_class *)cls)->cache == NULL)
376 {
377 ((struct objc_class *)cls)->cache = (Cache) &emptyCache;
378 ((struct objc_class *)cls)->info = CLS_CLASS;
379 }
380
381 if (((struct objc_class *)cls)->isa->cache == NULL)
382 {
383 ((struct objc_class *)cls)->isa->cache = (Cache) &emptyCache;
384 ((struct objc_class *)cls)->isa->info = CLS_META;
385 }
386
387 // Add the class to the table
388 (void) NXHashInsert (class_hash, cls);
389
390 // Desynchronize
391 OBJC_UNLOCK (&classLock);
392 }
393
394 /***********************************************************************
395 * _objcTweakMethodListPointerForClass.
396 **********************************************************************/
397 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
398 {
399 struct objc_method_list * originalList;
400 const int initialEntries = 4;
401 int mallocSize;
402 struct objc_method_list ** ptr;
403
404 // Remember existing list
405 originalList = (struct objc_method_list *) cls->methodLists;
406
407 // Allocate and zero a method list array
408 mallocSize = sizeof(struct objc_method_list *) * initialEntries;
409 ptr = (struct objc_method_list **) malloc_zone_calloc (_objc_create_zone (), 1, mallocSize);
410
411 // Insert the existing list into the array
412 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
413 ptr[0] = originalList;
414
415 // Replace existing list with array
416 ((struct objc_class *)cls)->methodLists = ptr;
417 ((struct objc_class *)cls)->info |= CLS_METHOD_ARRAY;
418
419 // Do the same thing to the meta-class
420 if (((((struct objc_class *)cls)->info & CLS_CLASS) != 0) && cls->isa)
421 _objcTweakMethodListPointerForClass (cls->isa);
422 }
423
424 /***********************************************************************
425 * _objc_insertMethods.
426 **********************************************************************/
427 void _objc_insertMethods (struct objc_method_list * mlist,
428 struct objc_method_list *** list)
429 {
430 struct objc_method_list ** ptr;
431 volatile struct objc_method_list ** tempList;
432 int endIndex;
433 int oldSize;
434 int newSize;
435
436 // Locate unused entry for insertion point
437 ptr = *list;
438 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
439 ptr += 1;
440
441 // If array is full, double it
442 if (*ptr == END_OF_METHODS_LIST)
443 {
444 // Calculate old and new dimensions
445 endIndex = ptr - *list;
446 oldSize = (endIndex + 1) * sizeof(void *);
447 newSize = oldSize + sizeof(struct objc_method_list *); // only increase by 1
448
449 // Replace existing array with copy twice its size
450 tempList = (struct objc_method_list **) malloc_zone_realloc ((void *) _objc_create_zone (),
451 (void *) *list,
452 (size_t) newSize);
453 *list = tempList;
454
455 // Zero out addition part of new array
456 bzero (&((*list)[endIndex]), newSize - oldSize);
457
458 // Place new end marker
459 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
460
461 // Insertion point corresponds to old array end
462 ptr = &((*list)[endIndex]);
463 }
464
465 // Right shift existing entries by one
466 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
467
468 // Insert at method list at beginning of array
469 **list = mlist;
470 }
471
472 /***********************************************************************
473 * _objc_removeMethods.
474 **********************************************************************/
475 void _objc_removeMethods (struct objc_method_list * mlist,
476 struct objc_method_list *** list)
477 {
478 struct objc_method_list ** ptr;
479
480 // Locate list in the array
481 ptr = *list;
482 while (*ptr != mlist) {
483 // fix for radar # 2538790
484 if ( *ptr == END_OF_METHODS_LIST ) return;
485 ptr += 1;
486 }
487
488 // Remove this entry
489 *ptr = 0;
490
491 // Left shift the following entries
492 while (*(++ptr) != END_OF_METHODS_LIST)
493 *(ptr-1) = *ptr;
494 *(ptr-1) = 0;
495 }
496
497 /***********************************************************************
498 * _objc_add_category. Install the specified category's methods and
499 * protocols into the class it augments.
500 **********************************************************************/
501 static inline void _objc_add_category(struct objc_class *cls, struct objc_category *category, int version)
502 {
503 // Augment instance methods
504 if (category->instance_methods)
505 _objc_insertMethods (category->instance_methods, &cls->methodLists);
506
507 // Augment class methods
508 if (category->class_methods)
509 _objc_insertMethods (category->class_methods, &cls->isa->methodLists);
510
511 // Augment protocols
512 if ((version >= 5) && category->protocols)
513 {
514 if (cls->isa->version >= 5)
515 {
516 category->protocols->next = cls->protocols;
517 cls->protocols = category->protocols;
518 cls->isa->protocols = category->protocols;
519 }
520 else
521 {
522 _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
523 _objc_inform ("class `%s' must be recompiled\n", category->class_name);
524 }
525 }
526 }
527
528 /***********************************************************************
529 * _objc_add_category_flush_caches. Install the specified category's methods into
530 * the class it augments, and flush the class' method cache.
531 *
532 **********************************************************************/
533 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
534 {
535 // Install the category's methods into its intended class
536 _objc_add_category (cls, category, version);
537
538 // Flush caches so category's methods can get called
539 _objc_flush_caches (cls);
540 }
541
542 /***********************************************************************
543 * _objc_resolve_categories_for_class. Install all categories intended
544 * for the specified class, in reverse order from the order in which we
545 * found the categories in the image.
546 * This is done as lazily as we can.
547 **********************************************************************/
548 void _objc_resolve_categories_for_class (struct objc_class * cls)
549 {
550 _objc_unresolved_category * cat;
551 _objc_unresolved_category * next;
552
553 // Nothing to do if there are no categories at all
554 if (!category_hash)
555 return;
556
557 // Locate and remove first element in category list
558 // associated with this class
559 cat = NXMapRemove (category_hash, cls->name);
560
561 // Traverse the list of categories, if any, registered for this class
562 while (cat)
563 {
564 if (cat->bindme) {
565 _objc_bindModuleContainingCategory(cat->cat);
566 }
567 // Install the category
568 // use the non-flush-cache version since we are only
569 // called from the class intialization code
570 _objc_add_category (cls, cat->cat, cat->version);
571
572 // Delink and reclaim this registration
573 next = cat->next;
574 free (cat);
575 cat = next;
576 }
577 }
578
579 /***********************************************************************
580 * _objc_register_category. Add the specified category to the registry
581 * of categories to be installed later (once we know for sure which
582 * classes we have). If there are multiple categories on a given class,
583 * they will be processed in reverse order from the order in which they
584 * were found in the image.
585 **********************************************************************/
586 static void _objc_register_category (struct objc_category * cat,
587 long version,
588 int bindme)
589 {
590 _objc_unresolved_category * new_cat;
591 _objc_unresolved_category * old;
592 struct objc_class *theClass;
593
594
595 // If the category's class exists, just add the category
596 // We could check to see if its initted, and if not, defer this
597 // work until _objc_resolve_categories_for_class for all cases
598 // The only trick then is whether we need to bind it. This
599 // might be doable if we store an obscured pointer so that we
600 // avoid touching the memory... [BG 5/2001 still in think mode]
601 if (theClass = objc_lookUpClass (cat->class_name))
602 {
603 if (bindme) {
604 _objc_bindModuleContainingCategory(cat);
605 }
606 _objc_add_category_flush_caches (theClass, cat, version);
607 return;
608 }
609
610 // Create category lookup table if needed
611 if (!category_hash)
612 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
613 128,
614 _objc_create_zone ());
615
616 // Locate an existing category, if any, for the class. This is linked
617 // after the new entry, so list is LIFO.
618 old = NXMapGet (category_hash, cat->class_name);
619
620 // Register the category to be fixed up later
621 new_cat = malloc_zone_malloc (_objc_create_zone (),
622 sizeof(_objc_unresolved_category));
623 new_cat->next = old;
624 new_cat->cat = cat;
625 new_cat->version = version;
626 new_cat->bindme = bindme; // could use a bit in the next pointer instead of a whole word
627 (void) NXMapInsert (category_hash, cat->class_name , new_cat);
628 }
629
630 /***********************************************************************
631 * _objc_add_categories_from_image.
632 **********************************************************************/
633 static void _objc_add_categories_from_image (header_info * hi)
634 {
635 Module mods;
636 unsigned int midx;
637 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
638
639 // Major loop - process all modules in the header
640 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
641
642 trace(0xb120, hi->mod_count, 0, 0);
643
644 for (midx = 0; midx < hi->mod_count; midx += 1)
645 {
646 unsigned int index;
647 unsigned int total;
648
649 // Nothing to do for a module without a symbol table
650 if (mods[midx].symtab == NULL)
651 continue;
652
653 // Total entries in symbol table (class entries followed
654 // by category entries)
655 total = mods[midx].symtab->cls_def_cnt +
656 mods[midx].symtab->cat_def_cnt;
657
658
659 trace(0xb123, midx, mods[midx].symtab->cat_def_cnt, 0);
660
661 // Minor loop - register all categories from given module
662 for (index = mods[midx].symtab->cls_def_cnt; index < total; index += 1)
663 {
664 _objc_register_category(mods[midx].symtab->defs[index], mods[midx].version, isDynamic);
665 }
666
667 trace(0xb124, midx, 0, 0);
668 }
669
670 trace(0xb12f, 0, 0, 0);
671 }
672
673 /***********************************************************************
674 * _headerForClass.
675 **********************************************************************/
676 static const header_info * _headerForClass (struct objc_class * cls)
677 {
678 const struct segment_command * objcSeg;
679 unsigned int size;
680 unsigned long vmaddrPlus;
681 header_info * hInfo;
682
683 // Check all headers in the vector
684 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
685 {
686 // Locate header data, if any
687 objcSeg = _getObjcHeaderData ((headerType *) hInfo->mhdr, &size);
688 if (!objcSeg)
689 continue;
690
691 // Is the class in this header?
692 vmaddrPlus = (unsigned long) objcSeg->vmaddr + hInfo->image_slide;
693 if ((vmaddrPlus <= (unsigned long) cls) &&
694 ((unsigned long) cls < (vmaddrPlus + size)))
695 return hInfo;
696 }
697
698 // Not found
699 return 0;
700 }
701
702 /***********************************************************************
703 * _nameForHeader.
704 **********************************************************************/
705 const char * _nameForHeader (const headerType * header)
706 {
707 return _getObjcHeaderName ((headerType *) header);
708 }
709
710 /***********************************************************************
711 * checkForPendingClassReferences. Complete any fixups registered for
712 * this class.
713 **********************************************************************/
714 static void _objc_checkForPendingClassReferences (struct objc_class * cls)
715 {
716 PendingClass * pending;
717
718 // Nothing to do if there are no pending classes
719 if (!pendingClassRefsMap)
720 return;
721
722 // Get pending list for this class
723 pending = NXMapGet (pendingClassRefsMap, cls->name);
724 if (!pending)
725 return;
726
727 // Remove the list from the table
728 (void) NXMapRemove (pendingClassRefsMap, cls->name);
729
730 // Process all elements in the list
731 while (pending)
732 {
733 PendingClass * next;
734
735 // Remember follower for loop
736 next = pending->next;
737
738 // Fill in a pointer to Class
739 // (satisfies caller of objc_pendClassReference)
740 if (pending->ref)
741 *pending->ref = objc_getClass (cls->name);
742
743 // Fill in super, isa, cache, and version for the class
744 // and its meta-class
745 // (satisfies caller of objc_pendClassInstallation)
746 // NOTE: There must be no more than one of these for
747 // any given classToSetUp
748 if (pending->classToSetUp)
749 {
750 struct objc_class * fixCls;
751
752 // Locate the Class to be fixed up
753 fixCls = pending->classToSetUp;
754
755 // Set up super class fields with names to be replaced by pointers
756 fixCls->super_class = (struct objc_class *) pending->nameof_superclass;
757 fixCls->isa->super_class = (struct objc_class *) pending->nameof_superclass;
758
759 // Fix up class pointers, version, and cache pointers
760 _class_install_relationships (fixCls, pending->version);
761 }
762
763 // Reclaim the element
764 free (pending);
765
766 // Move on
767 pending = next;
768 }
769 }
770
771 /***********************************************************************
772 * newPending. Allocate and zero a PendingClass structure.
773 **********************************************************************/
774 static inline PendingClass * newPending (void)
775 {
776 PendingClass * pending;
777
778 pending = (PendingClass *) malloc_zone_calloc (_objc_create_zone (), 1, sizeof(PendingClass));
779
780 return pending;
781 }
782
783 /***********************************************************************
784 * pendingClassRefsMapTable. Return a pointer to the lookup table for
785 * pending classes.
786 **********************************************************************/
787 static inline NXMapTable * pendingClassRefsMapTable (void)
788 {
789 // Allocate table if needed
790 if (!pendingClassRefsMap)
791 pendingClassRefsMap = NXCreateMapTableFromZone (NXStrValueMapPrototype, 10, _objc_create_zone ());
792
793 // Return table pointer
794 return pendingClassRefsMap;
795 }
796
797 /***********************************************************************
798 * objc_pendClassReference. Register the specified class pointer (ref)
799 * to be filled in later with a pointer to the class having the specified
800 * name.
801 **********************************************************************/
802 void objc_pendClassReference (const char * className,
803 struct objc_class * * ref)
804 {
805 NXMapTable * table;
806 PendingClass * pending;
807
808 // Create and/or locate pending class lookup table
809 table = pendingClassRefsMapTable ();
810
811 // Create entry containing the class reference
812 pending = newPending ();
813 pending->ref = ref;
814
815 // Link new entry into head of list of entries for this class
816 pending->next = NXMapGet (pendingClassRefsMap, className);
817
818 // (Re)place entry list in the table
819 (void) NXMapInsert (table, className, pending);
820 }
821
822 /***********************************************************************
823 * objc_pendClassInstallation. Register the specified class to have its
824 * super class pointers filled in later because the superclass is not
825 * yet found.
826 **********************************************************************/
827 void objc_pendClassInstallation (struct objc_class *cls, int version)
828 {
829 NXMapTable * table;
830 PendingClass * pending;
831
832 // Create and/or locate pending class lookup table
833 table = pendingClassRefsMapTable ();
834
835 // Create entry referring to this class
836 pending = newPending ();
837 pending->classToSetUp = cls;
838 pending->nameof_superclass = (const char *) cls->super_class;
839 pending->version = version;
840
841 // Link new entry into head of list of entries for this class
842 pending->next = NXMapGet (pendingClassRefsMap, cls->super_class);
843
844 // (Re)place entry list in the table
845 (void) NXMapInsert (table, cls->super_class, pending);
846 }
847
848 /***********************************************************************
849 * _objc_add_classes_from_image. Install all classes contained in the
850 * specified image.
851 **********************************************************************/
852 static void _objc_add_classes_from_image(NXHashTable *clsHash, header_info *hi)
853 {
854 unsigned int index;
855 unsigned int midx;
856 Module mods;
857 int isDynamic = (hi->mhdr->filetype == MH_DYLIB) || (hi->mhdr->filetype == MH_BUNDLE);
858
859 // Major loop - process all modules in the image
860 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
861 for (midx = 0; midx < hi->mod_count; midx += 1)
862 {
863 // Skip module containing no classes
864 if (mods[midx].symtab == NULL)
865 continue;
866
867 // Minor loop - process all the classes in given module
868 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
869 {
870 struct objc_class * oldCls;
871 struct objc_class * newCls;
872
873 // Locate the class description pointer
874 newCls = mods[midx].symtab->defs[index];
875
876 // remember to bind the module on initialization
877 if (isDynamic)
878 newCls->info |= CLS_NEED_BIND ;
879
880 // Convert old style method list to the new style
881 _objcTweakMethodListPointerForClass (newCls);
882
883 oldCls = NXHashInsert (clsHash, newCls);
884
885 // Non-Nil oldCls is a class that NXHashInsert just
886 // bumped from table because it has the same name
887 // as newCls
888 if (oldCls)
889 {
890 const header_info * oldHeader;
891 const header_info * newHeader;
892 const char * oldName;
893 const char * newName;
894
895 // Log the duplication
896 oldHeader = _headerForClass (oldCls);
897 newHeader = _headerForClass (newCls);
898 oldName = _nameForHeader (oldHeader->mhdr);
899 newName = _nameForHeader (newHeader->mhdr);
900 _objc_inform ("Both %s and %s have implementations of class %s.",
901 oldName, newName, oldCls->name);
902 _objc_inform ("Using implementation from %s.", newName);
903
904 // Use the chosen class
905 // NOTE: Isn't this a NOP?
906 newCls = objc_lookUpClass (oldCls->name);
907 }
908
909 // Unless newCls was a duplicate, and we chose the
910 // existing one instead, set the version in the meta-class
911 if (newCls != oldCls)
912 newCls->isa->version = mods[midx].version;
913
914 // Install new categories intended for this class
915 // NOTE: But, if we displaced an existing "isEqual"
916 // class, the categories have already been installed
917 // on an old class and are gone from the registry!!
918
919 // we defer this work until the class is initialized.
920 //_objc_resolve_categories_for_class (newCls);
921
922 // Resolve (a) pointers to the named class, and/or
923 // (b) the super_class, cache, and version
924 // fields of newCls and its meta-class
925 // NOTE: But, if we displaced an existing "isEqual"
926 // class, this has already been done... with an
927 // old-now-"unused" class!!
928 _objc_checkForPendingClassReferences (newCls);
929
930 }
931 }
932 }
933
934 /***********************************************************************
935 * _objc_fixup_string_objects_for_image. Initialize the isa pointers
936 * of all NSConstantString objects.
937 **********************************************************************/
938 static void _objc_fixup_string_objects_for_image (header_info * hi)
939 {
940 unsigned int size;
941 OBJC_CONSTANT_STRING_PTR section;
942 struct objc_class * constantStringClass;
943 unsigned int index;
944
945 // Locate section holding string objects
946 section = _getObjcStringObjects ((headerType *) hi->mhdr, &size);
947 if (!section || !size)
948 return;
949 section = (OBJC_CONSTANT_STRING_PTR) ((unsigned long) section + hi->image_slide);
950
951 // Luckily NXConstantString is the same size as NSConstantString
952 constantStringClass = objc_getClass ("NSConstantString");
953
954 // Process each string object in the section
955 for (index = 0; index < size; index += 1)
956 {
957 struct objc_class * * isaptr;
958
959 isaptr = (struct objc_class * *) OBJC_CONSTANT_STRING_DEREF section[index];
960 if (*isaptr == 0)
961 *isaptr = constantStringClass;
962 }
963 }
964
965 /***********************************************************************
966 * _objc_map_class_refs_for_image. Convert the class ref entries from
967 * a class name string pointer to a class pointer. If the class does
968 * not yet exist, the reference is added to a list of pending references
969 * to be fixed up at a later date.
970 **********************************************************************/
971 static void _objc_map_class_refs_for_image (header_info * hi)
972 {
973 struct objc_class * * cls_refs;
974 unsigned int size;
975 unsigned int index;
976
977 // Locate class refs in image
978 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
979 if (!cls_refs)
980 return;
981 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
982
983 // Process each class ref
984 for (index = 0; index < size; index += 1)
985 {
986 const char * ref;
987 struct objc_class * cls;
988
989 // Get ref to convert from name string to class pointer
990 ref = (const char *) cls_refs[index];
991
992 // Get pointer to class of this name
993 cls = (struct objc_class *)objc_lookUpClass (ref);
994
995 // If class isn't there yet, use pending mechanism
996 if (!cls)
997 {
998 // Register this ref to be set later
999 objc_pendClassReference (ref, &cls_refs[index]);
1000
1001 // Use place-holder class
1002 cls_refs[index] = _objc_getNonexistentClass ();
1003 }
1004
1005 // Replace name string pointer with class pointer
1006 else
1007 cls_refs[index] = cls;
1008 }
1009 }
1010
1011 /***********************************************************************
1012 * map_selrefs. Register each selector in the specified array. If a
1013 * given selector is already registered, update this array to point to
1014 * the registered selector string.
1015 **********************************************************************/
1016 static inline void map_selrefs(SEL *sels, unsigned int cnt)
1017 {
1018 unsigned int index;
1019
1020 // Process each selector
1021 for (index = 0; index < cnt; index += 1)
1022 {
1023 SEL sel;
1024
1025 // Lookup pointer to uniqued string
1026 sel = sel_registerNameNoCopy ((const char *) sels[index]);
1027
1028 // Replace this selector with uniqued one (avoid
1029 // modifying the VM page if this would be a NOP)
1030 if (sels[index] != sel)
1031 sels[index] = sel;
1032 }
1033 }
1034
1035
1036 /***********************************************************************
1037 * map_method_descs. For each method in the specified method list,
1038 * replace the name pointer with a uniqued selector.
1039 **********************************************************************/
1040 static void map_method_descs (struct objc_method_description_list * methods)
1041 {
1042 unsigned int index;
1043
1044 // Process each method
1045 for (index = 0; index < methods->count; index += 1)
1046 {
1047 struct objc_method_description * method;
1048 SEL sel;
1049
1050 // Get method entry to fix up
1051 method = &methods->list[index];
1052
1053 // Lookup pointer to uniqued string
1054 sel = sel_registerNameNoCopy ((const char *) method->name);
1055
1056 // Replace this selector with uniqued one (avoid
1057 // modifying the VM page if this would be a NOP)
1058 if (method->name != sel)
1059 method->name = sel;
1060 }
1061 }
1062
1063 /***********************************************************************
1064 * _fixup.
1065 **********************************************************************/
1066 @interface Protocol(RuntimePrivate)
1067 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
1068 @end
1069
1070 /***********************************************************************
1071 * _objc_fixup_protocol_objects_for_image. For each protocol in the
1072 * specified image, selectorize the method names and call +_fixup.
1073 **********************************************************************/
1074 static void _objc_fixup_protocol_objects_for_image (header_info * hi)
1075 {
1076 unsigned int size;
1077 OBJC_PROTOCOL_PTR protos;
1078 unsigned int index;
1079
1080 // Locate protocols in the image
1081 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
1082 if (!protos)
1083 return;
1084
1085 // Apply the slide bias
1086 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
1087
1088 // Process each protocol
1089 for (index = 0; index < size; index += 1)
1090 {
1091 // Selectorize the instance methods
1092 if (protos[index] OBJC_PROTOCOL_DEREF instance_methods)
1093 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF instance_methods);
1094
1095 // Selectorize the class methods
1096 if (protos[index] OBJC_PROTOCOL_DEREF class_methods)
1097 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF class_methods);
1098 }
1099
1100 // Invoke Protocol class method to fix up the protocol
1101 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
1102 }
1103
1104 /***********************************************************************
1105 * _objc_headerStart. Return what headers we know about.
1106 **********************************************************************/
1107 header_info * _objc_headerStart ()
1108 {
1109
1110 // Take advatage of our previous work
1111 return FirstHeader;
1112 }
1113
1114 void _objc_bindModuleContainingList() {
1115 /* We define this for backwards binary compat with things which should not
1116 * have been using it (cough OmniWeb), but now it does nothing for them.
1117 */
1118 }
1119
1120 /**********************************************************************
1121 * _objc_bind_symbol. Bind the module containing the symbol. Use 2-level namespace API
1122 * Only look in images that we know to have ObjC symbols (e.g. 9 for Mail 7/2001)
1123 * Radar 2701686
1124 ***********************************************************************/
1125 static void _objc_bind_symbol(const char *name)
1126 {
1127 static header_info *lastHeader = NULL;
1128 header_info *hInfo;
1129 const headerType *imageHeader = lastHeader ? lastHeader->mhdr : NULL;
1130
1131 // Ideally we would have a way to not even process a symbol in a module
1132 // we've already visited
1133
1134
1135 // First assume there is some locality and search where we last found a symbol
1136 if ( imageHeader
1137 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1138 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1139 {
1140 // Found
1141 return;
1142 }
1143
1144 // Symbol wasn't found in the image we last searched
1145 // Search in all the images known to contain ObjcC
1146 for ( hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1147 {
1148 imageHeader = hInfo->mhdr;
1149 if ( hInfo != lastHeader
1150 && NSIsSymbolNameDefinedInImage(imageHeader, name)
1151 && NSLookupSymbolInImage(imageHeader, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND) != NULL )
1152 {
1153 // found
1154 lastHeader = hInfo;
1155 return;
1156 }
1157 }
1158 // die now, or later ??
1159 // _objc_fatal("could not find %s", name);
1160 }
1161
1162 /***********************************************************************
1163 * _objc_bindModuleContainingCategory. Bind the module containing the
1164 * category.
1165 **********************************************************************/
1166 static void _objc_bindModuleContainingCategory (Category cat)
1167 {
1168 char * class_name;
1169 char * category_name;
1170 char * name;
1171 char tmp_buf[128];
1172 unsigned int name_len;
1173
1174 // Bind ".objc_category_name_<classname>_<categoryname>",
1175 // where <classname> is the class name with the leading
1176 // '%'s stripped.
1177 class_name = cat->class_name;
1178 category_name = cat->category_name;
1179 name_len = strlen(class_name) + strlen(category_name) + 30;
1180 if ( name_len > 128 )
1181 name = malloc(name_len);
1182 else
1183 name = tmp_buf;
1184 while (*class_name == '%')
1185 class_name += 1;
1186 strcpy (name, ".objc_category_name_");
1187 strcat (name, class_name);
1188 strcat (name, "_");
1189 strcat (name, category_name);
1190 if (LaunchingDebug) { _objc_syslog("_objc_bindModuleContainingCategory for %s on %s", category_name, class_name); }
1191 _objc_bind_symbol(name);
1192 if ( name != tmp_buf )
1193 free(name);
1194 }
1195
1196 /***********************************************************************
1197 * _objc_bindModuleContainingClass. Bind the module containing the
1198 * class.
1199 * This is done lazily, just after initializing the class (if needed)
1200 **********************************************************************/
1201
1202 void _objc_bindModuleContainingClass (struct objc_class * cls) {
1203 char * name;
1204 const char * class_name;
1205 char tmp_buf[128];
1206 unsigned int name_len;
1207
1208 // Use the real class behind the poser
1209 if (CLS_GETINFO (cls, CLS_POSING))
1210 cls = getOriginalClassForPosingClass (cls);
1211 class_name = cls->name;
1212
1213 name_len = strlen(class_name) + 20;
1214 if ( name_len > 128 )
1215 name = malloc(name_len);
1216 else
1217 name = tmp_buf;
1218
1219 while (*class_name == '%')
1220 class_name += 1;
1221 strcpy (name, ".objc_class_name_");
1222 strcat (name, class_name);
1223 if (LaunchingDebug) { _objc_syslog("_objc_bindModuleContainingClass for %s", class_name); }
1224 _objc_bind_symbol(name);
1225 if ( name != tmp_buf )
1226 free(name);
1227 }
1228
1229
1230 /***********************************************************************
1231 * _objc_bindClassIfNeeded.
1232 * If the given class is still marked as needs-bind, bind the module
1233 * containing it.
1234 * Called during _objc_call_loads_for_image just before sending +load,
1235 * and during class_initialize just before sending +initialize.
1236 **********************************************************************/
1237 void _objc_bindClassIfNeeded(struct objc_class *cls)
1238 {
1239 // Clear NEED_BIND *after* binding to prevent race
1240 // This assumes that simultaneous binding of one module by two threads is ok.
1241 if (cls->info & CLS_NEED_BIND) {
1242 _objc_bindModuleContainingClass(cls);
1243 cls->info &= ~CLS_NEED_BIND;
1244 }
1245 }
1246
1247
1248 /***********************************************************************
1249 * _objc_addHeader.
1250 *
1251 **********************************************************************/
1252
1253 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
1254 #define HINFO_SIZE 16
1255
1256 static int HeaderInfoCounter = 0;
1257 static header_info HeaderInfoTable[HINFO_SIZE] = { {0} };
1258
1259 static header_info * _objc_addHeader(const headerType *header, unsigned long vmaddr_slide)
1260 {
1261 int mod_count;
1262 Module mod_ptr = _getObjcModules ((headerType *) header, &mod_count);
1263 header_info *result;
1264
1265 // if there is no objc data - ignore this entry!
1266 if (mod_ptr == NULL) {
1267 return NULL;
1268 }
1269
1270 if (HeaderInfoCounter < HINFO_SIZE) {
1271 // avoid mallocs for the common case
1272 result = &HeaderInfoTable[HeaderInfoCounter++];
1273 }
1274 else {
1275 result = malloc_zone_malloc(_objc_create_zone(), sizeof(header_info));
1276 }
1277
1278 // Set up the new vector entry
1279 result->mhdr = header;
1280 result->mod_ptr = mod_ptr;
1281 result->mod_count = mod_count;
1282 result->image_slide = vmaddr_slide;
1283
1284 // chain it on
1285 // (a simple lock here would go a long way towards thread safety)
1286 result->next = FirstHeader;
1287 FirstHeader = result;
1288
1289 return result;
1290 }
1291
1292 /**********************************************************************
1293 * _objc_fatalHeader
1294 *
1295 * If we have it we're in trouble
1296 **************************************************************************/
1297 static void _objc_fatalHeader(const headerType *header)
1298 {
1299 header_info *hInfo;
1300
1301 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next) {
1302 if (hInfo->mhdr == header) {
1303 _objc_fatal("cannot unmap an image containing ObjC data");
1304 }
1305 }
1306 }
1307
1308 /***********************************************************************
1309 * _objc_fixup_selector_refs. Register all of the selectors in each
1310 * image, and fix them all up.
1311 *
1312 **********************************************************************/
1313 static void _objc_fixup_selector_refs (const header_info * hi)
1314 {
1315 unsigned int size;
1316 Module mods;
1317 SEL * messages_refs;
1318
1319 mods = (Module) ((unsigned long) hi->mod_ptr + hi->image_slide);
1320
1321 // Fix up message refs
1322 messages_refs = (SEL *) _getObjcMessageRefs ((headerType *) hi->mhdr, &size);
1323 if (messages_refs)
1324 {
1325 messages_refs = (SEL *) ((unsigned long) messages_refs + hi->image_slide);
1326 map_selrefs (messages_refs, size);
1327 }
1328 }
1329
1330
1331 /***********************************************************************
1332 * _objc_call_loads_for_image.
1333 **********************************************************************/
1334 static void _objc_call_loads_for_image (header_info * header)
1335 {
1336 struct objc_class * cls;
1337 struct objc_class * * pClass;
1338 Category * pCategory;
1339 IMP load_method;
1340 unsigned int nModules;
1341 unsigned int nClasses;
1342 unsigned int nCategories;
1343 struct objc_symtab * symtab;
1344 struct objc_module * module;
1345
1346 // Major loop - process all modules named in header
1347 module = (struct objc_module *) ((unsigned long) header->mod_ptr + header->image_slide);
1348 for (nModules = header->mod_count; nModules; nModules -= 1, module += 1)
1349 {
1350 symtab = module->symtab;
1351 if (symtab == NULL)
1352 continue;
1353
1354 // Minor loop - call the +load from each class in the given module
1355 for (nClasses = symtab->cls_def_cnt, pClass = (Class *) symtab->defs;
1356 nClasses;
1357 nClasses -= 1, pClass += 1)
1358 {
1359 struct objc_method_list **mlistp;
1360 cls = (struct objc_class *)*pClass;
1361 mlistp = get_base_method_list(cls->isa);
1362 if (cls->isa->methodLists && mlistp)
1363 {
1364 // Look up the method manually (vs messaging the class) to bypass
1365 // +initialize and cache fill on class that is not even loaded yet
1366 load_method = class_lookupNamedMethodInMethodList (*mlistp, "load");
1367 if (load_method) {
1368 _objc_bindClassIfNeeded(cls);
1369 (*load_method) ((id) cls, @selector(load));
1370 }
1371 }
1372 }
1373
1374 // Minor loop - call the +load from augmented class of
1375 // each category in the given module
1376 for (nCategories = symtab->cat_def_cnt,
1377 pCategory = (Category *) &symtab->defs[symtab->cls_def_cnt];
1378 nCategories;
1379 nCategories -= 1, pCategory += 1)
1380 {
1381 struct objc_method_list * methods;
1382
1383 methods = (*pCategory)->class_methods;
1384 if (methods)
1385 {
1386 load_method = class_lookupNamedMethodInMethodList (methods, "load");
1387 if (load_method) {
1388 // Strictly speaking we shouldn't need (and don't want) to get the class here
1389 // The side effect we're looking for is to load it if needed.
1390 // Since category +loads are rare we could spend some cycles finding out
1391 // if we have a "bindme" TBD and do it here, saving a class load.
1392 // But chances are the +load will cause class initialization anyway
1393 cls = objc_getClass ((*pCategory)->class_name);
1394 // the class & all categories are now bound in
1395 (*load_method) ((id) cls, @selector(load));
1396 }
1397 }
1398 }
1399 }
1400 }
1401
1402 /***********************************************************************
1403 * runtime configuration
1404 **********************************************************************/
1405 static void objc_setConfiguration() {
1406 if ( LaunchingDebug == -1 ) {
1407 // watch image loading and binding
1408 LaunchingDebug = getenv("LaunchingDebug") != NULL;
1409 }
1410 }
1411 /***********************************************************************
1412 * objc_setMultithreaded.
1413 **********************************************************************/
1414 void objc_setMultithreaded (BOOL flag)
1415 {
1416 // Nothing here. Thread synchronization in the runtime is always active.
1417 }
1418
1419
1420
1421 /***********************************************************************
1422 * _objc_pthread_destroyspecific
1423 * Destructor for objc's per-thread data.
1424 * arg shouldn't be NULL, but we check anyway.
1425 **********************************************************************/
1426 extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
1427 void _objc_pthread_destroyspecific(void *arg)
1428 {
1429 _objc_pthread_data *data = (_objc_pthread_data *)arg;
1430 if (data != NULL) {
1431 _destroyInitializingClassList(data->initializingClasses);
1432
1433 // add further cleanup here...
1434
1435 free(data);
1436 }
1437 }
1438
1439
1440 /***********************************************************************
1441 * _objcInit.
1442 * Library initializer called by dyld & from crt0
1443 **********************************************************************/
1444
1445 void _objcInit(void) {
1446 header_info *hInfo;
1447 static int _done = 0;
1448 extern void __CFInitialize(void);
1449 extern int ptrace(int, int, int, int); // a system call visible to sc_trace
1450
1451 /* Protect against multiple invocations, as all library
1452 * initializers should. */
1453 if (0 != _done) return;
1454 _done = 1;
1455
1456 ptrace(0xb000, 0, 0, 0);
1457 trace(0xb000, 0, 0, 0);
1458
1459 // make sure CF is initialized before we go further;
1460 // someday this can be removed, as it'll probably be automatic
1461 __CFInitialize();
1462
1463 pthread_key_create(&_objc_pthread_key, _objc_pthread_destroyspecific);
1464
1465 // Create the class lookup table
1466 _objc_init_class_hash ();
1467
1468 trace(0xb001, 0, 0, 0);
1469
1470 objc_setConfiguration(); // Get our configuration
1471
1472 trace(0xb003, 0, 0, 0);
1473
1474 // a pre-cheetah comment:
1475 // XXXXX BEFORE HERE *NO* PAGES ARE STOMPED ON;
1476
1477 // Register our image mapping routine with dyld so it
1478 // gets invoked when an image is added. This also invokes
1479 // the callback right now on any images already present.
1480
1481 // The modules present in the application and the existing
1482 // mapped images are treated differently than a newly discovered
1483 // mapped image - we process all modules for classes before
1484 // trying to install_relationships (glue up their superclasses)
1485 // or trying to send them any +load methods.
1486
1487 // So we tell the map_image dyld callback to not do this part...
1488
1489 Postpone_install_relationships = 1;
1490
1491 // register for unmapping first so we can't miss any during load attempts
1492 _dyld_register_func_for_remove_image (&_objc_unmap_image);
1493
1494 // finally, register for images
1495 _dyld_register_func_for_add_image (&_objc_map_image);
1496
1497 // a pre-cheetah comment:
1498 // XXXXX BEFORE HERE *ALL* PAGES ARE STOMPED ON
1499
1500 Postpone_install_relationships = 0;
1501
1502 trace(0xb006, 0, 0, 0);
1503
1504 // Install relations on classes that were found
1505 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1506 {
1507 int nModules;
1508 int index;
1509 struct objc_module * module;
1510 struct objc_class * cls;
1511
1512 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1513 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1514 {
1515 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1516 {
1517 cls = (struct objc_class *) module->symtab->defs[index];
1518 _class_install_relationships (cls, module->version);
1519 }
1520
1521 module += 1;
1522 }
1523
1524 trace(0xb007, hInfo, hInfo->mod_count, 0);
1525
1526 }
1527
1528 trace(0xb008, 0, 0, 0);
1529
1530 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1531 {
1532 // Initialize the isa pointers of all NXConstantString objects
1533 (void)_objc_fixup_string_objects_for_image (hInfo);
1534
1535 // Convert class refs from name pointers to ids
1536 (void)_objc_map_class_refs_for_image (hInfo);
1537 }
1538
1539 trace(0xb00a, 0, 0, 0);
1540
1541 // For each image selectorize the method names and +_fixup each of
1542 // protocols in the image
1543 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1544 _objc_fixup_protocol_objects_for_image (hInfo);
1545
1546 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1547 _objc_call_loads_for_image (hInfo);
1548
1549 ptrace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1550 trace(0xb00f, 0, 0, 0); // end of __initialize_objc ObjC init
1551 }
1552
1553
1554 /***********************************************************************
1555 * _objc_map_image.
1556 **********************************************************************/
1557 static void _objc_map_image(headerType *mh, unsigned long vmaddr_slide)
1558 {
1559 static int dumpClasses = -1;
1560 header_info *hInfo;
1561
1562 if ( dumpClasses == -1 ) {
1563 if ( getenv("OBJC_DUMP_CLASSES") ) dumpClasses = 1;
1564 else dumpClasses = 0;
1565 }
1566
1567 trace(0xb100, 0, 0, 0);
1568
1569 // Add this header to the chain
1570 hInfo = _objc_addHeader (mh, vmaddr_slide);
1571
1572 if (!hInfo) return;
1573
1574 if (LaunchingDebug) { _objc_syslog("objc_map_image for %s\n", _nameForHeader(mh)); }
1575
1576 trace(0xb101, 0, 0, 0);
1577
1578 // Register any categories and/or classes and/or selectors this image contains
1579 _objc_add_categories_from_image (hInfo);
1580
1581 trace(0xb103, 0, 0, 0);
1582
1583 _objc_add_classes_from_image (class_hash, hInfo);
1584
1585 trace(0xb104, 0, 0, 0);
1586
1587 _objc_fixup_selector_refs (hInfo);
1588
1589 trace(0xb105, 0, 0, 0);
1590
1591 // Log all known class names, if asked
1592 if ( dumpClasses )
1593 {
1594 printf ("classes...\n");
1595 objc_dump_class_hash ();
1596 }
1597
1598 if (!Postpone_install_relationships)
1599 {
1600 int nModules;
1601 int index;
1602 struct objc_module * module;
1603
1604 // Major loop - process each module
1605 module = (struct objc_module *) ((unsigned long) hInfo->mod_ptr + hInfo->image_slide);
1606
1607 trace(0xb106, hInfo->mod_count, 0, 0);
1608
1609 for (nModules = hInfo->mod_count; nModules; nModules -= 1)
1610 {
1611 // Minor loop - process each class in a given module
1612 for (index = 0; index < module->symtab->cls_def_cnt; index += 1)
1613 {
1614 struct objc_class * cls;
1615
1616 // Locate the class description
1617 cls = (struct objc_class *) module->symtab->defs[index];
1618
1619 // If there is no superclass or the superclass can be found,
1620 // install this class, and invoke the expected callback
1621 if (!((struct objc_class *)cls)->super_class || objc_lookUpClass ((char *) ((struct objc_class *)cls)->super_class))
1622 {
1623 _class_install_relationships (cls, module->version);
1624 if (callbackFunction)
1625 (*callbackFunction) (cls, 0);
1626 }
1627 else
1628 {
1629 // Super class can not be found yet, arrange for this class to
1630 // be filled in later
1631 objc_pendClassInstallation (cls, module->version);
1632 ((struct objc_class *)cls)->super_class = _objc_getNonexistentClass ();
1633 ((struct objc_class *)cls)->isa->super_class = _objc_getNonexistentClass ();
1634 }
1635 }
1636
1637 // Move on
1638 module += 1;
1639 }
1640
1641 trace(0xb108, 0, 0, 0);
1642
1643 // Initialize the isa pointers of all NXConstantString objects
1644 _objc_fixup_string_objects_for_image (hInfo);
1645
1646 trace(0xb109, 0, 0, 0);
1647
1648 // Convert class refs from name pointers to ids
1649 _objc_map_class_refs_for_image (hInfo);
1650
1651 trace(0xb10a, 0, 0, 0);
1652
1653 // Selectorize the method names and +_fixup each of
1654 // protocols in the image
1655 _objc_fixup_protocol_objects_for_image (hInfo);
1656
1657 trace(0xb10b, 0, 0, 0);
1658
1659 // Call +load on all classes and categorized classes
1660 _objc_call_loads_for_image (hInfo);
1661
1662 trace(0xb10c, 0, 0, 0);
1663 }
1664
1665 trace(0xb10f, 0, 0, 0);
1666 }
1667
1668 /***********************************************************************
1669 * _objc_unmap_image.
1670 **********************************************************************/
1671 static void _objc_unmap_image(headerType *mh, unsigned long vmaddr_slide) {
1672 // we shouldn't have it if it didn't have objc data
1673 // if we do have it, do a fatal
1674 _objc_fatalHeader(mh);
1675 }
1676
1677 /***********************************************************************
1678 * objc_setNilObjectMsgHandler.
1679 **********************************************************************/
1680 void objc_setNilObjectMsgHandler (NilObjectMsgCallback nilObjMsgCallback)
1681 {
1682 _objc_msgNil = nilObjMsgCallback;
1683 }
1684
1685 /***********************************************************************
1686 * objc_getNilObjectMsgHandler.
1687 **********************************************************************/
1688 NilObjectMsgCallback objc_getNilObjectMsgHandler (void)
1689 {
1690 return _objc_msgNil;
1691 }
1692
1693