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