]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-runtime.m
8687470c3f757ad7fbba9e5340bfd01989f6e397
[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 * Class loading and connecting (GrP 2004-2-11)
34 *
35 * When images are loaded (during program startup or otherwise), the
36 * runtime needs to load classes and categories from the images, connect
37 * classes to superclasses and categories to parent classes, and call
38 * +load methods.
39 *
40 * The Objective-C runtime can cope with classes arriving in any order.
41 * That is, a class may be discovered by the runtime before some
42 * superclass is known. To handle out-of-order class loads, the
43 * runtime uses a "pending class" system.
44 *
45 * (Historical note)
46 * Panther and earlier: many classes arrived out-of-order because of
47 * the poorly-ordered callback from dyld. However, the runtime's
48 * pending mechanism only handled "missing superclass" and not
49 * "present superclass but missing higher class". See Radar #3225652.
50 * Tiger: The runtime's pending mechanism was augmented to handle
51 * arbitrary missing classes. In addition, dyld was rewritten and
52 * now sends the callbacks in strictly bottom-up link order.
53 * The pending mechanism may now be needed only for rare and
54 * hard to construct programs.
55 * (End historical note)
56 *
57 * A class when first seen in an image is considered "unconnected".
58 * It is stored in `unconnected_class_hash`. If all of the class's
59 * superclasses exist and are already "connected", then the new class
60 * can be connected to its superclasses and moved to `class_hash` for
61 * normal use. Otherwise, the class waits in `unconnected_class_hash`
62 * until the superclasses finish connecting.
63 *
64 * A "connected" class is
65 * (1) in `class_hash`,
66 * (2) connected to its superclasses,
67 * (3) has no unconnected superclasses,
68 * (4) is otherwise initialized and ready for use, and
69 * (5) is eligible for +load if +load has not already been called.
70 *
71 * An "unconnected" class is
72 * (1) in `unconnected_class_hash`,
73 * (2) not connected to its superclasses,
74 * (3) has an immediate superclass which is either missing or unconnected,
75 * (4) is not ready for use, and
76 * (5) is not yet eligible for +load.
77 *
78 * Image mapping is NOT CURRENTLY THREAD-SAFE with respect to just about
79 * * * anything. Image mapping IS RE-ENTRANT in several places: superclass
80 * lookup may cause ZeroLink to load another image, and +load calls may
81 * cause dyld to load another image.
82 *
83 * Image mapping sequence:
84 *
85 * Read all classes in all new images.
86 * Add them all to unconnected_class_hash.
87 * Fix up any pended classrefs referring to them.
88 * Attach any pending categories.
89 * Read all categories in all new images.
90 * Attach categories whose parent class exists (connected or not),
91 * and pend the rest.
92 * Mark them all eligible for +load (if implemented), even if the
93 * parent class is missing.
94 * Try to connect all classes in all new images.
95 * If the superclass is missing, pend the class
96 * If the superclass is unconnected, try to recursively connect it
97 * If the superclass is connected:
98 * connect the class
99 * mark the class eligible for +load, if implemented
100 * connect any pended subclasses of the class
101 * Resolve selector refs and class refs in all new images.
102 * Class refs whose classes still do not exist are pended.
103 * Fix up protocol objects in all new images.
104 * Call +load for classes and categories.
105 * May include classes or categories that are not in these images,
106 * but are newly eligible because of these image.
107 * Class +loads will be called superclass-first because of the
108 * superclass-first nature of the connecting process.
109 * Category +load needs to be deferred until the parent class is
110 * connected and has had its +load called.
111 *
112 * Performance: all classes are read before any categories are read.
113 * Fewer categories need be pended for lack of a parent class.
114 *
115 * Performance: all categories are attempted to be attached before
116 * any classes are connected. Fewer class caches need be flushed.
117 * (Unconnected classes and their respective subclasses are guaranteed
118 * to be un-messageable, so their caches will be empty.)
119 *
120 * Performance: all classes are read before any classes are connected.
121 * Fewer classes need be pended for lack of a superclass.
122 *
123 * Correctness: all selector and class refs are fixed before any
124 * protocol fixups or +load methods. libobjc itself contains selector
125 * and class refs which are used in protocol fixup and +load.
126 *
127 * Correctness: +load methods are scheduled in bottom-up link order.
128 * This constraint is in addition to superclass order. Some +load
129 * implementations expect to use another class in a linked-to library,
130 * even if the two classes don't share a direct superclass relationship.
131 *
132 **********************************************************************/
133
134
135 /***********************************************************************
136 * Imports.
137 **********************************************************************/
138
139 #include <mach-o/ldsyms.h>
140 #include <mach-o/dyld.h>
141 #include <mach-o/dyld_gdb.h>
142 #include <mach/mach.h>
143 #include <mach/mach_error.h>
144
145 // project headers first, otherwise we get the installed ones
146 #import "objc-class.h"
147 #import <objc/objc-runtime.h>
148 #import <objc/hashtable2.h>
149 #import "maptable.h"
150 #import "objc-private.h"
151 #import <objc/Object.h>
152 #import <objc/Protocol.h>
153 #import "objc-rtp.h"
154 #import "objc-auto.h"
155
156 #include <sys/time.h>
157 #include <sys/resource.h>
158 #include <sys/types.h>
159 #include <sys/stat.h>
160 #include <fcntl.h>
161
162 /* NXHashTable SPI */
163 OBJC_EXPORT unsigned _NXHashCapacity(NXHashTable *table);
164 OBJC_EXPORT void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity);
165
166
167 OBJC_EXPORT Class _objc_getNonexistentClass(void);
168
169
170 OBJC_EXPORT Class getOriginalClassForPosingClass(Class);
171
172
173 /***********************************************************************
174 * Constants and macros internal to this module.
175 **********************************************************************/
176
177 /* Turn on support for literal string objects. */
178 #define LITERAL_STRING_OBJECTS
179
180 /***********************************************************************
181 * Types internal to this module.
182 **********************************************************************/
183
184 typedef struct _objc_unresolved_category
185 {
186 struct _objc_unresolved_category * next;
187 struct objc_category * cat; // may be NULL
188 long version;
189 } _objc_unresolved_category;
190
191 typedef struct _PendingSubclass
192 {
193 struct objc_class *subclass; // subclass to finish connecting; may be NULL
194 struct _PendingSubclass *next;
195 } PendingSubclass;
196
197 typedef struct _PendingClassRef
198 {
199 struct objc_class **ref; // class reference to fix up; may be NULL
200 struct _PendingClassRef *next;
201 } PendingClassRef;
202
203 struct loadable_class {
204 struct objc_class *cls; // may be NULL
205 IMP method;
206 };
207
208 struct loadable_category {
209 struct objc_category *cat; // may be NULL
210 IMP method;
211 };
212
213
214 /***********************************************************************
215 * Exports.
216 **********************************************************************/
217
218 // Function called after class has been fixed up (MACH only)
219 void (*callbackFunction)(Class, const char *) = 0;
220
221 // Lock for class hashtable
222 OBJC_DECLARE_LOCK (classLock);
223
224 // Settings from environment variables
225 __private_extern__ int PrintImages = -1; // env OBJC_PRINT_IMAGES
226 __private_extern__ int PrintLoading = -1; // env OBJC_PRINT_LOAD_METHODS
227 __private_extern__ int PrintConnecting = -1; // env OBJC_PRINT_CONNECTION
228 __private_extern__ int PrintRTP = -1; // env OBJC_PRINT_RTP
229 __private_extern__ int PrintGC = -1; // env OBJC_PRINT_GC
230 __private_extern__ int PrintSharing = -1; // env OBJC_PRINT_SHARING
231 __private_extern__ int PrintCxxCtors = -1; // env OBJC_PRINT_CXX_CTORS
232
233 __private_extern__ int UseInternalZone = -1; // env OBJC_USE_INTERNAL_ZONE
234 __private_extern__ int AllowInterposing = -1;// env OBJC_ALLOW_INTERPOSING
235
236 __private_extern__ int DebugUnload = -1; // env OBJC_DEBUG_UNLOAD
237 __private_extern__ int DebugFragileSuperclasses = -1; // env OBJC_DEBUG_FRAGILE_SUPERCLASSES
238
239 __private_extern__ int ForceGC = -1; // env OBJC_FORCE_GC
240 __private_extern__ int ForceNoGC = -1; // env OBJC_FORCE_NO_GC
241 __private_extern__ int CheckFinalizers = -1; // env OBJC_CHECK_FINALIZERS
242
243 // objc's key for pthread_getspecific
244 __private_extern__ pthread_key_t _objc_pthread_key = 0;
245
246 // List of classes that need +load called (pending superclass +load)
247 // This list always has superclasses first because of the way it is constructed
248 static struct loadable_class *loadable_classes NOBSS = NULL;
249 static int loadable_classes_used NOBSS = 0;
250 static int loadable_classes_allocated NOBSS = 0;
251
252 // List of categories that need +load called (pending parent class +load)
253 static struct loadable_category *loadable_categories NOBSS = NULL;
254 static int loadable_categories_used NOBSS = 0;
255 static int loadable_categories_allocated NOBSS = 0;
256
257 // Selectors for which @selector() doesn't work
258 __private_extern__ SEL cxx_construct_sel = NULL;
259 __private_extern__ SEL cxx_destruct_sel = NULL;
260 __private_extern__ const char *cxx_construct_name = ".cxx_construct";
261 __private_extern__ const char *cxx_destruct_name = ".cxx_destruct";
262
263
264 /***********************************************************************
265 * Function prototypes internal to this module.
266 **********************************************************************/
267
268 static unsigned classHash (void * info, struct objc_class * data);
269 static int classIsEqual (void * info, struct objc_class * name, struct objc_class * cls);
270 static int _objc_defaultClassHandler (const char * clsName);
271 static void _objcTweakMethodListPointerForClass (struct objc_class * cls);
272 static void _objc_add_category_flush_caches(struct objc_class * cls, struct objc_category * category, int version);
273 static void _objc_add_category(struct objc_class * cls, struct objc_category * category, int version);
274 static void _objc_register_category (struct objc_category * cat, long version);
275 static void _objc_read_categories_from_image (header_info * hi);
276 static const header_info * _headerForClass (struct objc_class * cls);
277 static NXMapTable * pendingClassRefsMapTable (void);
278 static NXMapTable * pendingSubclassesMapTable (void);
279 static void _objc_read_classes_from_image (header_info * hi);
280 static void _objc_map_class_refs_for_image (header_info * hi);
281 static void _objc_fixup_protocol_objects_for_image (header_info * hi);
282 static void _objc_fixup_selector_refs (const header_info * hi);
283 static void _objc_unmap_image(const headerType *mh);
284 static BOOL connect_class(struct objc_class *cls);
285 static void add_category_to_loadable_list(struct objc_category *cat);
286 static vm_range_t get_shared_range(vm_address_t start, vm_address_t end);
287 static void offer_shared_range(vm_address_t start, vm_address_t end);
288 static void install_shared_range(vm_range_t remote, vm_address_t local);
289 static void clear_shared_range_file_cache(void);
290
291
292 /***********************************************************************
293 * Static data internal to this module.
294 **********************************************************************/
295
296 // we keep a linked list of header_info's describing each image as told to us by dyld
297 static header_info *FirstHeader NOBSS = 0; // NULL means empty list
298 static header_info *LastHeader NOBSS = 0; // NULL means invalid; recompute it
299
300 // Hash table of classes
301 static NXHashTable * class_hash NOBSS = 0;
302 static NXHashTablePrototype classHashPrototype =
303 {
304 (unsigned (*) (const void *, const void *)) classHash,
305 (int (*)(const void *, const void *, const void *)) classIsEqual,
306 NXNoEffectFree, 0
307 };
308
309 // Hash table of unconnected classes
310 static NXHashTable *unconnected_class_hash NOBSS = NULL;
311
312 // Exported copy of class_hash variable (hook for debugging tools)
313 NXHashTable *_objc_debug_class_hash = NULL;
314
315 // Function pointer objc_getClass calls through when class is not found
316 static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
317
318 // Function pointer called by objc_getClass and objc_lookupClass when
319 // class is not found. _objc_classLoader is called before objc_classHandler.
320 static BOOL (*_objc_classLoader)(const char *) = NULL;
321
322 // Category and class registries
323 // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
324 // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
325 static NXMapTable * category_hash = NULL;
326
327 // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
328 // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
329 static NXMapTable * pendingClassRefsMap = NULL;
330 static NXMapTable * pendingSubclassesMap = NULL;
331
332 /***********************************************************************
333 * objc_dump_class_hash. Log names of all known classes.
334 **********************************************************************/
335 void objc_dump_class_hash (void)
336 {
337 NXHashTable * table;
338 unsigned count;
339 struct objc_class * data;
340 NXHashState state;
341
342 table = class_hash;
343 count = 0;
344 state = NXInitHashState (table);
345 while (NXNextHashState (table, &state, (void **) &data))
346 printf ("class %d: %s\n", ++count, data->name);
347 }
348
349 /***********************************************************************
350 * classHash.
351 **********************************************************************/
352 static unsigned classHash (void * info,
353 struct objc_class * data)
354 {
355 // Nil classes hash to zero
356 if (!data)
357 return 0;
358
359 // Call through to real hash function
360 return _objc_strhash ((unsigned char *) ((struct objc_class *) data)->name);
361 }
362
363 /***********************************************************************
364 * classIsEqual. Returns whether the class names match. If we ever
365 * check more than the name, routines like objc_lookUpClass have to
366 * change as well.
367 **********************************************************************/
368 static int classIsEqual (void * info,
369 struct objc_class * name,
370 struct objc_class * cls)
371 {
372 // Standard string comparison
373 // Our local inlined version is significantly shorter on PPC and avoids the
374 // mflr/mtlr and dyld_stub overhead when calling strcmp.
375 return _objc_strcmp(name->name, cls->name) == 0;
376 }
377
378
379 /***********************************************************************
380 * NXMapKeyCopyingInsert
381 * Like NXMapInsert, but strdups the key if necessary.
382 * Used to prevent stale pointers when bundles are unloaded.
383 **********************************************************************/
384 static void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value)
385 {
386 void *realKey;
387 void *realValue = NULL;
388
389 if ((realKey = NXMapMember(table, key, &realValue)) != NX_MAPNOTAKEY) {
390 // key DOES exist in table - use table's key for insertion
391 } else {
392 // key DOES NOT exist in table - copy the new key before insertion
393 realKey = _strdup_internal(key);
394 }
395 return NXMapInsert(table, realKey, value);
396 }
397
398
399 /***********************************************************************
400 * NXMapKeyFreeingRemove
401 * Like NXMapRemove, but frees the existing key if necessary.
402 * Used to prevent stale pointers when bundles are unloaded.
403 **********************************************************************/
404 static void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key)
405 {
406 void *realKey;
407 void *realValue = NULL;
408
409 if ((realKey = NXMapMember(table, key, &realValue)) != NX_MAPNOTAKEY) {
410 // key DOES exist in table - remove pair and free key
411 realValue = NXMapRemove(table, realKey);
412 _free_internal(realKey); // the key from the table, not necessarily the one given
413 return realValue;
414 } else {
415 // key DOES NOT exist in table - nothing to do
416 return NULL;
417 }
418 }
419
420
421 /***********************************************************************
422 * _objc_init_class_hash. Return the class lookup table, create it if
423 * necessary.
424 **********************************************************************/
425 void _objc_init_class_hash (void)
426 {
427 // Do nothing if class hash table already exists
428 if (class_hash)
429 return;
430
431 // class_hash starts small, with only enough capacity for libobjc itself.
432 // If a second library is found by map_images(), class_hash is immediately
433 // resized to capacity 1024 to cut down on rehashes.
434 // Old numbers: A smallish Foundation+AppKit program will have
435 // about 520 classes. Larger apps (like IB or WOB) have more like
436 // 800 classes. Some customers have massive quantities of classes.
437 // Foundation-only programs aren't likely to notice the ~6K loss.
438 class_hash = NXCreateHashTableFromZone (classHashPrototype,
439 16,
440 nil,
441 _objc_internal_zone ());
442 _objc_debug_class_hash = class_hash;
443 }
444
445 /***********************************************************************
446 * objc_getClassList. Return the known classes.
447 **********************************************************************/
448 int objc_getClassList(Class *buffer, int bufferLen) {
449 NXHashState state;
450 struct objc_class * class;
451 int cnt, num;
452
453 OBJC_LOCK(&classLock);
454 num = NXCountHashTable(class_hash);
455 if (NULL == buffer) {
456 OBJC_UNLOCK(&classLock);
457 return num;
458 }
459 cnt = 0;
460 state = NXInitHashState(class_hash);
461 while (cnt < bufferLen &&
462 NXNextHashState(class_hash, &state, (void **)&class))
463 {
464 buffer[cnt++] = class;
465 }
466 OBJC_UNLOCK(&classLock);
467 return num;
468 }
469
470 /***********************************************************************
471 * objc_getClasses. Return class lookup table.
472 *
473 * NOTE: This function is very dangerous, since you cannot safely use
474 * the hashtable without locking it, and the lock is private!
475 **********************************************************************/
476 void * objc_getClasses (void)
477 {
478 // Return the class lookup hash table
479 return class_hash;
480 }
481
482 /***********************************************************************
483 * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
484 **********************************************************************/
485 static int _objc_defaultClassHandler (const char * clsName)
486 {
487 // Return zero so objc_getClass doesn't bother re-searching
488 return 0;
489 }
490
491 /***********************************************************************
492 * objc_setClassHandler. Set objc_classHandler to the specified value.
493 *
494 * NOTE: This should probably deal with userSuppliedHandler being NULL,
495 * because the objc_classHandler caller does not check... it would bus
496 * error. It would make sense to handle NULL by restoring the default
497 * handler. Is anyone hacking with this, though?
498 **********************************************************************/
499 void objc_setClassHandler (int (*userSuppliedHandler) (const char *))
500 {
501 objc_classHandler = userSuppliedHandler;
502 }
503
504
505 /***********************************************************************
506 * look_up_class
507 * Map a class name to a class using various methods.
508 * This is the common implementation of objc_lookUpClass and objc_getClass,
509 * and is also used internally to get additional search options.
510 * Sequence:
511 * 1. class_hash
512 * 2. unconnected_class_hash (optional)
513 * 3. classLoader callback
514 * 4. classHandler callback (optional)
515 **********************************************************************/
516 static id look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler)
517 {
518 BOOL includeClassLoader = YES; // class loader cannot be skipped
519 id result = nil;
520 struct objc_class query;
521
522 query.name = aClassName;
523
524 retry:
525
526 if (!result && class_hash) {
527 // Check ordinary classes
528 OBJC_LOCK (&classLock);
529 result = (id)NXHashGet(class_hash, &query);
530 OBJC_UNLOCK (&classLock);
531 }
532
533 if (!result && includeUnconnected && unconnected_class_hash) {
534 // Check not-yet-connected classes
535 OBJC_LOCK(&classLock);
536 result = (id)NXHashGet(unconnected_class_hash, &query);
537 OBJC_UNLOCK(&classLock);
538 }
539
540 if (!result && includeClassLoader && _objc_classLoader) {
541 // Try class loader callback
542 if ((*_objc_classLoader)(aClassName)) {
543 // Re-try lookup without class loader
544 includeClassLoader = NO;
545 goto retry;
546 }
547 }
548
549 if (!result && includeClassHandler && objc_classHandler) {
550 // Try class handler callback
551 if ((*objc_classHandler)(aClassName)) {
552 // Re-try lookup without class handler or class loader
553 includeClassLoader = NO;
554 includeClassHandler = NO;
555 goto retry;
556 }
557 }
558
559 return result;
560 }
561
562
563 /***********************************************************************
564 * objc_getClass. Return the id of the named class. If the class does
565 * not exist, call _objc_classLoader and then objc_classHandler, either of
566 * which may create a new class.
567 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
568 **********************************************************************/
569 id objc_getClass (const char * aClassName)
570 {
571 // NO unconnected, YES class handler
572 return look_up_class(aClassName, NO, YES);
573 }
574
575
576 /***********************************************************************
577 * objc_getRequiredClass.
578 * Same as objc_getClass, but kills the process if the class is not found.
579 * This is used by ZeroLink, where failing to find a class would be a
580 * compile-time link error without ZeroLink.
581 **********************************************************************/
582 id objc_getRequiredClass(const char *aClassName)
583 {
584 id cls = objc_getClass(aClassName);
585 if (!cls) _objc_fatal("link error: class '%s' not found.", aClassName);
586 return cls;
587 }
588
589
590 /***********************************************************************
591 * objc_lookUpClass. Return the id of the named class.
592 * If the class does not exist, call _objc_classLoader, which may create
593 * a new class.
594 *
595 * Formerly objc_getClassWithoutWarning ()
596 **********************************************************************/
597 id objc_lookUpClass (const char * aClassName)
598 {
599 // NO unconnected, NO class handler
600 return look_up_class(aClassName, NO, NO);
601 }
602
603 /***********************************************************************
604 * objc_getMetaClass. Return the id of the meta class the named class.
605 * Warning: doesn't work if aClassName is the name of a posed-for class's isa!
606 **********************************************************************/
607 id objc_getMetaClass (const char * aClassName)
608 {
609 struct objc_class * cls;
610
611 cls = objc_getClass (aClassName);
612 if (!cls)
613 {
614 _objc_inform ("class `%s' not linked into application", aClassName);
615 return Nil;
616 }
617
618 return cls->isa;
619 }
620
621 /***********************************************************************
622 * objc_addClass. Add the specified class to the table of known classes,
623 * after doing a little verification and fixup.
624 **********************************************************************/
625 void objc_addClass (struct objc_class *cls)
626 {
627 // Synchronize access to hash table
628 OBJC_LOCK (&classLock);
629
630 // Make sure both the class and the metaclass have caches!
631 // Clear all bits of the info fields except CLS_CLASS and CLS_META.
632 // Normally these bits are already clear but if someone tries to cons
633 // up their own class on the fly they might need to be cleared.
634 if (cls->cache == NULL) {
635 cls->cache = (Cache) &emptyCache;
636 cls->info = CLS_CLASS;
637 }
638
639 if (cls->isa->cache == NULL) {
640 cls->isa->cache = (Cache) &emptyCache;
641 cls->isa->info = CLS_META;
642 }
643
644 // methodLists should be:
645 // 1. NULL (Tiger and later only)
646 // 2. A -1 terminated method list array
647 // In either case, CLS_NO_METHOD_ARRAY remains clear.
648 // If the user manipulates the method list directly,
649 // they must use the magic private format.
650
651 // Add the class to the table
652 (void) NXHashInsert (class_hash, cls);
653
654 // Desynchronize
655 OBJC_UNLOCK (&classLock);
656 }
657
658 /***********************************************************************
659 * _objcTweakMethodListPointerForClass.
660 * Change the class's method list pointer to a method list array.
661 * Does nothing if the method list pointer is already a method list array.
662 * If the class is currently in use, methodListLock must be held by the caller.
663 **********************************************************************/
664 static void _objcTweakMethodListPointerForClass (struct objc_class * cls)
665 {
666 struct objc_method_list * originalList;
667 const int initialEntries = 4;
668 int mallocSize;
669 struct objc_method_list ** ptr;
670
671 // Do nothing if methodLists is already an array.
672 if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) return;
673
674 // Remember existing list
675 originalList = (struct objc_method_list *) cls->methodLists;
676
677 // Allocate and zero a method list array
678 mallocSize = sizeof(struct objc_method_list *) * initialEntries;
679 ptr = (struct objc_method_list **) _calloc_internal(1, mallocSize);
680
681 // Insert the existing list into the array
682 ptr[initialEntries - 1] = END_OF_METHODS_LIST;
683 ptr[0] = originalList;
684
685 // Replace existing list with array
686 cls->methodLists = ptr;
687 _class_clearInfo(cls, CLS_NO_METHOD_ARRAY);
688 }
689
690
691 /***********************************************************************
692 * _objc_insertMethods.
693 * Adds methods to a class.
694 * Does not flush any method caches.
695 * Does not take any locks.
696 * If the class is already in use, use class_addMethods() instead.
697 **********************************************************************/
698 void _objc_insertMethods(struct objc_class *cls,
699 struct objc_method_list *mlist)
700 {
701 struct objc_method_list ***list;
702 struct objc_method_list **ptr;
703 int endIndex;
704 int oldSize;
705 int newSize;
706
707 if (!cls->methodLists) {
708 // cls has no methods - simply use this method list
709 cls->methodLists = (struct objc_method_list **)mlist;
710 _class_setInfo(cls, CLS_NO_METHOD_ARRAY);
711 return;
712 }
713
714 // Create method list array if necessary
715 _objcTweakMethodListPointerForClass(cls);
716
717 list = &cls->methodLists;
718
719 // Locate unused entry for insertion point
720 ptr = *list;
721 while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
722 ptr += 1;
723
724 // If array is full, add to it
725 if (*ptr == END_OF_METHODS_LIST)
726 {
727 // Calculate old and new dimensions
728 endIndex = ptr - *list;
729 oldSize = (endIndex + 1) * sizeof(void *);
730 newSize = oldSize + sizeof(struct objc_method_list *); // only increase by 1
731
732 // Grow the method list array by one.
733 // This block may be from user code; don't use _realloc_internal
734 *list = (struct objc_method_list **)realloc(*list, newSize);
735
736 // Zero out addition part of new array
737 bzero (&((*list)[endIndex]), newSize - oldSize);
738
739 // Place new end marker
740 (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
741
742 // Insertion point corresponds to old array end
743 ptr = &((*list)[endIndex]);
744 }
745
746 // Right shift existing entries by one
747 bcopy (*list, (*list) + 1, ((void *) ptr) - ((void *) *list));
748
749 // Insert at method list at beginning of array
750 **list = mlist;
751 }
752
753 /***********************************************************************
754 * _objc_removeMethods.
755 * Remove methods from a class.
756 * Does not take any locks.
757 * Does not flush any method caches.
758 * If the class is currently in use, use class_removeMethods() instead.
759 **********************************************************************/
760 void _objc_removeMethods(struct objc_class *cls,
761 struct objc_method_list *mlist)
762 {
763 struct objc_method_list ***list;
764 struct objc_method_list **ptr;
765
766 if (cls->methodLists == NULL) {
767 // cls has no methods
768 return;
769 }
770 if (cls->methodLists == (struct objc_method_list **)mlist) {
771 // mlist is the class's only method list - erase it
772 cls->methodLists = NULL;
773 return;
774 }
775 if (cls->info & CLS_NO_METHOD_ARRAY) {
776 // cls has only one method list, and this isn't it - do nothing
777 return;
778 }
779
780 // cls has a method list array - search it
781
782 list = &cls->methodLists;
783
784 // Locate list in the array
785 ptr = *list;
786 while (*ptr != mlist) {
787 // fix for radar # 2538790
788 if ( *ptr == END_OF_METHODS_LIST ) return;
789 ptr += 1;
790 }
791
792 // Remove this entry
793 *ptr = 0;
794
795 // Left shift the following entries
796 while (*(++ptr) != END_OF_METHODS_LIST)
797 *(ptr-1) = *ptr;
798 *(ptr-1) = 0;
799 }
800
801 /***********************************************************************
802 * _objc_add_category. Install the specified category's methods and
803 * protocols into the class it augments.
804 * The class is assumed not to be in use yet: no locks are taken and
805 * no method caches are flushed.
806 **********************************************************************/
807 static inline void _objc_add_category(struct objc_class *cls, struct objc_category *category, int version)
808 {
809 if (PrintConnecting) {
810 _objc_inform("CONNECT: attaching category '%s (%s)'", cls->name, category->category_name);
811 }
812
813 // Augment instance methods
814 if (category->instance_methods)
815 _objc_insertMethods (cls, category->instance_methods);
816
817 // Augment class methods
818 if (category->class_methods)
819 _objc_insertMethods (cls->isa, category->class_methods);
820
821 // Augment protocols
822 if ((version >= 5) && category->protocols)
823 {
824 if (cls->isa->version >= 5)
825 {
826 category->protocols->next = cls->protocols;
827 cls->protocols = category->protocols;
828 cls->isa->protocols = category->protocols;
829 }
830 else
831 {
832 _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
833 _objc_inform ("class `%s' must be recompiled\n", category->class_name);
834 }
835 }
836 }
837
838 /***********************************************************************
839 * _objc_add_category_flush_caches. Install the specified category's
840 * methods into the class it augments, and flush the class' method cache.
841 **********************************************************************/
842 static void _objc_add_category_flush_caches(struct objc_class *cls, struct objc_category *category, int version)
843 {
844 // Install the category's methods into its intended class
845 OBJC_LOCK(&methodListLock);
846 _objc_add_category (cls, category, version);
847 OBJC_UNLOCK(&methodListLock);
848
849 // Flush caches so category's methods can get called
850 _objc_flush_caches (cls);
851 }
852
853
854 /***********************************************************************
855 * reverse_cat
856 * Reverse the given linked list of pending categories.
857 * The pending category list is built backwards, and needs to be
858 * reversed before actually attaching the categories to a class.
859 * Returns the head of the new linked list.
860 **********************************************************************/
861 static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat)
862 {
863 if (!cat) return NULL;
864
865 _objc_unresolved_category *prev = NULL;
866 _objc_unresolved_category *cur = cat;
867 _objc_unresolved_category *ahead = cat->next;
868
869 while (cur) {
870 ahead = cur->next;
871 cur->next = prev;
872 prev = cur;
873 cur = ahead;
874 }
875
876 return prev;
877 }
878
879
880 /***********************************************************************
881 * resolve_categories_for_class.
882 * Install all existing categories intended for the specified class.
883 * cls must be a true class and not a metaclass.
884 **********************************************************************/
885 static void resolve_categories_for_class(struct objc_class *cls)
886 {
887 _objc_unresolved_category * pending;
888 _objc_unresolved_category * next;
889
890 // Nothing to do if there are no categories at all
891 if (!category_hash) return;
892
893 // Locate and remove first element in category list
894 // associated with this class
895 pending = NXMapKeyFreeingRemove (category_hash, cls->name);
896
897 // Traverse the list of categories, if any, registered for this class
898
899 // The pending list is built backwards. Reverse it and walk forwards.
900 pending = reverse_cat(pending);
901
902 while (pending) {
903 if (pending->cat) {
904 // Install the category
905 // use the non-flush-cache version since we are only
906 // called from the class intialization code
907 _objc_add_category(cls, pending->cat, pending->version);
908 }
909
910 // Delink and reclaim this registration
911 next = pending->next;
912 _free_internal(pending);
913 pending = next;
914 }
915 }
916
917
918 /***********************************************************************
919 * _objc_resolve_categories_for_class.
920 * Public version of resolve_categories_for_class. This was
921 * exported pre-10.4 for Omni et al. to workaround a problem
922 * with too-lazy category attachment.
923 * cls should be a class, but this function can also cope with metaclasses.
924 **********************************************************************/
925 void _objc_resolve_categories_for_class(struct objc_class *cls)
926 {
927
928 // If cls is a metaclass, get the class.
929 // resolve_categories_for_class() requires a real class to work correctly.
930 if (ISMETA(cls)) {
931 if (strncmp(cls->name, "_%", 2) == 0) {
932 // Posee's meta's name is smashed and isn't in the class_hash,
933 // so objc_getClass doesn't work.
934 char *baseName = strchr(cls->name, '%'); // get posee's real name
935 cls = objc_getClass(baseName);
936 } else {
937 cls = objc_getClass(cls->name);
938 }
939 }
940
941 resolve_categories_for_class(cls);
942 }
943
944
945 /***********************************************************************
946 * _objc_register_category.
947 * Process a category read from an image.
948 * If the category's class exists, attach the category immediately.
949 * If the category's class does not exist yet, pend the category for
950 * later attachment. Pending categories are attached in the order
951 * they were discovered.
952 **********************************************************************/
953 static void _objc_register_category(struct objc_category *cat, long version)
954 {
955 _objc_unresolved_category * new_cat;
956 _objc_unresolved_category * old;
957 struct objc_class *theClass;
958
959 // If the category's class exists, attach the category.
960 if ((theClass = objc_lookUpClass(cat->class_name))) {
961 _objc_add_category_flush_caches(theClass, cat, version);
962 return;
963 }
964
965 // If the category's class exists but is unconnected,
966 // then attach the category to the class but don't bother
967 // flushing any method caches (because they must be empty).
968 // YES unconnected, NO class_handler
969 if ((theClass = look_up_class(cat->class_name, YES, NO))) {
970 _objc_add_category(theClass, cat, version);
971 return;
972 }
973
974
975 // Category's class does not exist yet.
976 // Save the category for later attachment.
977
978 if (PrintConnecting) {
979 _objc_inform("CONNECT: pending category '%s (%s)'", cat->class_name, cat->category_name);
980 }
981
982 // Create category lookup table if needed
983 if (!category_hash)
984 category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
985 128,
986 _objc_internal_zone ());
987
988 // Locate an existing list of categories, if any, for the class.
989 old = NXMapGet (category_hash, cat->class_name);
990
991 // Register the category to be fixed up later.
992 // The category list is built backwards, and is reversed again
993 // by resolve_categories_for_class().
994 new_cat = _malloc_internal(sizeof(_objc_unresolved_category));
995 new_cat->next = old;
996 new_cat->cat = cat;
997 new_cat->version = version;
998 (void) NXMapKeyCopyingInsert (category_hash, cat->class_name, new_cat);
999 }
1000
1001
1002 /***********************************************************************
1003 * _objc_read_categories_from_image.
1004 * Read all categories from the given image.
1005 * Install them on their parent classes, or register them for later
1006 * installation.
1007 * Register them for later +load, if implemented.
1008 **********************************************************************/
1009 static void _objc_read_categories_from_image (header_info * hi)
1010 {
1011 Module mods;
1012 unsigned int midx;
1013
1014 if (_objcHeaderIsReplacement(hi)) {
1015 // Ignore any categories in this image
1016 return;
1017 }
1018
1019 // Major loop - process all modules in the header
1020 mods = hi->mod_ptr;
1021
1022 // NOTE: The module and category lists are traversed backwards
1023 // to preserve the pre-10.4 processing order. Changing the order
1024 // would have a small chance of introducing binary compatibility bugs.
1025 midx = hi->mod_count;
1026 while (midx-- > 0) {
1027 unsigned int index;
1028 unsigned int total;
1029
1030 // Nothing to do for a module without a symbol table
1031 if (mods[midx].symtab == NULL)
1032 continue;
1033
1034 // Total entries in symbol table (class entries followed
1035 // by category entries)
1036 total = mods[midx].symtab->cls_def_cnt +
1037 mods[midx].symtab->cat_def_cnt;
1038
1039 // Minor loop - register all categories from given module
1040 index = total;
1041 while (index-- > mods[midx].symtab->cls_def_cnt) {
1042 struct objc_category *cat = mods[midx].symtab->defs[index];
1043 _objc_register_category(cat, mods[midx].version);
1044 add_category_to_loadable_list(cat);
1045 }
1046 }
1047 }
1048
1049
1050 /***********************************************************************
1051 * _headerForAddress.
1052 * addr can be a class or a category
1053 **********************************************************************/
1054 static const header_info *_headerForAddress(void *addr)
1055 {
1056 unsigned long size;
1057 unsigned long seg;
1058 header_info * hInfo;
1059
1060 // Check all headers in the vector
1061 for (hInfo = FirstHeader; hInfo != NULL; hInfo = hInfo->next)
1062 {
1063 // Locate header data, if any
1064 if (!hInfo->objcSegmentHeader) continue;
1065 seg = hInfo->objcSegmentHeader->vmaddr + hInfo->image_slide;
1066 size = hInfo->objcSegmentHeader->filesize;
1067
1068 // Is the class in this header?
1069 if ((seg <= (unsigned long) addr) &&
1070 ((unsigned long) addr < (seg + size)))
1071 return hInfo;
1072 }
1073
1074 // Not found
1075 return 0;
1076 }
1077
1078
1079 /***********************************************************************
1080 * _headerForClass
1081 * Return the image header containing this class, or NULL.
1082 * Returns NULL on runtime-constructed classes, and the NSCF classes.
1083 **********************************************************************/
1084 static const header_info *_headerForClass(struct objc_class *cls)
1085 {
1086 return _headerForAddress(cls);
1087 }
1088
1089
1090 /***********************************************************************
1091 * _nameForHeader.
1092 **********************************************************************/
1093 const char * _nameForHeader (const headerType * header)
1094 {
1095 return _getObjcHeaderName ((headerType *) header);
1096 }
1097
1098
1099 /***********************************************************************
1100 * class_is_connected.
1101 * Returns TRUE if class cls is connected.
1102 * A connected class has either a connected superclass or a NULL superclass,
1103 * and is present in class_hash.
1104 **********************************************************************/
1105 static BOOL class_is_connected(struct objc_class *cls)
1106 {
1107 BOOL result;
1108 OBJC_LOCK(&classLock);
1109 result = NXHashMember(class_hash, cls);
1110 OBJC_UNLOCK(&classLock);
1111 return result;
1112 }
1113
1114
1115 /***********************************************************************
1116 * pendingClassRefsMapTable. Return a pointer to the lookup table for
1117 * pending class refs.
1118 **********************************************************************/
1119 static inline NXMapTable *pendingClassRefsMapTable(void)
1120 {
1121 // Allocate table if needed
1122 if (!pendingClassRefsMap) {
1123 pendingClassRefsMap =
1124 NXCreateMapTableFromZone(NXStrValueMapPrototype,
1125 10, _objc_internal_zone ());
1126 }
1127
1128 // Return table pointer
1129 return pendingClassRefsMap;
1130 }
1131
1132
1133 /***********************************************************************
1134 * pendingSubclassesMapTable. Return a pointer to the lookup table for
1135 * pending subclasses.
1136 **********************************************************************/
1137 static inline NXMapTable *pendingSubclassesMapTable(void)
1138 {
1139 // Allocate table if needed
1140 if (!pendingSubclassesMap) {
1141 pendingSubclassesMap =
1142 NXCreateMapTableFromZone(NXStrValueMapPrototype,
1143 10, _objc_internal_zone ());
1144 }
1145
1146 // Return table pointer
1147 return pendingSubclassesMap;
1148 }
1149
1150
1151 /***********************************************************************
1152 * pendClassInstallation
1153 * Finish connecting class cls when its superclass becomes connected.
1154 * Check for multiple pends of the same class because connect_class does not.
1155 **********************************************************************/
1156 static void pendClassInstallation(struct objc_class *cls,
1157 const char *superName)
1158 {
1159 NXMapTable *table;
1160 PendingSubclass *pending;
1161 PendingSubclass *oldList;
1162 PendingSubclass *l;
1163
1164 // Create and/or locate pending class lookup table
1165 table = pendingSubclassesMapTable ();
1166
1167 // Make sure this class isn't already in the pending list.
1168 oldList = NXMapGet (table, superName);
1169 for (l = oldList; l != NULL; l = l->next) {
1170 if (l->subclass == cls) return; // already here, nothing to do
1171 }
1172
1173 // Create entry referring to this class
1174 pending = _malloc_internal(sizeof(PendingSubclass));
1175 pending->subclass = cls;
1176
1177 // Link new entry into head of list of entries for this class
1178 pending->next = oldList;
1179
1180 // (Re)place entry list in the table
1181 (void) NXMapKeyCopyingInsert (table, superName, pending);
1182 }
1183
1184
1185 /***********************************************************************
1186 * pendClassReference
1187 * Fix up a class ref when the class with the given name becomes connected.
1188 **********************************************************************/
1189 static void pendClassReference(struct objc_class **ref,
1190 const char *className)
1191 {
1192 NXMapTable *table;
1193 PendingClassRef *pending;
1194
1195 // Create and/or locate pending class lookup table
1196 table = pendingClassRefsMapTable ();
1197
1198 // Create entry containing the class reference
1199 pending = _malloc_internal(sizeof(PendingClassRef));
1200 pending->ref = ref;
1201
1202 // Link new entry into head of list of entries for this class
1203 pending->next = NXMapGet (table, className);
1204
1205 // (Re)place entry list in the table
1206 (void) NXMapKeyCopyingInsert (table, className, pending);
1207
1208 if (PrintConnecting) {
1209 _objc_inform("CONNECT: pended reference to class '%s' at %p",
1210 className, (void *)ref);
1211 }
1212 }
1213
1214
1215 /***********************************************************************
1216 * resolve_references_to_class
1217 * Fix up any pending class refs to this class.
1218 **********************************************************************/
1219 static void resolve_references_to_class(struct objc_class *cls)
1220 {
1221 PendingClassRef *pending;
1222
1223 if (!pendingClassRefsMap) return; // no unresolved refs for any class
1224
1225 pending = NXMapGet(pendingClassRefsMap, cls->name);
1226 if (!pending) return; // no unresolved refs for this class
1227
1228 NXMapKeyFreeingRemove(pendingClassRefsMap, cls->name);
1229
1230 if (PrintConnecting) {
1231 _objc_inform("CONNECT: resolving references to class '%s'", cls->name);
1232 }
1233
1234 while (pending) {
1235 PendingClassRef *next = pending->next;
1236 if (pending->ref) *pending->ref = cls;
1237 _free_internal(pending);
1238 pending = next;
1239 }
1240
1241 if (NXCountMapTable(pendingClassRefsMap) == 0) {
1242 NXFreeMapTable(pendingClassRefsMap);
1243 pendingClassRefsMap = NULL;
1244 }
1245 }
1246
1247
1248 /***********************************************************************
1249 * resolve_subclasses_of_class
1250 * Fix up any pending subclasses of this class.
1251 **********************************************************************/
1252 static void resolve_subclasses_of_class(struct objc_class *cls)
1253 {
1254 PendingSubclass *pending;
1255
1256 if (!pendingSubclassesMap) return; // no unresolved subclasses
1257
1258 pending = NXMapGet(pendingSubclassesMap, cls->name);
1259 if (!pending) return; // no unresolved subclasses for this class
1260
1261 NXMapKeyFreeingRemove(pendingSubclassesMap, cls->name);
1262
1263 // Destroy the pending table if it's now empty, to save memory.
1264 if (NXCountMapTable(pendingSubclassesMap) == 0) {
1265 NXFreeMapTable(pendingSubclassesMap);
1266 pendingSubclassesMap = NULL;
1267 }
1268
1269 if (PrintConnecting) {
1270 _objc_inform("CONNECT: resolving subclasses of class '%s'", cls->name);
1271 }
1272
1273 while (pending) {
1274 PendingSubclass *next = pending->next;
1275 if (pending->subclass) connect_class(pending->subclass);
1276 _free_internal(pending);
1277 pending = next;
1278 }
1279 }
1280
1281
1282 /***********************************************************************
1283 * get_base_method_list
1284 * Returns the method list containing the class's own methods,
1285 * ignoring any method lists added by categories or class_addMethods.
1286 * Called only by add_class_to_loadable_list.
1287 * Does not hold methodListLock because add_class_to_loadable_list
1288 * does not manipulate in-use classes.
1289 **********************************************************************/
1290 static struct objc_method_list *get_base_method_list(struct objc_class *cls)
1291 {
1292 struct objc_method_list **ptr;
1293
1294 if (!cls->methodLists) return NULL;
1295 if (cls->info & CLS_NO_METHOD_ARRAY) return (struct objc_method_list *)cls->methodLists;
1296 ptr = cls->methodLists;
1297 if (!*ptr || *ptr == END_OF_METHODS_LIST) return NULL;
1298 while ( *ptr != 0 && *ptr != END_OF_METHODS_LIST ) { ptr++; }
1299 --ptr;
1300 return *ptr;
1301 }
1302
1303
1304 /***********************************************************************
1305 * add_class_to_loadable_list
1306 * Class cls has just become connected. Schedule it for +load if
1307 * it implements a +load method.
1308 **********************************************************************/
1309 static void add_class_to_loadable_list(struct objc_class *cls)
1310 {
1311 IMP method = NULL;
1312 struct objc_method_list *mlist;
1313
1314 mlist = get_base_method_list(cls->isa);
1315 if (mlist) {
1316 method = lookupNamedMethodInMethodList (mlist, "load");
1317 }
1318 // Don't bother if cls has no +load method
1319 if (!method) return;
1320
1321 if (PrintLoading) {
1322 _objc_inform("LOAD: class '%s' scheduled for +load", cls->name);
1323 }
1324
1325 if (loadable_classes_used == loadable_classes_allocated) {
1326 loadable_classes_allocated = loadable_classes_allocated*2 + 16;
1327 loadable_classes =
1328 _realloc_internal(loadable_classes,
1329 loadable_classes_allocated *
1330 sizeof(struct loadable_class));
1331 }
1332
1333 loadable_classes[loadable_classes_used].cls = cls;
1334 loadable_classes[loadable_classes_used].method = method;
1335 loadable_classes_used++;
1336 }
1337
1338
1339 /***********************************************************************
1340 * add_category_to_loadable_list
1341 * Category cat's parent class exists and the category has been attached
1342 * to its class. Schedule this category for +load after its parent class
1343 * becomes connected and has its own +load method called.
1344 **********************************************************************/
1345 static void add_category_to_loadable_list(struct objc_category *cat)
1346 {
1347 IMP method = NULL;
1348 struct objc_method_list *mlist;
1349
1350 mlist = cat->class_methods;
1351 if (mlist) {
1352 method = lookupNamedMethodInMethodList (mlist, "load");
1353 }
1354 // Don't bother if cat has no +load method
1355 if (!method) return;
1356
1357 if (PrintLoading) {
1358 _objc_inform("LOAD: category '%s(%s)' scheduled for +load",
1359 cat->class_name, cat->category_name);
1360 }
1361
1362 if (loadable_categories_used == loadable_categories_allocated) {
1363 loadable_categories_allocated = loadable_categories_allocated*2 + 16;
1364 loadable_categories =
1365 _realloc_internal(loadable_categories,
1366 loadable_categories_allocated *
1367 sizeof(struct loadable_category));
1368 }
1369
1370 loadable_categories[loadable_categories_used].cat = cat;
1371 loadable_categories[loadable_categories_used].method = method;
1372 loadable_categories_used++;
1373 }
1374
1375
1376 /***********************************************************************
1377 * remove_class_from_loadable_list
1378 * Class cls may have been loadable before, but it is now no longer
1379 * loadable (because its image is being unmapped).
1380 **********************************************************************/
1381 static void remove_class_from_loadable_list(struct objc_class *cls)
1382 {
1383 if (loadable_classes) {
1384 int i;
1385 for (i = 0; i < loadable_classes_used; i++) {
1386 if (loadable_classes[i].cls == cls) {
1387 loadable_classes[i].cls = NULL;
1388 if (PrintLoading) {
1389 _objc_inform("LOAD: class '%s' unscheduled for +load", cls->name);
1390 }
1391 return;
1392 }
1393 }
1394 }
1395 }
1396
1397
1398 /***********************************************************************
1399 * remove_category_from_loadable_list
1400 * Category cat may have been loadable before, but it is now no longer
1401 * loadable (because its image is being unmapped).
1402 **********************************************************************/
1403 static void remove_category_from_loadable_list(struct objc_category *cat)
1404 {
1405 if (loadable_categories) {
1406 int i;
1407 for (i = 0; i < loadable_categories_used; i++) {
1408 if (loadable_categories[i].cat == cat) {
1409 loadable_categories[i].cat = NULL;
1410 if (PrintLoading) {
1411 _objc_inform("LOAD: category '%s(%s)' unscheduled for +load",
1412 cat->class_name, cat->category_name);
1413 }
1414 return;
1415 }
1416 }
1417 }
1418 }
1419
1420
1421 /***********************************************************************
1422 * call_class_loads
1423 * Call all pending class +load methods.
1424 * If new classes become loadable, +load is NOT called for them.
1425 *
1426 * Called only by call_load_methods().
1427 **********************************************************************/
1428 static void call_class_loads(void)
1429 {
1430 int i;
1431
1432 // Detach current loadable list.
1433 struct loadable_class *classes = loadable_classes;
1434 int used = loadable_classes_used;
1435 loadable_classes = NULL;
1436 loadable_classes_allocated = 0;
1437 loadable_classes_used = 0;
1438
1439 // Call all +loads for the detached list.
1440 for (i = 0; i < used; i++) {
1441 struct objc_class *cls = classes[i].cls;
1442 IMP load_method = classes[i].method;
1443 if (!cls) continue;
1444
1445 if (PrintLoading) {
1446 _objc_inform("LOAD: +[%s load]\n", cls->name);
1447 }
1448 (*load_method) ((id) cls, @selector(load));
1449 }
1450
1451 // Destroy the detached list.
1452 if (classes) _free_internal(classes);
1453 }
1454
1455
1456 /***********************************************************************
1457 * call_category_loads
1458 * Call some pending category +load methods.
1459 * The parent class of the +load-implementing categories has all of
1460 * its categories attached, in case some are lazily waiting for +initalize.
1461 * Don't call +load unless the parent class is connected.
1462 * If new categories become loadable, +load is NOT called, and they
1463 * are added to the end of the loadable list, and we return TRUE.
1464 * Return FALSE if no new categories became loadable.
1465 *
1466 * Called only by call_load_methods().
1467 **********************************************************************/
1468 static BOOL call_category_loads(void)
1469 {
1470 int i, shift;
1471 BOOL new_categories_added = NO;
1472
1473 // Detach current loadable list.
1474 struct loadable_category *cats = loadable_categories;
1475 int used = loadable_categories_used;
1476 int allocated = loadable_categories_allocated;
1477 loadable_categories = NULL;
1478 loadable_categories_allocated = 0;
1479 loadable_categories_used = 0;
1480
1481 // Call all +loads for the detached list.
1482 for (i = 0; i < used; i++) {
1483 struct objc_category *cat = cats[i].cat;
1484 IMP load_method = cats[i].method;
1485 struct objc_class *cls;
1486 if (!cat) continue;
1487
1488 cls = objc_getClass(cat->class_name);
1489 if (cls && class_is_connected(cls)) {
1490 if (PrintLoading) {
1491 _objc_inform("LOAD: +[%s(%s) load]\n",
1492 cls->name, cat->category_name);
1493 }
1494 (*load_method) ((id) cls, @selector(load));
1495 cats[i].cat = NULL;
1496 }
1497 }
1498
1499 // Compact detached list (order-preserving)
1500 shift = 0;
1501 for (i = 0; i < used; i++) {
1502 if (cats[i].cat) {
1503 cats[i-shift] = cats[i];
1504 } else {
1505 shift++;
1506 }
1507 }
1508 used -= shift;
1509
1510 // Copy any new +load candidates from the new list to the detached list.
1511 new_categories_added = (loadable_categories_used > 0);
1512 for (i = 0; i < loadable_categories_used; i++) {
1513 if (used == allocated) {
1514 allocated = allocated*2 + 16;
1515 cats = _realloc_internal(cats, allocated *
1516 sizeof(struct loadable_category));
1517 }
1518 cats[used++] = loadable_categories[i];
1519 }
1520
1521 // Destroy the new list.
1522 if (loadable_categories) _free_internal(loadable_categories);
1523
1524 // Reattach the (now augmented) detached list.
1525 // But if there's nothing left to load, destroy the list.
1526 if (used) {
1527 loadable_categories = cats;
1528 loadable_categories_used = used;
1529 loadable_categories_allocated = allocated;
1530 } else {
1531 if (cats) _free_internal(cats);
1532 loadable_categories = NULL;
1533 loadable_categories_used = 0;
1534 loadable_categories_allocated = 0;
1535 }
1536
1537 if (PrintLoading) {
1538 if (loadable_categories_used != 0) {
1539 _objc_inform("LOAD: %d categories still waiting for +load\n",
1540 loadable_categories_used);
1541 }
1542 }
1543
1544 return new_categories_added;
1545 }
1546
1547
1548 /***********************************************************************
1549 * call_load_methods
1550 * Call all pending class and category +load methods.
1551 * Class +load methods are called superclass-first.
1552 * Category +load methods are not called until after the parent class's +load.
1553 *
1554 * This method must be RE-ENTRANT, because a +load could trigger
1555 * more image mapping. In addition, the superclass-first ordering
1556 * must be preserved in the face of re-entrant calls. Therefore,
1557 * only the OUTERMOST call of this function will do anything, and
1558 * that call will handle all loadable classes, even those generated
1559 * while it was running.
1560 *
1561 * The sequence below preserves +load ordering in the face of
1562 * image loading during a +load, and make sure that no
1563 * +load method is forgotten because it was added during
1564 * a +load call.
1565 * Sequence:
1566 * 1. Repeatedly call class +loads until there aren't any more
1567 * 2. Call category +loads ONCE.
1568 * 3. Run more +loads if:
1569 * (a) there are more classes to load, OR
1570 * (b) there are some potential category +loads that have
1571 * still never been attempted.
1572 * Category +loads are only run once to ensure "parent class first"
1573 * ordering, even if a category +load triggers a new loadable class
1574 * and a new loadable category attached to that class.
1575 *
1576 * fixme this is not thread-safe, but neither is the rest of image mapping.
1577 **********************************************************************/
1578 static void call_load_methods(void)
1579 {
1580 static pthread_t load_method_thread NOBSS = NULL;
1581 BOOL more_categories;
1582
1583 if (load_method_thread) {
1584 // +loads are already being called. Do nothing, but complain
1585 // if it looks like multithreaded use of this thread-unsafe code.
1586
1587 if (! pthread_equal(load_method_thread, pthread_self())) {
1588 _objc_inform("WARNING: multi-threaded library loading detected "
1589 "(implementation is not thread-safe)");
1590 }
1591 return;
1592 }
1593
1594 // Nobody else is calling +loads, so we should do it ourselves.
1595 load_method_thread = pthread_self();
1596
1597 do {
1598 // 1. Repeatedly call class +loads until there aren't any more
1599 while (loadable_classes_used > 0) {
1600 call_class_loads();
1601 }
1602
1603 // 2. Call category +loads ONCE
1604 more_categories = call_category_loads();
1605
1606 // 3. Run more +loads if there are classes OR more untried categories
1607 } while (loadable_classes_used > 0 || more_categories);
1608
1609 load_method_thread = NULL;
1610 }
1611
1612
1613 /***********************************************************************
1614 * really_connect_class
1615 * Connect cls to superclass supercls unconditionally.
1616 * Also adjust the class hash tables and handle +load and pended subclasses.
1617 *
1618 * This should be called from connect_class() ONLY.
1619 **********************************************************************/
1620 static void really_connect_class(struct objc_class *cls,
1621 struct objc_class *supercls)
1622 {
1623 struct objc_class *oldCls;
1624 struct objc_class *meta = cls->isa;
1625
1626 // Wire the classes together.
1627 if (supercls) {
1628 cls->super_class = supercls;
1629 meta->super_class = supercls->isa;
1630 meta->isa = supercls->isa->isa;
1631 } else {
1632 cls->super_class = NULL; // superclass of root class is NULL
1633 meta->super_class = cls; // superclass of root metaclass is root class
1634 meta->isa = meta; // metaclass of root metaclass is root metaclass
1635 }
1636
1637 OBJC_LOCK(&classLock);
1638
1639 // Update hash tables.
1640 NXHashRemove(unconnected_class_hash, cls);
1641 oldCls = NXHashInsert(class_hash, cls);
1642
1643 // Delete unconnected_class_hash if it is now empty.
1644 if (NXCountHashTable(unconnected_class_hash) == 0) {
1645 NXFreeHashTable(unconnected_class_hash);
1646 unconnected_class_hash = NULL;
1647 }
1648
1649 OBJC_UNLOCK(&classLock);
1650
1651 // Warn if the new class has the same name as a previously-installed class.
1652 // The new class is kept and the old class is discarded.
1653 if (oldCls) {
1654 const header_info *oldHeader = _headerForClass(oldCls);
1655 const header_info *newHeader = _headerForClass(cls);
1656 const char *oldName = _nameForHeader(oldHeader->mhdr);
1657 const char *newName = _nameForHeader(newHeader->mhdr);
1658
1659 _objc_inform ("Both %s and %s have implementations of class %s.",
1660 oldName, newName, oldCls->name);
1661 _objc_inform ("Using implementation from %s.", newName);
1662 }
1663
1664 // Prepare for +load and connect newly-connectable subclasses
1665 add_class_to_loadable_list(cls);
1666 resolve_subclasses_of_class(cls);
1667
1668 // GC debugging: make sure all classes with -dealloc also have -finalize
1669 if (CheckFinalizers) {
1670 extern IMP findIMPInClass(Class cls, SEL sel);
1671 if (findIMPInClass(cls, sel_getUid("dealloc")) &&
1672 ! findIMPInClass(cls, sel_getUid("finalize")))
1673 {
1674 _objc_inform("GC: class '%s' implements -dealloc but not -finalize", cls->name);
1675 }
1676 }
1677
1678 // Debugging: if this class has ivars, make sure this class's ivars don't
1679 // overlap with its super's. This catches some broken fragile base classes.
1680 // Do not use super->instance_size vs. self->ivar[0] to check this.
1681 // Ivars may be packed across instance_size boundaries.
1682 if (DebugFragileSuperclasses && cls->ivars && cls->ivars->ivar_count) {
1683 struct objc_class *ivar_cls = supercls;
1684
1685 // Find closest superclass that has some ivars, if one exists.
1686 while (ivar_cls &&
1687 (!ivar_cls->ivars || ivar_cls->ivars->ivar_count == 0))
1688 {
1689 ivar_cls = ivar_cls->super_class;
1690 }
1691
1692 if (ivar_cls) {
1693 // Compare superclass's last ivar to this class's first ivar
1694 struct objc_ivar *super_ivar =
1695 &ivar_cls->ivars->ivar_list[ivar_cls->ivars->ivar_count - 1];
1696 struct objc_ivar *self_ivar =
1697 &cls->ivars->ivar_list[0];
1698
1699 // fixme could be smarter about super's ivar size
1700 if (self_ivar->ivar_offset <= super_ivar->ivar_offset) {
1701 _objc_inform("WARNING: ivars of superclass '%s' and "
1702 "subclass '%s' overlap; superclass may have "
1703 "changed since subclass was compiled",
1704 ivar_cls->name, cls->name);
1705 }
1706 }
1707 }
1708 }
1709
1710
1711 /***********************************************************************
1712 * connect_class
1713 * Connect class cls to its superclasses, if possible.
1714 * If cls becomes connected, move it from unconnected_class_hash
1715 * to connected_class_hash.
1716 * Returns TRUE if cls is connected.
1717 * Returns FALSE if cls could not be connected for some reason
1718 * (missing superclass or still-unconnected superclass)
1719 **********************************************************************/
1720 static BOOL connect_class(struct objc_class *cls)
1721 {
1722 if (class_is_connected(cls)) {
1723 // This class is already connected to its superclass.
1724 // Do nothing.
1725 return TRUE;
1726 }
1727 else if (cls->super_class == NULL) {
1728 // This class is a root class.
1729 // Connect it to itself.
1730
1731 if (PrintConnecting) {
1732 _objc_inform("CONNECT: class '%s' now connected (root class)",
1733 cls->name);
1734 }
1735
1736 really_connect_class(cls, NULL);
1737 return TRUE;
1738 }
1739 else {
1740 // This class is not a root class and is not yet connected.
1741 // Connect it if its superclass and root class are already connected.
1742 // Otherwise, add this class to the to-be-connected list,
1743 // pending the completion of its superclass and root class.
1744
1745 // At this point, cls->super_class and cls->isa->isa are still STRINGS
1746 char *supercls_name = (char *)cls->super_class;
1747 struct objc_class *supercls;
1748
1749 // YES unconnected, YES class handler
1750 if (NULL == (supercls = look_up_class(supercls_name, YES, YES))) {
1751 // Superclass does not exist yet.
1752 // pendClassInstallation will handle duplicate pends of this class
1753 pendClassInstallation(cls, supercls_name);
1754
1755 if (PrintConnecting) {
1756 _objc_inform("CONNECT: class '%s' NOT connected (missing super)", cls->name);
1757 }
1758 return FALSE;
1759 }
1760
1761 if (! connect_class(supercls)) {
1762 // Superclass exists but is not yet connected.
1763 // pendClassInstallation will handle duplicate pends of this class
1764 pendClassInstallation(cls, supercls_name);
1765
1766 if (PrintConnecting) {
1767 _objc_inform("CONNECT: class '%s' NOT connected (unconnected super)", cls->name);
1768 }
1769 return FALSE;
1770 }
1771
1772 // Superclass exists and is connected.
1773 // Connect this class to the superclass.
1774
1775 if (PrintConnecting) {
1776 _objc_inform("CONNECT: class '%s' now connected", cls->name);
1777 }
1778
1779 really_connect_class(cls, supercls);
1780 return TRUE;
1781 }
1782 }
1783
1784
1785 /***********************************************************************
1786 * _objc_read_classes_from_image.
1787 * Read classes from the given image, perform assorted minor fixups,
1788 * Does not connect classes to superclasses.
1789 * Does attach pended categories to the classes.
1790 * Adds all classes to unconnected_class_hash. class_hash is unchanged.
1791 **********************************************************************/
1792 static void _objc_read_classes_from_image(header_info *hi)
1793 {
1794 unsigned int index;
1795 unsigned int midx;
1796 Module mods;
1797 int isBundle = (hi->mhdr->filetype == MH_BUNDLE);
1798
1799 if (_objcHeaderIsReplacement(hi)) {
1800 // Ignore any classes in this image
1801 return;
1802 }
1803
1804 // class_hash starts small, enough only for libobjc itself.
1805 // If other Objective-C libraries are found, immediately resize
1806 // class_hash, assuming that Foundation and AppKit are about
1807 // to add lots of classes.
1808 OBJC_LOCK(&classLock);
1809 if (hi->mhdr != &_mh_dylib_header && _NXHashCapacity(class_hash) < 1024) {
1810 _NXHashRehashToCapacity(class_hash, 1024);
1811 }
1812 OBJC_UNLOCK(&classLock);
1813
1814 // Major loop - process all modules in the image
1815 mods = hi->mod_ptr;
1816 for (midx = 0; midx < hi->mod_count; midx += 1)
1817 {
1818 // Skip module containing no classes
1819 if (mods[midx].symtab == NULL)
1820 continue;
1821
1822 // Minor loop - process all the classes in given module
1823 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
1824 {
1825 struct objc_class * newCls;
1826
1827 // Locate the class description pointer
1828 newCls = mods[midx].symtab->defs[index];
1829
1830 // Classes loaded from Mach-O bundles can be unloaded later.
1831 // Nothing uses this class yet, so _class_setInfo is not needed.
1832 if (isBundle) newCls->info |= CLS_FROM_BUNDLE;
1833 if (isBundle) newCls->isa->info |= CLS_FROM_BUNDLE;
1834
1835 // Use common static empty cache instead of NULL
1836 if (newCls->cache == NULL)
1837 newCls->cache = (Cache) &emptyCache;
1838 if (newCls->isa->cache == NULL)
1839 newCls->isa->cache = (Cache) &emptyCache;
1840
1841 // Set metaclass version
1842 newCls->isa->version = mods[midx].version;
1843
1844 // methodLists is NULL or a single list, not an array
1845 newCls->info |= CLS_NO_METHOD_ARRAY;
1846 newCls->isa->info |= CLS_NO_METHOD_ARRAY;
1847
1848 // Install into unconnected_class_hash
1849 OBJC_LOCK(&classLock);
1850 if (!unconnected_class_hash) {
1851 unconnected_class_hash =
1852 NXCreateHashTableFromZone(classHashPrototype, 128, NULL,
1853 _objc_internal_zone());
1854 }
1855 NXHashInsert(unconnected_class_hash, newCls);
1856 OBJC_UNLOCK(&classLock);
1857
1858 // Fix up pended class refs to this class, if any
1859 resolve_references_to_class(newCls);
1860
1861 // Attach pended categories for this class, if any
1862 resolve_categories_for_class(newCls);
1863 }
1864 }
1865 }
1866
1867
1868 /***********************************************************************
1869 * _objc_connect_classes_from_image.
1870 * Connect the classes in the given image to their superclasses,
1871 * or register them for later connection if any superclasses are missing.
1872 **********************************************************************/
1873 static void _objc_connect_classes_from_image(header_info *hi)
1874 {
1875 unsigned int index;
1876 unsigned int midx;
1877 Module mods;
1878 BOOL replacement = _objcHeaderIsReplacement(hi);
1879
1880 // Major loop - process all modules in the image
1881 mods = hi->mod_ptr;
1882 for (midx = 0; midx < hi->mod_count; midx += 1)
1883 {
1884 // Skip module containing no classes
1885 if (mods[midx].symtab == NULL)
1886 continue;
1887
1888 // Minor loop - process all the classes in given module
1889 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
1890 {
1891 struct objc_class *cls = mods[midx].symtab->defs[index];
1892 if (! replacement) {
1893 BOOL connected = connect_class(cls);
1894 if (connected && callbackFunction) {
1895 (*callbackFunction)(cls, 0);
1896 }
1897 } else {
1898 // Replacement image - fix up super_class only (#3704817)
1899 const char *super_name = (const char *) cls->super_class;
1900 if (super_name) cls->super_class = objc_getClass(super_name);
1901 }
1902 }
1903 }
1904 }
1905
1906
1907 /***********************************************************************
1908 * _objc_map_class_refs_for_image. Convert the class ref entries from
1909 * a class name string pointer to a class pointer. If the class does
1910 * not yet exist, the reference is added to a list of pending references
1911 * to be fixed up at a later date.
1912 **********************************************************************/
1913 static void _objc_map_class_refs_for_image (header_info * hi)
1914 {
1915 struct objc_class * * cls_refs;
1916 unsigned int size;
1917 unsigned int index;
1918
1919 // Locate class refs in image
1920 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
1921 if (!cls_refs)
1922 return;
1923 cls_refs = (struct objc_class * *) ((unsigned long) cls_refs + hi->image_slide);
1924
1925 // Process each class ref
1926 for (index = 0; index < size; index += 1)
1927 {
1928 const char * ref;
1929 struct objc_class * cls;
1930
1931 // Get ref to convert from name string to class pointer
1932 ref = (const char *) cls_refs[index];
1933
1934 // Get pointer to class of this name
1935 // YES unconnected, YES class loader
1936 cls = look_up_class(ref, YES, YES);
1937 if (cls) {
1938 // Referenced class exists. Fix up the reference.
1939 cls_refs[index] = cls;
1940 } else {
1941 // Referenced class does not exist yet. Insert a placeholder
1942 // class and fix up the reference later.
1943 pendClassReference (&cls_refs[index], ref);
1944 cls_refs[index] = _objc_getNonexistentClass ();
1945 }
1946 }
1947 }
1948
1949
1950 /***********************************************************************
1951 * _objc_remove_pending_class_refs_in_image
1952 * Delete any pending class ref fixups for class refs in the given image,
1953 * because the image is about to be unloaded.
1954 **********************************************************************/
1955 static void _objc_remove_pending_class_refs_in_image(header_info *hi)
1956 {
1957 struct objc_class **cls_refs, **cls_refs_end;
1958 unsigned int size;
1959
1960 if (!pendingClassRefsMap) return;
1961
1962 // Locate class refs in this image
1963 cls_refs = _getObjcClassRefs ((headerType *) hi->mhdr, &size);
1964 if (!cls_refs)
1965 return;
1966 cls_refs = (struct objc_class **) ((uintptr_t)cls_refs + hi->image_slide);
1967 cls_refs_end = (struct objc_class **)(size + (uintptr_t)cls_refs);
1968
1969 // Search the pending class ref table for class refs in this range.
1970 // The class refs may have already been stomped with nonexistentClass,
1971 // so there's no way to recover the original class name.
1972
1973 const char *key;
1974 PendingClassRef *pending;
1975 NXMapState state = NXInitMapState(pendingClassRefsMap);
1976 while(NXNextMapState(pendingClassRefsMap, &state,
1977 (const void **)&key, (const void **)&pending))
1978 {
1979 for ( ; pending != NULL; pending = pending->next) {
1980 if (pending->ref >= cls_refs && pending->ref < cls_refs_end) {
1981 pending->ref = NULL;
1982 }
1983 }
1984 }
1985 }
1986
1987
1988 /***********************************************************************
1989 * map_selrefs. Register each selector in the specified array. If a
1990 * given selector is already registered, update this array to point to
1991 * the registered selector string.
1992 * If copy is TRUE, all selector data is always copied. This is used
1993 * for registering selectors from unloadable bundles, so the selector
1994 * can still be used after the bundle's data segment is unmapped.
1995 * Returns YES if dst was written to, NO if it was unchanged.
1996 **********************************************************************/
1997 static inline BOOL map_selrefs(SEL *src, SEL *dst, size_t size, BOOL copy)
1998 {
1999 BOOL result = NO;
2000 unsigned int cnt = size / sizeof(SEL);
2001 unsigned int index;
2002
2003 sel_lock();
2004
2005 // Process each selector
2006 for (index = 0; index < cnt; index += 1)
2007 {
2008 SEL sel;
2009
2010 // Lookup pointer to uniqued string
2011 sel = sel_registerNameNoLock((const char *) src[index], copy);
2012
2013 // Replace this selector with uniqued one (avoid
2014 // modifying the VM page if this would be a NOP)
2015 if (dst[index] != sel) {
2016 dst[index] = sel;
2017 result = YES;
2018 }
2019 }
2020
2021 sel_unlock();
2022
2023 return result;
2024 }
2025
2026
2027 /***********************************************************************
2028 * map_method_descs. For each method in the specified method list,
2029 * replace the name pointer with a uniqued selector.
2030 * If copy is TRUE, all selector data is always copied. This is used
2031 * for registering selectors from unloadable bundles, so the selector
2032 * can still be used after the bundle's data segment is unmapped.
2033 **********************************************************************/
2034 static void map_method_descs (struct objc_method_description_list * methods, BOOL copy)
2035 {
2036 unsigned int index;
2037
2038 sel_lock();
2039
2040 // Process each method
2041 for (index = 0; index < methods->count; index += 1)
2042 {
2043 struct objc_method_description * method;
2044 SEL sel;
2045
2046 // Get method entry to fix up
2047 method = &methods->list[index];
2048
2049 // Lookup pointer to uniqued string
2050 sel = sel_registerNameNoLock((const char *) method->name, copy);
2051
2052 // Replace this selector with uniqued one (avoid
2053 // modifying the VM page if this would be a NOP)
2054 if (method->name != sel)
2055 method->name = sel;
2056 }
2057
2058 sel_unlock();
2059 }
2060
2061 /***********************************************************************
2062 * _fixup.
2063 **********************************************************************/
2064 @interface Protocol(RuntimePrivate)
2065 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries;
2066 @end
2067
2068 /***********************************************************************
2069 * _objc_fixup_protocol_objects_for_image. For each protocol in the
2070 * specified image, selectorize the method names and call +_fixup.
2071 **********************************************************************/
2072 static void _objc_fixup_protocol_objects_for_image (header_info * hi)
2073 {
2074 unsigned int size;
2075 OBJC_PROTOCOL_PTR protos;
2076 unsigned int index;
2077 int isBundle = hi->mhdr->filetype == MH_BUNDLE;
2078
2079 // Locate protocols in the image
2080 protos = (OBJC_PROTOCOL_PTR) _getObjcProtocols ((headerType *) hi->mhdr, &size);
2081 if (!protos)
2082 return;
2083
2084 // Apply the slide bias
2085 protos = (OBJC_PROTOCOL_PTR) ((unsigned long) protos + hi->image_slide);
2086
2087 // Process each protocol
2088 for (index = 0; index < size; index += 1)
2089 {
2090 // Selectorize the instance methods
2091 if (protos[index] OBJC_PROTOCOL_DEREF instance_methods)
2092 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF instance_methods, isBundle);
2093
2094 // Selectorize the class methods
2095 if (protos[index] OBJC_PROTOCOL_DEREF class_methods)
2096 map_method_descs (protos[index] OBJC_PROTOCOL_DEREF class_methods, isBundle);
2097 }
2098
2099 // Invoke Protocol class method to fix up the protocol
2100 [Protocol _fixup:(OBJC_PROTOCOL_PTR)protos numElements:size];
2101 }
2102
2103 /***********************************************************************
2104 * _objc_headerStart. Return what headers we know about.
2105 **********************************************************************/
2106 header_info * _objc_headerStart ()
2107 {
2108
2109 // Take advatage of our previous work
2110 return FirstHeader;
2111 }
2112
2113 void _objc_bindModuleContainingList() {
2114 /* We define this for backwards binary compat with things which should not
2115 * have been using it (cough OmniWeb), but now it does nothing for them.
2116 */
2117 }
2118
2119
2120 /***********************************************************************
2121 * _objc_addHeader.
2122 **********************************************************************/
2123
2124 // tested with 2; typical case is 4, but OmniWeb & Mail push it towards 20
2125 #define HINFO_SIZE 16
2126
2127 static int HeaderInfoCounter NOBSS = 0;
2128 static header_info HeaderInfoTable[HINFO_SIZE] NOBSS = { {0} };
2129
2130 static header_info * _objc_addHeader(const struct mach_header *header)
2131 {
2132 int mod_count = 0;
2133 uintptr_t mod_unslid;
2134 uint32_t info_size = 0;
2135 uintptr_t image_info_unslid;
2136 const struct segment_command *objc_segment;
2137 ptrdiff_t slide;
2138 header_info *result;
2139
2140 // Locate the __OBJC segment
2141 objc_segment = getsegbynamefromheader(header, SEG_OBJC);
2142 if (!objc_segment) return NULL;
2143
2144 // Locate some sections in the __OBJC segment
2145 mod_unslid = (uintptr_t)_getObjcModules(header, &mod_count);
2146 if (!mod_unslid) return NULL;
2147 image_info_unslid = (uintptr_t)_getObjcImageInfo(header, &info_size);
2148
2149 // Calculate vm slide.
2150 slide = _getImageSlide(header);
2151
2152
2153 // Find or allocate a header_info entry.
2154 if (HeaderInfoCounter < HINFO_SIZE) {
2155 result = &HeaderInfoTable[HeaderInfoCounter++];
2156 } else {
2157 result = _malloc_internal(sizeof(header_info));
2158 }
2159
2160 // Set up the new header_info entry.
2161 result->mhdr = header;
2162 result->mod_ptr = (Module)(mod_unslid + slide);
2163 result->mod_count = mod_count;
2164 result->image_slide = slide;
2165 result->objcSegmentHeader = objc_segment;
2166 if (image_info_unslid) {
2167 result->info = (objc_image_info *)(image_info_unslid + slide);
2168 } else {
2169 result->info = NULL;
2170 }
2171
2172 // Make sure every copy of objc_image_info in this image is the same.
2173 // This means same version and same bitwise contents.
2174 if (result->info) {
2175 objc_image_info *start = result->info;
2176 objc_image_info *end =
2177 (objc_image_info *)(info_size + (uint8_t *)start);
2178 objc_image_info *info = start;
2179 while (info < end) {
2180 // version is byte size, except for version 0
2181 size_t struct_size = info->version;
2182 if (struct_size == 0) struct_size = 2 * sizeof(uint32_t);
2183 if (info->version != start->version ||
2184 0 != memcmp(info, start, struct_size))
2185 {
2186 _objc_fatal("'%s' has inconsistently-compiled Objective-C "
2187 "code. Please recompile all code in it.",
2188 _nameForHeader(header));
2189 }
2190 info = (objc_image_info *)(struct_size + (uint8_t *)info);
2191 }
2192 }
2193
2194 // Add the header to the header list.
2195 // The header is appended to the list, to preserve the bottom-up order.
2196 result->next = NULL;
2197 if (!FirstHeader) {
2198 // list is empty
2199 FirstHeader = LastHeader = result;
2200 } else {
2201 if (!LastHeader) {
2202 // list is not empty, but LastHeader is invalid - recompute it
2203 LastHeader = FirstHeader;
2204 while (LastHeader->next) LastHeader = LastHeader->next;
2205 }
2206 // LastHeader is now valid
2207 LastHeader->next = result;
2208 LastHeader = result;
2209 }
2210
2211 return result;
2212 }
2213
2214
2215 /***********************************************************************
2216 * _objc_RemoveHeader
2217 * Remove the given header from the header list.
2218 * FirstHeader is updated.
2219 * LastHeader is set to NULL. Any code that uses LastHeader must
2220 * detect this NULL and recompute LastHeader by traversing the list.
2221 **********************************************************************/
2222 static void _objc_removeHeader(header_info *hi)
2223 {
2224 header_info **hiP;
2225
2226 for (hiP = &FirstHeader; *hiP != NULL; hiP = &(**hiP).next) {
2227 if (*hiP == hi) {
2228 header_info *deadHead = *hiP;
2229
2230 // Remove from the linked list (updating FirstHeader if necessary).
2231 *hiP = (**hiP).next;
2232
2233 // Update LastHeader if necessary.
2234 if (LastHeader == deadHead) {
2235 LastHeader = NULL; // will be recomputed next time it's used
2236 }
2237
2238 // Free the memory, unless it was in the static HeaderInfoTable.
2239 if (deadHead < HeaderInfoTable ||
2240 deadHead >= HeaderInfoTable + HINFO_SIZE)
2241 {
2242 _free_internal(deadHead);
2243 }
2244
2245 break;
2246 }
2247 }
2248 }
2249
2250
2251 /***********************************************************************
2252 * check_gc
2253 * Check whether the executable supports or requires GC, and make sure
2254 * all already-loaded libraries support the executable's GC mode.
2255 * Returns TRUE if the executable wants GC on.
2256 **********************************************************************/
2257 static BOOL check_wants_gc(void)
2258 {
2259 // GC is off in Tiger.
2260 return NO;
2261 /*
2262 const header_info *hi;
2263 BOOL appWantsGC;
2264
2265 // Environment variables can override the following.
2266 if (ForceGC) {
2267 _objc_inform("GC: forcing GC ON because OBJC_FORCE_GC is set");
2268 appWantsGC = YES;
2269 }
2270 else if (ForceNoGC) {
2271 _objc_inform("GC: forcing GC OFF because OBJC_FORCE_NO_GC is set");
2272 appWantsGC = NO;
2273 }
2274 else {
2275 // Find the executable and check its GC bits.
2276 // If the executable cannot be found, default to NO.
2277 // (The executable will not be found if the executable contains
2278 // no Objective-C code.)
2279 appWantsGC = NO;
2280 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
2281 if (hi->mhdr->filetype == MH_EXECUTE) {
2282 appWantsGC = _objcHeaderSupportsGC(hi) ? YES : NO;
2283 if (PrintGC) {
2284 _objc_inform("GC: executable '%s' %s GC",
2285 _nameForHeader(hi->mhdr),
2286 appWantsGC ? "supports" : "does not support");
2287 }
2288 }
2289 }
2290 }
2291 return appWantsGC;
2292 */
2293 }
2294
2295 /***********************************************************************
2296 * verify_gc_readiness
2297 * if we want gc, verify that every header describes files compiled
2298 * and presumably ready for gc.
2299 ************************************************************************/
2300
2301 static void verify_gc_readiness(BOOL wantsGC, header_info *hi)
2302 {
2303 BOOL busted = NO;
2304
2305 // Find the libraries and check their GC bits against the app's request
2306 for (; hi != NULL; hi = hi->next) {
2307 if (hi->mhdr->filetype == MH_EXECUTE) {
2308 continue;
2309 }
2310 else if (hi->mhdr == &_mh_dylib_header) {
2311 // libobjc itself works with anything even though it is not
2312 // compiled with -fobjc-gc (fixme should it be?)
2313 }
2314 else if (wantsGC && ! _objcHeaderSupportsGC(hi)) {
2315 // App wants GC but library does not support it - bad
2316 _objc_inform("'%s' was not compiled with -fobjc-gc, but "
2317 "the application requires GC",
2318 _nameForHeader(hi->mhdr));
2319 busted = YES;
2320 }
2321
2322 if (PrintGC) {
2323 _objc_inform("GC: library '%s' %s GC", _nameForHeader(hi->mhdr),
2324 _objcHeaderSupportsGC(hi) ? "supports" : "does not support");
2325 }
2326 }
2327
2328 if (busted) {
2329 // GC state is not consistent.
2330 // Kill the process unless one of the forcing flags is set.
2331 if (!ForceGC && !ForceNoGC) {
2332 _objc_fatal("*** GC capability of application and some libraries did not match");
2333 }
2334 }
2335 }
2336
2337
2338 /***********************************************************************
2339 * _objc_fixup_selector_refs. Register all of the selectors in each
2340 * image, and fix them all up.
2341 *
2342 * If the image is a dylib (not a bundle or an executable), and contains
2343 * at least one full aligned page of selector refs, this function uses
2344 * the shared range functions to try to recycle already-written memory
2345 * from other processes.
2346 **********************************************************************/
2347 static void _objc_fixup_selector_refs (const header_info * hi)
2348 {
2349 unsigned int count;
2350 Module mods;
2351 vm_address_t local_sels;
2352 vm_size_t local_size;
2353
2354 mods = hi->mod_ptr;
2355
2356 // Fix up message refs
2357 local_sels = (vm_address_t) _getObjcMessageRefs ((headerType *) hi->mhdr, &count);
2358 local_size = count * sizeof(SEL);
2359
2360 if (local_sels) {
2361 vm_address_t aligned_start, aligned_end;
2362
2363 local_sels = local_sels + hi->image_slide;
2364 aligned_start = round_page(local_sels);
2365 aligned_end = trunc_page(local_sels + local_size);
2366
2367 if (aligned_start >= aligned_end ||
2368 hi->mhdr->filetype == MH_BUNDLE ||
2369 hi->mhdr->filetype == MH_EXECUTE)
2370 {
2371 // Less than a page of sels, OR bundle or executable - fix in place
2372
2373 map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size,
2374 hi->mhdr->filetype == MH_BUNDLE);
2375
2376 if (PrintSharing) {
2377 _objc_inform("SHARING: NONE [%p..%p) (%d pages) for %s",
2378 local_sels, local_sels+local_size,
2379 (aligned_end > aligned_start ?
2380 (aligned_end-aligned_start) / vm_page_size : 0),
2381 _nameForHeader(hi->mhdr));
2382 }
2383 }
2384 else {
2385 // At least one page of sels - try to use sharing
2386 vm_range_t remote_range;
2387
2388 if (PrintSharing) {
2389 _objc_inform("SHARING: looking for range [%p..%p) ...",
2390 aligned_start, aligned_end);
2391 }
2392
2393 remote_range = get_shared_range(aligned_start, aligned_end);
2394
2395 if (remote_range.address != 0) {
2396 // Sharing succeeded - fix using remote_range
2397 BOOL stomped;
2398
2399 // local_sels..aligned_start (unshared)
2400 map_selrefs((SEL *)local_sels, (SEL *)local_sels,
2401 aligned_start - local_sels, NO);
2402 // aligned_start..aligned_end (shared)
2403 stomped =
2404 map_selrefs((SEL *)aligned_start, (SEL *)remote_range.address,
2405 aligned_end - aligned_start, NO);
2406 // aligned_end..local_sels+local_size (unshared)
2407 map_selrefs((SEL *)aligned_end, (SEL *)aligned_end,
2408 local_sels+local_size - aligned_end, NO);
2409
2410 install_shared_range(remote_range, aligned_start);
2411
2412 if (PrintSharing) {
2413 _objc_inform("SHARING: %s [%p..%p) (%d pages) for %s",
2414 stomped ? "TRIED" : "USING",
2415 local_sels, local_sels+local_size,
2416 (aligned_end-aligned_start) / vm_page_size,
2417 _nameForHeader(hi->mhdr));
2418 }
2419 }
2420 else {
2421 // Sharing failed, including first process -
2422 // fix in place and then offer to share
2423
2424 map_selrefs((SEL *)local_sels, (SEL *)local_sels, local_size, NO);
2425
2426 offer_shared_range(aligned_start, aligned_end);
2427
2428 if (PrintSharing) {
2429 _objc_inform("SHARING: OFFER [%p..%p) (%d pages) for %s",
2430 local_sels, local_sels+local_size,
2431 (aligned_end-aligned_start) / vm_page_size,
2432 _nameForHeader(hi->mhdr));
2433 }
2434 }
2435 }
2436 }
2437 }
2438
2439
2440 /***********************************************************************
2441 * objc_setConfiguration
2442 * Read environment variables that affect the runtime.
2443 * Also print environment variable help, if requested.
2444 **********************************************************************/
2445 static void objc_setConfiguration() {
2446 int PrintHelp = (getenv("OBJC_HELP") != NULL);
2447 int PrintOptions = (getenv("OBJC_PRINT_OPTIONS") != NULL);
2448
2449 if (PrintHelp) {
2450 _objc_inform("OBJC_HELP: describe Objective-C runtime environment variables");
2451 if (PrintOptions) {
2452 _objc_inform("OBJC_HELP is set");
2453 }
2454 _objc_inform("OBJC_PRINT_OPTIONS: list which options are set");
2455 }
2456 if (PrintOptions) {
2457 _objc_inform("OBJC_PRINT_OPTIONS is set");
2458 }
2459
2460 #define OPTION(var, env, help) \
2461 if ( var == -1 ) { \
2462 var = getenv(#env) != NULL; \
2463 if (PrintHelp) _objc_inform(#env ": " help); \
2464 if (PrintOptions && var) _objc_inform(#env " is set"); \
2465 }
2466
2467 OPTION(PrintImages, OBJC_PRINT_IMAGES,
2468 "log image and library names as the runtime loads them");
2469 OPTION(PrintConnecting, OBJC_PRINT_CONNECTION,
2470 "log progress of class and category connections");
2471 OPTION(PrintLoading, OBJC_PRINT_LOAD_METHODS,
2472 "log class and category +load methods as they are called");
2473 OPTION(PrintRTP, OBJC_PRINT_RTP,
2474 "log initialization of the Objective-C runtime pages");
2475 OPTION(PrintGC, OBJC_PRINT_GC,
2476 "log some GC operations");
2477 OPTION(PrintSharing, OBJC_PRINT_SHARING,
2478 "log cross-process memory sharing");
2479 OPTION(PrintCxxCtors, OBJC_PRINT_CXX_CTORS,
2480 "log calls to C++ ctors and dtors for instance variables");
2481
2482 OPTION(DebugUnload, OBJC_DEBUG_UNLOAD,
2483 "warn about poorly-behaving bundles when unloaded");
2484 OPTION(DebugFragileSuperclasses, OBJC_DEBUG_FRAGILE_SUPERCLASSES,
2485 "warn about subclasses that may have been broken by subsequent changes to superclasses");
2486
2487 OPTION(UseInternalZone, OBJC_USE_INTERNAL_ZONE,
2488 "allocate runtime data in a dedicated malloc zone");
2489 OPTION(AllowInterposing, OBJC_ALLOW_INTERPOSING,
2490 "allow function interposing of objc_msgSend()");
2491
2492 OPTION(ForceGC, OBJC_FORCE_GC,
2493 "force GC ON, even if the executable wants it off");
2494 OPTION(ForceNoGC, OBJC_FORCE_NO_GC,
2495 "force GC OFF, even if the executable wants it on");
2496 OPTION(CheckFinalizers, OBJC_CHECK_FINALIZERS,
2497 "warn about classes that implement -dealloc but not -finalize");
2498 #undef OPTION
2499 }
2500
2501
2502 /***********************************************************************
2503 * objc_setMultithreaded.
2504 **********************************************************************/
2505 void objc_setMultithreaded (BOOL flag)
2506 {
2507 // Nothing here. Thread synchronization in the runtime is always active.
2508 }
2509
2510
2511
2512 /***********************************************************************
2513 * _objc_pthread_destroyspecific
2514 * Destructor for objc's per-thread data.
2515 * arg shouldn't be NULL, but we check anyway.
2516 **********************************************************************/
2517 extern void _destroyInitializingClassList(struct _objc_initializing_classes *list);
2518 void _objc_pthread_destroyspecific(void *arg)
2519 {
2520 _objc_pthread_data *data = (_objc_pthread_data *)arg;
2521 if (data != NULL) {
2522 _destroyInitializingClassList(data->initializingClasses);
2523
2524 // add further cleanup here...
2525
2526 _free_internal(data);
2527 }
2528 }
2529
2530
2531 /***********************************************************************
2532 * _objcInit
2533 * Former library initializer. This function is now merely a placeholder
2534 * for external callers. All runtime initialization has now been moved
2535 * to map_images().
2536 **********************************************************************/
2537 void _objcInit(void)
2538 {
2539 // do nothing
2540 }
2541
2542
2543 /***********************************************************************
2544 * map_images
2545 * Process the given images which are being mapped in by dyld.
2546 * All class registration and fixups are performed (or deferred pending
2547 * discovery of missing superclasses etc), and +load methods are called.
2548 *
2549 * info[] is in bottom-up order i.e. libobjc will be earlier in the
2550 * array than any library that links to libobjc.
2551 **********************************************************************/
2552 static void map_images(const struct dyld_image_info infoList[],
2553 uint32_t infoCount)
2554 {
2555 static BOOL firstTime = YES;
2556 static BOOL wantsGC NOBSS = NO;
2557 uint32_t i;
2558 header_info *firstNewHeader = NULL;
2559 header_info *hInfo;
2560
2561 // Perform first-time initialization if necessary.
2562 // This function is called before ordinary library initializers.
2563 if (firstTime) {
2564 pthread_key_create(&_objc_pthread_key, _objc_pthread_destroyspecific);
2565 objc_setConfiguration(); // read environment variables
2566 _objc_init_class_hash (); // create class_hash
2567 // grab selectors for which @selector() doesn't work
2568 cxx_construct_sel = sel_registerName(cxx_construct_name);
2569 cxx_destruct_sel = sel_registerName(cxx_destruct_name);
2570 }
2571
2572 if (PrintImages) {
2573 _objc_inform("IMAGES: processing %u newly-mapped images...\n", infoCount);
2574 }
2575
2576
2577 // Find all images with an __OBJC segment.
2578 // firstNewHeader is set the the first one, and the header_info
2579 // linked list following firstNewHeader is the rest.
2580 for (i = 0; i < infoCount; i++) {
2581 const struct mach_header *mhdr = infoList[i].imageLoadAddress;
2582
2583 hInfo = _objc_addHeader(mhdr);
2584 if (!hInfo) {
2585 // no objc data in this entry
2586 if (PrintImages) {
2587 _objc_inform("IMAGES: image '%s' contains no __OBJC segment\n",
2588 infoList[i].imageFilePath);
2589 }
2590 continue;
2591 }
2592
2593 if (!firstNewHeader) firstNewHeader = hInfo;
2594
2595 if (PrintImages) {
2596 _objc_inform("IMAGES: loading image for %s%s%s%s\n",
2597 _nameForHeader(mhdr),
2598 mhdr->filetype == MH_BUNDLE ? " (bundle)" : "",
2599 _objcHeaderIsReplacement(hInfo) ? " (replacement)":"",
2600 _objcHeaderSupportsGC(hInfo) ? " (supports GC)":"");
2601 }
2602 }
2603
2604 // Perform one-time runtime initialization that must be deferred until
2605 // the executable itself is found. This needs to be done before
2606 // further initialization.
2607 // (The executable may not be present in this infoList if the
2608 // executable does not contain Objective-C code but Objective-C
2609 // is dynamically loaded later. In that case, check_wants_gc()
2610 // will do the right thing.)
2611 if (firstTime) {
2612 wantsGC = check_wants_gc();
2613 verify_gc_readiness(wantsGC, FirstHeader);
2614 // TIGER DEVELOPMENT ONLY
2615 // REQUIRE A SPECIAL NON-SHIPPING FILE TO ENABLE GC
2616 if (wantsGC) {
2617 // make sure that the special file is there before proceeding with GC
2618 struct stat ignored;
2619 wantsGC = stat("/autozone", &ignored) != -1;
2620 if (!wantsGC && PrintGC)
2621 _objc_inform("GC: disabled, lacking /autozone file");
2622 }
2623
2624 gc_init(wantsGC); // needs executable for GC decision
2625 rtp_init(); // needs GC decision first
2626 } else {
2627 verify_gc_readiness(wantsGC, firstNewHeader);
2628 }
2629
2630
2631 // Initialize everything. Parts of this order are important for
2632 // correctness or performance.
2633
2634 // Read classes from all images.
2635 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2636 _objc_read_classes_from_image(hInfo);
2637 }
2638
2639 // Read categories from all images.
2640 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2641 _objc_read_categories_from_image(hInfo);
2642 }
2643
2644 // Connect classes from all images.
2645 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2646 _objc_connect_classes_from_image(hInfo);
2647 }
2648
2649 // Fix up class refs, selector refs, and protocol objects from all images.
2650 for (hInfo = firstNewHeader; hInfo != NULL; hInfo = hInfo->next) {
2651 _objc_map_class_refs_for_image(hInfo);
2652 _objc_fixup_selector_refs(hInfo);
2653 _objc_fixup_protocol_objects_for_image(hInfo);
2654 }
2655
2656 // Close any shared range file left open during selector uniquing
2657 clear_shared_range_file_cache();
2658
2659 firstTime = NO;
2660
2661 // Call pending +load methods.
2662 // Note that this may in turn cause map_images() to be called again.
2663 call_load_methods();
2664 }
2665
2666
2667 /***********************************************************************
2668 * unmap_images
2669 * Process the given images which are about to be unmapped by dyld.
2670 * Currently we assume only MH_BUNDLE images are unmappable, and
2671 * print warnings about anything else.
2672 **********************************************************************/
2673 static void unmap_images(const struct dyld_image_info infoList[],
2674 uint32_t infoCount)
2675 {
2676 uint32_t i;
2677
2678 if (PrintImages) {
2679 _objc_inform("IMAGES: processing %u newly-unmapped images...\n", infoCount);
2680 }
2681
2682 for (i = 0; i < infoCount; i++) {
2683 const struct mach_header *mhdr = infoList[i].imageLoadAddress;
2684
2685 if (mhdr->filetype == MH_BUNDLE) {
2686 _objc_unmap_image(mhdr);
2687 } else {
2688 // currently only MH_BUNDLEs can be unmapped safely
2689 if (PrintImages) {
2690 _objc_inform("IMAGES: unmapped image '%s' was not a Mach-O bundle; ignoring\n", infoList[i].imageFilePath);
2691 }
2692 }
2693 }
2694 }
2695
2696
2697 /***********************************************************************
2698 * _objc_notify_images
2699 * Callback from dyld informing objc of images to be added or removed.
2700 * This function is never called directly. Instead, a section
2701 * __OBJC,__image_notify contains a function pointer to this, and dyld
2702 * discovers it from there.
2703 **********************************************************************/
2704 __private_extern__
2705 void _objc_notify_images(enum dyld_image_mode mode, uint32_t infoCount,
2706 const struct dyld_image_info infoList[])
2707 {
2708 if (mode == dyld_image_adding) {
2709 map_images(infoList, infoCount);
2710 } else if (mode == dyld_image_removing) {
2711 unmap_images(infoList, infoCount);
2712 }
2713 }
2714
2715
2716 /***********************************************************************
2717 * _objc_remove_classes_in_image
2718 * Remove all classes in the given image from the runtime, because
2719 * the image is about to be unloaded.
2720 * Things to clean up:
2721 * class_hash
2722 * unconnected_class_hash
2723 * pending subclasses list (only if class is still unconnected)
2724 * loadable class list
2725 * class's method caches
2726 * class refs in all other images
2727 **********************************************************************/
2728 static void _objc_remove_classes_in_image(header_info *hi)
2729 {
2730 unsigned int index;
2731 unsigned int midx;
2732 Module mods;
2733
2734 OBJC_LOCK(&classLock);
2735
2736 // Major loop - process all modules in the image
2737 mods = hi->mod_ptr;
2738 for (midx = 0; midx < hi->mod_count; midx += 1)
2739 {
2740 // Skip module containing no classes
2741 if (mods[midx].symtab == NULL)
2742 continue;
2743
2744 // Minor loop - process all the classes in given module
2745 for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
2746 {
2747 struct objc_class * cls;
2748
2749 // Locate the class description pointer
2750 cls = mods[midx].symtab->defs[index];
2751
2752 // Remove from loadable class list, if present
2753 remove_class_from_loadable_list(cls);
2754
2755 // Remove from unconnected_class_hash and pending subclasses
2756 if (unconnected_class_hash && NXHashMember(unconnected_class_hash, cls)) {
2757 NXHashRemove(unconnected_class_hash, cls);
2758 if (pendingSubclassesMap) {
2759 // Find this class in its superclass's pending list
2760 char *supercls_name = (char *)cls->super_class;
2761 PendingSubclass *pending =
2762 NXMapGet(pendingSubclassesMap, supercls_name);
2763 for ( ; pending != NULL; pending = pending->next) {
2764 if (pending->subclass == cls) {
2765 pending->subclass = Nil;
2766 break;
2767 }
2768 }
2769 }
2770 }
2771
2772 // Remove from class_hash
2773 NXHashRemove(class_hash, cls);
2774
2775 // Free method list array (from objcTweakMethodListPointerForClass)
2776 // These blocks might be from user code; don't use free_internal
2777 if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) {
2778 free(cls->methodLists);
2779 }
2780 if (cls->isa->methodLists && !(cls->isa->info & CLS_NO_METHOD_ARRAY)) {
2781 free(cls->isa->methodLists);
2782 }
2783
2784 // Free method caches, if any
2785 if (cls->cache && cls->cache != &emptyCache) {
2786 _free_internal(cls->cache);
2787 }
2788 if (cls->isa->cache && cls->isa->cache != &emptyCache) {
2789 _free_internal(cls->isa->cache);
2790 }
2791 }
2792 }
2793
2794
2795 // Search all other images for class refs that point back to this range.
2796 // Un-fix and re-pend any such class refs.
2797
2798 // Get the location of the dying image's __OBJC segment
2799 uintptr_t seg = hi->objcSegmentHeader->vmaddr + hi->image_slide;
2800 size_t seg_size = hi->objcSegmentHeader->filesize;
2801
2802 header_info *other_hi;
2803 for (other_hi = FirstHeader; other_hi != NULL; other_hi = other_hi->next) {
2804 struct objc_class **other_refs;
2805 unsigned int size;
2806 if (other_hi == hi) continue; // skip the image being unloaded
2807
2808 // Locate class refs in the other image
2809 other_refs = _getObjcClassRefs((headerType *)other_hi->mhdr, &size);
2810 if (!other_refs) continue;
2811 other_refs = (struct objc_class **)((uintptr_t)other_refs + other_hi->image_slide);
2812
2813 // Process each class ref
2814 for (index = 0; index < size; index++) {
2815 if ((uintptr_t)(other_refs[index]) >= seg &&
2816 (uintptr_t)(other_refs[index]) < seg+seg_size)
2817 {
2818 pendClassReference(&other_refs[index],other_refs[index]->name);
2819 other_refs[index] = _objc_getNonexistentClass ();
2820 }
2821 }
2822 }
2823
2824 OBJC_UNLOCK(&classLock);
2825 }
2826
2827
2828 /***********************************************************************
2829 * _objc_remove_categories_in_image
2830 * Remove all categories in the given image from the runtime, because
2831 * the image is about to be unloaded.
2832 * Things to clean up:
2833 * unresolved category list
2834 * loadable category list
2835 **********************************************************************/
2836 static void _objc_remove_categories_in_image(header_info *hi)
2837 {
2838 Module mods;
2839 unsigned int midx;
2840
2841 // Major loop - process all modules in the header
2842 mods = hi->mod_ptr;
2843
2844 for (midx = 0; midx < hi->mod_count; midx++) {
2845 unsigned int index;
2846 unsigned int total;
2847 Symtab symtab = mods[midx].symtab;
2848
2849 // Nothing to do for a module without a symbol table
2850 if (symtab == NULL) continue;
2851
2852 // Total entries in symbol table (class entries followed
2853 // by category entries)
2854 total = symtab->cls_def_cnt + symtab->cat_def_cnt;
2855
2856 // Minor loop - check all categories from given module
2857 for (index = symtab->cls_def_cnt; index < total; index++) {
2858 struct objc_category *cat = symtab->defs[index];
2859
2860 // Clean up loadable category list
2861 remove_category_from_loadable_list(cat);
2862
2863 // Clean up category_hash
2864 if (category_hash) {
2865 _objc_unresolved_category *cat_entry =
2866 NXMapGet(category_hash, cat->class_name);
2867 for ( ; cat_entry != NULL; cat_entry = cat_entry->next) {
2868 if (cat_entry->cat == cat) {
2869 cat_entry->cat = NULL;
2870 break;
2871 }
2872 }
2873 }
2874 }
2875 }
2876 }
2877
2878
2879 /***********************************************************************
2880 * unload_paranoia
2881 * Various paranoid debugging checks that look for poorly-behaving
2882 * unloadable bundles.
2883 * Called by _objc_unmap_image when OBJC_UNLOAD_DEBUG is set.
2884 **********************************************************************/
2885 static void unload_paranoia(header_info *hi)
2886 {
2887 // Get the location of the dying image's __OBJC segment
2888 uintptr_t seg = hi->objcSegmentHeader->vmaddr + hi->image_slide;
2889 size_t seg_size = hi->objcSegmentHeader->filesize;
2890
2891 _objc_inform("UNLOAD DEBUG: unloading image '%s' [%p..%p]",
2892 _nameForHeader(hi->mhdr), seg, seg+seg_size);
2893
2894 OBJC_LOCK(&classLock);
2895
2896 // Make sure the image contains no categories on surviving classes.
2897 {
2898 Module mods;
2899 unsigned int midx;
2900
2901 // Major loop - process all modules in the header
2902 mods = hi->mod_ptr;
2903
2904 for (midx = 0; midx < hi->mod_count; midx++) {
2905 unsigned int index;
2906 unsigned int total;
2907 Symtab symtab = mods[midx].symtab;
2908
2909 // Nothing to do for a module without a symbol table
2910 if (symtab == NULL) continue;
2911
2912 // Total entries in symbol table (class entries followed
2913 // by category entries)
2914 total = symtab->cls_def_cnt + symtab->cat_def_cnt;
2915
2916 // Minor loop - check all categories from given module
2917 for (index = symtab->cls_def_cnt; index < total; index++) {
2918 struct objc_category *cat = symtab->defs[index];
2919 struct objc_class query;
2920
2921 query.name = cat->class_name;
2922 if (NXHashMember(class_hash, &query)) {
2923 _objc_inform("UNLOAD DEBUG: dying image contains category '%s(%s)' on surviving class '%s'!", cat->class_name, cat->category_name, cat->class_name);
2924 }
2925 }
2926 }
2927 }
2928
2929 // Make sure no surviving class is in the dying image.
2930 // Make sure no surviving class has a superclass in the dying image.
2931 // fixme check method implementations too
2932 {
2933 struct objc_class *cls;
2934 NXHashState state;
2935
2936 state = NXInitHashState(class_hash);
2937 while (NXNextHashState(class_hash, &state, (void **)&cls)) {
2938 if ((vm_address_t)cls >= seg &&
2939 (vm_address_t)cls < seg+seg_size)
2940 {
2941 _objc_inform("UNLOAD DEBUG: dying image contains surviving class '%s'!", cls->name);
2942 }
2943
2944 if ((vm_address_t)cls->super_class >= seg &&
2945 (vm_address_t)cls->super_class < seg+seg_size)
2946 {
2947 _objc_inform("UNLOAD DEBUG: dying image contains superclass '%s' of surviving class '%s'!", cls->super_class->name, cls->name);
2948 }
2949 }
2950 }
2951
2952 OBJC_UNLOCK(&classLock);
2953 }
2954
2955
2956 /***********************************************************************
2957 * _objc_unmap_image.
2958 * Destroy any Objective-C data for the given image, which is about to
2959 * be unloaded by dyld.
2960 * Note: not thread-safe, but image loading isn't either.
2961 **********************************************************************/
2962 static void _objc_unmap_image(const headerType *mh)
2963 {
2964 header_info *hi;
2965
2966 // Find the runtime's header_info struct for the image
2967 for (hi = FirstHeader; hi != NULL; hi = hi->next) {
2968 if (hi->mhdr == mh) break;
2969 }
2970 if (hi == NULL) return; // no objc data for this image
2971
2972 if (PrintImages) {
2973 _objc_inform("IMAGES: unloading image for %s%s%s%s\n",
2974 _nameForHeader(mh),
2975 mh->filetype == MH_BUNDLE ? " (bundle)" : "",
2976 _objcHeaderIsReplacement(hi) ? " (replacement)" : "",
2977 _objcHeaderSupportsGC(hi) ? " (supports GC)" : "");
2978 }
2979
2980 // Cleanup:
2981 // Remove image's classes from the class list and free auxiliary data.
2982 // Remove image's unresolved or loadable categories and free auxiliary data
2983 // Remove image's unresolved class refs.
2984 _objc_remove_classes_in_image(hi);
2985 _objc_remove_categories_in_image(hi);
2986 _objc_remove_pending_class_refs_in_image(hi);
2987
2988 // Perform various debugging checks if requested.
2989 if (DebugUnload) unload_paranoia(hi);
2990
2991 // Remove header_info from header list
2992 _objc_removeHeader(hi);
2993 }
2994
2995
2996 /***********************************************************************
2997 * _objc_setNilReceiver
2998 **********************************************************************/
2999 id _objc_setNilReceiver(id newNilReceiver)
3000 {
3001 id oldNilReceiver;
3002
3003 oldNilReceiver = _objc_nilReceiver;
3004 _objc_nilReceiver = newNilReceiver;
3005
3006 return oldNilReceiver;
3007 }
3008
3009 /***********************************************************************
3010 * _objc_getNilReceiver
3011 **********************************************************************/
3012 id _objc_getNilReceiver(void)
3013 {
3014 return _objc_nilReceiver;
3015 }
3016
3017
3018 /***********************************************************************
3019 * _objc_setClassLoader
3020 * Similar to objc_setClassHandler, but objc_classLoader is used for
3021 * both objc_getClass() and objc_lookupClass(), and objc_classLoader
3022 * pre-empts objc_classHandler.
3023 **********************************************************************/
3024 void _objc_setClassLoader(BOOL (*newClassLoader)(const char *))
3025 {
3026 _objc_classLoader = newClassLoader;
3027 }
3028
3029
3030 #if defined(__ppc__)
3031
3032 /**********************************************************************
3033 * objc_write_branch
3034 * Writes at entry a PPC branch instruction sequence that branches to target.
3035 * The sequence written will be 1 or 4 instructions long.
3036 * Returns the number of instructions written.
3037 **********************************************************************/
3038 __private_extern__ size_t objc_write_branch(void *entry, void *target)
3039 {
3040 unsigned *address = (unsigned *)entry; // location to store the 32 bit PPC instructions
3041 intptr_t destination = (intptr_t)target; // destination as an absolute address
3042 intptr_t displacement = (intptr_t)destination - (intptr_t)address; // destination as a branch relative offset
3043
3044 // Test to see if either the displacement or destination is within the +/- 2^25 range needed
3045 // for a simple PPC branch instruction. Shifting the high bit of the displacement (or destination)
3046 // left 6 bits and then 6 bits arithmetically to the right does a sign extend of the 26th bit. If
3047 // that result is equivalent to the original value, then the displacement (or destination) will fit
3048 // into a simple branch. Otherwise a four instruction branch sequence is required.
3049 if (((displacement << 6) >> 6) == displacement) {
3050 // use a relative branch with the displacement
3051 address[0] = 0x48000000 | (displacement & 0x03fffffc); // b *+displacement
3052 // issued 1 instruction
3053 return 1;
3054 } else if (((destination << 6) >> 6) == destination) {
3055 // use an absolute branch with the destination
3056 address[0] = 0x48000000 | (destination & 0x03fffffc) | 2; // ba destination (2 is the absolute flag)
3057 // issued 1 instruction
3058 return 1;
3059 } else {
3060 // The four instruction branch sequence requires that the destination be loaded
3061 // into a register, moved to the CTR register then branch using the contents
3062 // of the CTR register.
3063 unsigned lo = destination & 0xffff;
3064 unsigned hi = (destination >> 16) & 0xffff;
3065
3066 address[0] = 0x3d800000 | hi; // lis r12,hi ; load the hi half of destination
3067 address[1] = 0x618c0000 | lo; // ori r12,r12,lo ; merge in the lo half of destination
3068 address[2] = 0x7d8903a6; // mtctr ; move destination to the CTR register
3069 address[3] = 0x4e800420; // bctr ; branch to destination
3070 // issued 4 instructions
3071 return 4;
3072 }
3073 }
3074
3075 // defined(__ppc__)
3076 #endif
3077
3078
3079 /**********************************************************************
3080 * secure_open
3081 * Securely open a file from a world-writable directory (like /tmp)
3082 * If the file does not exist, it will be atomically created with mode 0600
3083 * If the file exists, it must be, and remain after opening:
3084 * 1. a regular file (in particular, not a symlink)
3085 * 2. owned by euid
3086 * 3. permissions 0600
3087 * 4. link count == 1
3088 * Returns a file descriptor or -1. Errno may or may not be set on error.
3089 **********************************************************************/
3090 __private_extern__ int secure_open(const char *filename, int flags, uid_t euid)
3091 {
3092 struct stat fs, ls;
3093 int fd = -1;
3094 BOOL truncate = NO;
3095 BOOL create = NO;
3096
3097 if (flags & O_TRUNC) {
3098 // Don't truncate the file until after it is open and verified.
3099 truncate = YES;
3100 flags &= ~O_TRUNC;
3101 }
3102 if (flags & O_CREAT) {
3103 // Don't create except when we're ready for it
3104 create = YES;
3105 flags &= ~O_CREAT;
3106 flags &= ~O_EXCL;
3107 }
3108
3109 if (lstat(filename, &ls) < 0) {
3110 if (errno == ENOENT && create) {
3111 // No such file - create it
3112 fd = open(filename, flags | O_CREAT | O_EXCL, 0600);
3113 if (fd >= 0) {
3114 // File was created successfully.
3115 // New file does not need to be truncated.
3116 return fd;
3117 } else {
3118 // File creation failed.
3119 return -1;
3120 }
3121 } else {
3122 // lstat failed, or user doesn't want to create the file
3123 return -1;
3124 }
3125 } else {
3126 // lstat succeeded - verify attributes and open
3127 if (S_ISREG(ls.st_mode) && // regular file?
3128 ls.st_nlink == 1 && // link count == 1?
3129 ls.st_uid == euid && // owned by euid?
3130 (ls.st_mode & ALLPERMS) == (S_IRUSR | S_IWUSR)) // mode 0600?
3131 {
3132 // Attributes look ok - open it and check attributes again
3133 fd = open(filename, flags, 0000);
3134 if (fd >= 0) {
3135 // File is open - double-check attributes
3136 if (0 == fstat(fd, &fs) &&
3137 fs.st_nlink == ls.st_nlink && // link count == 1?
3138 fs.st_uid == ls.st_uid && // owned by euid?
3139 fs.st_mode == ls.st_mode && // regular file, 0600?
3140 fs.st_ino == ls.st_ino && // same inode as before?
3141 fs.st_dev == ls.st_dev) // same device as before?
3142 {
3143 // File is open and OK
3144 if (truncate) ftruncate(fd, 0);
3145 return fd;
3146 } else {
3147 // Opened file looks funny - close it
3148 close(fd);
3149 return -1;
3150 }
3151 } else {
3152 // File didn't open
3153 return -1;
3154 }
3155 } else {
3156 // Unopened file looks funny - don't open it
3157 return -1;
3158 }
3159 }
3160 }
3161
3162
3163 /**********************************************************************
3164 * Shared range support:
3165 *
3166 * Some libraries contain many pages worth of selector references.
3167 * In most processes, these libraries get loaded at the same addresses,
3168 * so the selectors are uniqued to the same values. To save memory,
3169 * the runtime tries to share these memory pages across processes.
3170 *
3171 * A file /tmp/objc_sharing_<arch>_<euid> records memory ranges and process
3172 * IDs. When a set of selector refs is to be uniqued, this file is checked
3173 * for a matching memory range being shared by another process. If
3174 * such a range is found:
3175 * 1. map the sharing process's memory somewhere into this address space
3176 * 2. read from the real selector refs and write into the mapped memory.
3177 * 3. vm_copy from the mapped memory to the real selector refs location
3178 * 4. deallocate the mapped memory
3179 *
3180 * The mapped memory is merely used as a guess. Correct execution is
3181 * guaranteed no matter what values the mapped memory actually contains.
3182 * If the mapped memory really matches the values needed in this process,
3183 * the mapped memory will be unchanged. If the mapped memory doesn't match,
3184 * or contains random values, it will be fixed up to the correct values.
3185 * The memory is shared whenever the guess happens to be correct.
3186 *
3187 * The file of shared ranges is imprecise. Processes may die leaving
3188 * their entries in the file. A PID may be recycled to some process that
3189 * does not use Objective-C. The sharing mechanism is robust in the face
3190 * of these failures. Bad shared memory is simply fixed up. No shared
3191 * memory means the selectors are fixed in place. If an entry in the
3192 * file is found to be unusable, the process that finds it will instead
3193 * offer to share its own memory, replacing the bad entry in the file.
3194 *
3195 * Individual entries in the file are written atomically, but the file is
3196 * otherwise unsynchronized. At worst, a sharing opportunity may be missed
3197 * because two new entries are written simultaneously in the same place.
3198 **********************************************************************/
3199
3200
3201 struct remote_range_t {
3202 vm_range_t range;
3203 pid_t pid;
3204 };
3205
3206
3207 // Cache for the last shared range file used, and its EUID.
3208 static pthread_mutex_t sharedRangeLock = PTHREAD_MUTEX_INITIALIZER;
3209 static uid_t sharedRangeEUID = 0;
3210 static FILE * sharedRangeFile = NULL;
3211 static BOOL sharedRangeFileInUse = NO;
3212
3213
3214 /**********************************************************************
3215 * open_shared_range_file
3216 * Open the shared range file "/tmp/objc_sharing_<arch>_<euid>" in
3217 * the given mode.
3218 * The returned file should be closed with close_shared_range_file().
3219 **********************************************************************/
3220 static FILE *open_shared_range_file(BOOL create)
3221 {
3222 const char arch[] =
3223 #if defined(__ppc__) || defined(ppc)
3224 "ppc";
3225 #elif defined(__ppc64__) || defined(ppc64)
3226 "ppc64";
3227 #elif defined(__i386__) || defined(i386)
3228 "i386";
3229 #else
3230 # error "unknown architecture"
3231 #endif
3232 char filename[18 + sizeof(arch) + 1 + 3*sizeof(uid_t) + 1];
3233 uid_t euid;
3234 FILE *file = NULL;
3235 int fd;
3236
3237 // Never share when superuser
3238 euid = geteuid();
3239 if (euid == 0) {
3240 if (PrintSharing) {
3241 _objc_inform("SHARING: superuser never shares");
3242 }
3243 return NULL;
3244 }
3245
3246 // Return cached file if it matches and it's not still being used
3247 pthread_mutex_lock(&sharedRangeLock);
3248 if (!sharedRangeFileInUse && euid == sharedRangeEUID) {
3249 file = sharedRangeFile;
3250 sharedRangeFileInUse = YES;
3251 pthread_mutex_unlock(&sharedRangeLock);
3252 rewind(file);
3253 return file;
3254 }
3255 pthread_mutex_unlock(&sharedRangeLock);
3256
3257 // Open /tmp/objc_sharing_<euid>
3258 snprintf(filename,sizeof(filename), "/tmp/objc_sharing_%s_%u", arch, euid);
3259 fd = secure_open(filename, O_RDWR | (create ? O_CREAT : 0), euid);
3260 if (fd >= 0) {
3261 file = fdopen(fd, "r+");
3262 }
3263
3264 if (file) {
3265 // Cache this file if there's no already-open file cached
3266 pthread_mutex_lock(&sharedRangeLock);
3267 if (!sharedRangeFileInUse) {
3268 sharedRangeFile = file;
3269 sharedRangeEUID = euid;
3270 sharedRangeFileInUse = YES;
3271 }
3272 pthread_mutex_unlock(&sharedRangeLock);
3273 }
3274 else {
3275 // open() or fdopen() failed
3276 if (PrintSharing) {
3277 _objc_inform("SHARING: bad or missing sharing file '%s': %s",
3278 filename, errno ? strerror(errno) :
3279 "potential security violation");
3280 }
3281 }
3282
3283 return file;
3284 }
3285
3286
3287 /**********************************************************************
3288 * close_shared_range_file
3289 * Close a file opened with open_shared_range_file.
3290 * The file may actually be kept open and cached for a future
3291 * open_shared_range_file call. If so, clear_shared_range_file_cache()
3292 * can be used to really close the file.
3293 **********************************************************************/
3294 static void close_shared_range_file(FILE *file)
3295 {
3296 // Flush any writes in case the file is kept open.
3297 fflush(file);
3298
3299 pthread_mutex_lock(&sharedRangeLock);
3300 if (file == sharedRangeFile && sharedRangeFileInUse) {
3301 // This file is the cached shared file.
3302 // Leave the file open and cached, but no longer in use.
3303 sharedRangeFileInUse = NO;
3304 } else {
3305 // This is not the cached file.
3306 fclose(file);
3307 }
3308 pthread_mutex_unlock(&sharedRangeLock);
3309 }
3310
3311
3312 /**********************************************************************
3313 * clear_shared_range_file_cache
3314 * Really close any file left open by close_shared_range_file.
3315 * This is called by map_images() after loading multiple images, each
3316 * of which may have used the shared range file.
3317 **********************************************************************/
3318 static void clear_shared_range_file_cache(void)
3319 {
3320 pthread_mutex_lock(&sharedRangeLock);
3321 if (sharedRangeFile && !sharedRangeFileInUse) {
3322 fclose(sharedRangeFile);
3323 sharedRangeFile = NULL;
3324 sharedRangeEUID = 0;
3325 sharedRangeFileInUse = 0;
3326 }
3327 pthread_mutex_unlock(&sharedRangeLock);
3328 }
3329
3330
3331 /**********************************************************************
3332 * get_shared_range
3333 * Try to find a shared range matching addresses [aligned_start..aligned_end).
3334 * If a range is found, it is mapped into this process and returned.
3335 * If no range is found, or the found range could not be mapped for
3336 * some reason, the range {0, 0} is returned.
3337 * aligned_start and aligned_end must be page-aligned.
3338 **********************************************************************/
3339 static vm_range_t get_shared_range(vm_address_t aligned_start,
3340 vm_address_t aligned_end)
3341 {
3342 struct remote_range_t remote;
3343 vm_range_t result;
3344 FILE *file;
3345
3346 result.address = 0;
3347 result.size = 0;
3348
3349 // Open shared range file, but don't create it
3350 file = open_shared_range_file(NO);
3351 if (!file) return result;
3352
3353 // Search for the desired memory range
3354 while (1 == fread(&remote, sizeof(remote), 1, file)) {
3355 if (remote.pid != 0 &&
3356 remote.range.address == aligned_start &&
3357 remote.range.size == aligned_end - aligned_start)
3358 {
3359 // Found a match in the file - try to grab the memory
3360 mach_port_name_t remote_task;
3361 vm_prot_t cur_prot, max_prot;
3362 vm_address_t local_addr;
3363 kern_return_t kr;
3364
3365 // Find the task offering the memory
3366 kr = task_for_pid(mach_task_self(), remote.pid, &remote_task);
3367 if (kr != KERN_SUCCESS) {
3368 // task is dead
3369 if (PrintSharing) {
3370 _objc_inform("SHARING: no task for pid %d: %s",
3371 remote.pid, mach_error_string(kr));
3372 }
3373 break;
3374 }
3375
3376 // Map the memory into our process
3377 local_addr = 0;
3378 kr = vm_remap(mach_task_self(), &local_addr, remote.range.size,
3379 0 /*alignment*/, 1 /*anywhere*/,
3380 remote_task, remote.range.address,
3381 1 /*copy*/, &cur_prot, &max_prot, VM_INHERIT_NONE);
3382 mach_port_deallocate(mach_task_self(), remote_task);
3383
3384 if (kr != KERN_SUCCESS) {
3385 // couldn't map memory
3386 if (PrintSharing) {
3387 _objc_inform("SHARING: vm_remap from pid %d failed: %s",
3388 remote.pid, mach_error_string(kr));
3389 }
3390 break;
3391 }
3392
3393 if (!(cur_prot & VM_PROT_READ) || !(cur_prot & VM_PROT_WRITE)) {
3394 // Received memory is not mapped read/write - don't use it
3395 // fixme try to change permissions? check max_prot?
3396 if (PrintSharing) {
3397 _objc_inform("SHARING: memory from pid %d not read/write",
3398 remote.pid);
3399 }
3400 vm_deallocate(mach_task_self(), local_addr, remote.range.size);
3401 break;
3402 }
3403
3404 // Success
3405 result.address = local_addr;
3406 result.size = remote.range.size;
3407 }
3408 }
3409
3410 close_shared_range_file(file);
3411 return result;
3412 }
3413
3414
3415 /**********************************************************************
3416 * offer_shared_range
3417 * Offer memory range [aligned_start..aligned_end) in this process
3418 * to other Objective-C-using processes.
3419 * If some other entry in the shared range list matches this range,
3420 * is is overwritten with this process's PID. (Thus any stale PIDs are
3421 * replaced.)
3422 * If the shared range file could not be updated for any reason, this
3423 * function fails silently.
3424 * aligned_start and aligned_end must be page-aligned.
3425 **********************************************************************/
3426 static void offer_shared_range(vm_address_t aligned_start,
3427 vm_address_t aligned_end)
3428 {
3429 struct remote_range_t remote;
3430 struct remote_range_t local;
3431 BOOL found = NO;
3432 FILE *file;
3433 int err = 0;
3434
3435 local.range.address = aligned_start;
3436 local.range.size = aligned_end - aligned_start;
3437 local.pid = getpid();
3438
3439 // Open shared range file, creating if necessary
3440 file = open_shared_range_file(YES);
3441 if (!file) return;
3442
3443 // Find an existing entry for this range, if any
3444 while (1 == fread(&remote, sizeof(remote), 1, file)) {
3445 if (remote.pid != 0 &&
3446 remote.range.address == aligned_start &&
3447 remote.range.size == aligned_end - aligned_start)
3448 {
3449 // Found a match - overwrite it
3450 err = fseek(file, -sizeof(remote), SEEK_CUR);
3451 found = YES;
3452 break;
3453 }
3454 }
3455
3456 if (!found) {
3457 // No existing entry - write at the end of the file
3458 err = fseek(file, 0, SEEK_END);
3459 }
3460
3461 if (err == 0) {
3462 fwrite(&local, sizeof(local), 1, file);
3463 }
3464
3465 close_shared_range_file(file);
3466 }
3467
3468
3469 /**********************************************************************
3470 * install_shared_range
3471 * Install a shared range received from get_shared_range() into
3472 * its final resting place.
3473 * If possible, the memory is copied using virtual memory magic rather
3474 * than actual data writes. dst always gets updated values, even if
3475 * virtual memory magic is not possible.
3476 * The shared range is always deallocated.
3477 * src and dst must be page-aligned.
3478 **********************************************************************/
3479 static void install_shared_range(vm_range_t src, vm_address_t dst)
3480 {
3481 kern_return_t kr;
3482
3483 // Copy from src to dst
3484 kr = vm_copy(mach_task_self(), src.address, src.size, dst);
3485 if (kr != KERN_SUCCESS) {
3486 // VM copy failed. Use non-VM copy.
3487 if (PrintSharing) {
3488 _objc_inform("SHARING: vm_copy failed: %s", mach_error_string(kr));
3489 }
3490 memmove((void *)dst, (void *)src.address, src.size);
3491 }
3492
3493 // Unmap the shared range at src
3494 vm_deallocate(mach_task_self(), src.address, src.size);
3495 }