|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * objc-runtime.m
26: * Copyright 1988, NeXT, Inc.
27: * Author: s. naroff
28: *
29: */
30:
31: #ifdef SHLIB
32: #import "shlib.h"
33: #endif SHLIB
34:
35: #import "objc-private.h"
36: #include <mach-o/ldsyms.h>
37: #import "objc-runtime.h"
38: #import "hashtable.h"
39: #import "maptable.h"
40: #import "Object.h"
41: #import "Protocol.h"
42:
43: void *getsectdatafromheader(const struct mach_header *, char *, char *, int *);
44: static const struct segment_command *
45: getobjcsegmentfromheader(const struct mach_header *mhp);
46:
47: void (*callbackFunction)( Class, Category ) = 0;
48:
49: void *getsectdatafromheaderinfo(const struct header_info * info,
50: char * segname,
51: char * sectname,
52: int * size)
53: {
54: char *addr = getsectdatafromheader (info->mhdr, segname, sectname, size);
55: if (addr)
56: addr += info->image_slide;
57: return addr;
58: }
59:
60: /* Turn on support for literal string objects. */
61: #define LITERAL_STRING_OBJECTS
62:
63: /* system vectors...created at runtime by reading the `__OBJC' segments
64: * that are a part of the application.
65: */
66:
67: /* These two variables are now obsolete.
68: They have been replaced by header_vector and header_count. */
69:
70: static unsigned int module_count;
71: static Module *module_vector;
72:
73: /* We do not lock these variables, since they are only set during startup. */
74:
75: static struct header_info *header_vector = 0;
76: static unsigned int header_count = 0;
77:
78: /*
79: * Hash table of classes...
80: */
81: static NXHashTable *class_hash = 0;
82:
83: /* Mask which specifies whether we are multi-threaded or not.
84: A value of -1 means single-threaded, 0 means multi-threaded. */
85: int _objc_multithread_mask = -1;
86:
87: /* Lock for class hashtable. (Private extern) */
88:
89: OBJC_DECLARE_LOCK (classLock);
90:
91: static unsigned classHash (void *info, Class data)
92: {
93: return (data) ? _objc_strhash ((unsigned char *)((Class) data)->name) : 0;
94: }
95:
96: static int classIsEqual (void *info, Class name, Class cls)
97: {
98: return ((name->name[0] == cls->name[0]) &&
99: (strcmp(name->name, cls->name) == 0));
100: }
101:
102: static NXHashTablePrototype classHashPrototype =
103: {
104: (unsigned (*)(const void *, const void *))classHash,
105: (int (*)(const void *, const void *, const void *))classIsEqual,
106: NXNoEffectFree, 0
107: };
108:
109: /* This function is very dangerous, since you cannot safely use the hashtable
110: without locking it, and the lock is private! */
111:
112: NXHashTable *objc_getClasses (void)
113: {
114: return class_hash;
115: }
116:
117: static int _objc_defaultClassHandler(const char *clsName)
118: {
119: _objc_inform("class `%s' not linked into application", clsName);
120: return 0;
121: }
122:
123: static int (*objc_classHandler)(const char *) = _objc_defaultClassHandler;
124:
125: void objc_setClassHandler(int (*userSuppliedHandler)(const char *))
126: {
127: objc_classHandler = userSuppliedHandler;
128: }
129:
130: id objc_getClass(const char *aClassName)
131: {
132: struct objc_class cls;
133: id ret;
134:
135: OBJC_LOCK (&classLock);
136: cls.name = aClassName;
137:
138: if (!(ret = (id)NXHashGet(class_hash, &cls)))
139: {
140: int result;
141:
142: OBJC_UNLOCK (&classLock);
143: result = (*objc_classHandler)(aClassName);
144: OBJC_LOCK (&classLock);
145:
146: if (result)
147: ret = (id)NXHashGet(class_hash, &cls);
148: }
149:
150: OBJC_UNLOCK (&classLock);
151: return ret;
152: }
153:
154: /* Formerly objc_getClassWithoutWarning(). */
155:
156: id objc_lookUpClass (const char *aClassName)
157: {
158: struct objc_class cls;
159: id ret;
160:
161: OBJC_LOCK (&classLock);
162: cls.name = aClassName;
163:
164: ret = (id)NXHashGet(class_hash, &cls);
165:
166: OBJC_UNLOCK (&classLock);
167: return ret;
168: }
169:
170: id objc_getMetaClass(const char *aClassName)
171: {
172: Class class = objc_getClass (aClassName);
173:
174: if (class)
175: return class->isa;
176: else
177: return Nil;
178: }
179:
180: void objc_addClass (Class class)
181: {
182: OBJC_LOCK (&classLock);
183:
184: // make sure both the class and the metaclass have caches!
185: // Clear all bits of the info fields except CLS_CLASS and CLS_META.
186: // Normally these bits are already clear but if someone tries to cons
187: // up their own class on the fly they may need to be cleared.
188:
189: if (class->cache == NULL) {
190: class->cache = (Cache) &emptyCache;
191: class->info = CLS_CLASS;
192: }
193: if (class->isa->cache == NULL) {
194: class->isa->cache = (Cache) &emptyCache;
195: class->isa->info = CLS_META;
196: }
197:
198: NXHashInsert (class_hash, class);
199: OBJC_UNLOCK (&classLock);
200:
201: }
202:
203: /* Private extern used by objc_unloadModules(). */
204: void _objc_removeClass (Class class)
205: {
206: OBJC_LOCK (&classLock);
207: NXHashRemove (class_hash, class);
208: OBJC_UNLOCK (&classLock);
209:
210: }
211:
212: /* This only returns the statically linked modules.
213: I do not believe this is used now.
214: It has been replaced by _objc_headerVector(). */
215:
216: Module *objc_getModules (void)
217: {
218: if (!module_vector) {
219: Module mods;
220: unsigned int hidx, midx;
221: Module *mvp;
222:
223: for (hidx = 0; hidx < header_count; hidx++)
224: module_count += header_vector[hidx].mod_count;
225:
226: if (!(module_vector = NXZoneMalloc(_objc_create_zone(), sizeof(Module) * (module_count+1))))
227: _objc_fatal("unable to allocate module vector");
228:
229: for (hidx = 0, mvp = module_vector;
230: hidx < header_count; hidx++) {
231: for (mods = header_vector[hidx].mod_ptr, midx = 0;
232: midx < header_vector[hidx].mod_count;
233: midx++, mvp++) {
234:
235: *mvp = mods+midx;
236: }
237: }
238: *mvp = 0;
239: }
240: return module_vector;
241: }
242:
243: /* What could this be used for? It is not currently used. */
244:
245: Module *objc_addModule(Module myModule)
246: {
247: module_count++;
248: if (module_vector) {
249: module_vector = (Module *)NXZoneRealloc(_objc_create_zone(),
250: module_vector,
251: sizeof(Module) * (module_count + 1));
252: } else {
253: module_vector = (Module *)NXZoneMalloc(_objc_create_zone(),
254: sizeof(Module) * (module_count + 1));
255: }
256: if (!module_vector)
257: _objc_fatal("unable to reallocate module vector");
258:
259: module_vector[module_count-1] = myModule;
260: module_vector[module_count] = 0;
261: return module_vector;
262: }
263:
264: /* Private extern used by objc_unloadModules(). */
265:
266: void _objc_remove_category(struct objc_category *category, int version)
267: {
268: Class cls;
269:
270: if ((cls = objc_getClass(category->class_name))) {
271: if (category->instance_methods)
272: class_removeMethods(cls, category->instance_methods);
273:
274: if (category->class_methods)
275: class_removeMethods(cls->isa, category->class_methods);
276: if (version >= 5 && category->protocols)
277: _class_removeProtocols (cls, category->protocols);
278: } else {
279: _objc_inform("unable to remove category %s...\n",
280: category->category_name);
281: _objc_inform("class `%s' not linked into application\n",
282: category->class_name);
283: }
284: }
285:
286: static inline void
287: __objc_add_category(struct objc_category *category, int version)
288: {
289: Class cls;
290:
291: if ((cls = (Class)objc_getClass(category->class_name))) {
292: if (category->instance_methods) {
293: category->instance_methods->method_next = cls->methods;
294: cls->methods = category->instance_methods;
295: }
296: if (category->class_methods) {
297: category->class_methods->method_next = cls->isa->methods;
298: cls->isa->methods = category->class_methods;
299: }
300: if (version >= 5 && category->protocols)
301: {
302: if (cls->isa->version >= 5)
303: {
304: category->protocols->next = cls->protocols;
305: cls->protocols = category->protocols;
306: cls->isa->protocols = category->protocols;
307: }
308: else
309: {
310: _objc_inform ("unable to add protocols from category %s...\n",
311: category->category_name);
312: _objc_inform ("class `%s' must be recompiled\n",
313: category->class_name);
314: }
315: }
316: } else {
317: _objc_inform("unable to add category %s...\n",
318: category->category_name);
319: _objc_inform("class `%s' not linked into application\n",
320: category->class_name);
321: }
322: }
323:
324: /* Private extern used by objc_loadModules(). */
325:
326: void _objc_add_category(struct objc_category *category, int version)
327: {
328: __objc_add_category (category, version);
329:
330: _objc_flush_caches (objc_getClass (category->class_name));
331: }
332:
333: struct _objc_unresolved_category {
334: struct _objc_unresolved_category* next;
335: struct objc_category* cat;
336: long version;
337: };
338:
339: static NXMapTable* category_hash = 0;
340:
341: static void _objc_resolve_categories_for_class (Class cls)
342: {
343: struct _objc_unresolved_category *cat, *next;
344:
345: if (!category_hash)
346: return;
347:
348: cat = NXMapRemove (category_hash, cls->name);
349:
350: while (cat)
351: {
352: _objc_add_category (cat->cat, cat->version);
353:
354: next = cat->next;
355: free (cat);
356: cat = next;
357: }
358: }
359:
360:
361: static void _objc_register_category (struct objc_category *cat, long version)
362: {
363: struct _objc_unresolved_category *new_cat, *old;
364:
365: if (objc_lookUpClass (cat->class_name))
366: {
367: _objc_add_category (cat, version);
368: return;
369: }
370:
371: if (!category_hash)
372: category_hash = NXCreateMapTableFromZone (NXStrValueMapPrototype,
373: 128,
374: _objc_create_zone ());
375:
376: old = NXMapGet (category_hash, cat->class_name);
377: new_cat = NXZoneMalloc (_objc_create_zone(), sizeof (struct _objc_unresolved_category));
378: new_cat->next = old;
379: new_cat->cat = cat;
380: new_cat->version = version;
381: NXMapInsert (category_hash, cat->class_name , new_cat);
382: }
383:
384:
385: static void _objc_add_categories_from_image (struct header_info *hi)
386: {
387: Module mods;
388: unsigned int midx;
389:
390: for (mods = hi->mod_ptr, midx = 0;
391: midx < hi->mod_count;
392: midx++) {
393: unsigned int i, total;
394:
395: if (mods[midx].symtab == NULL)
396: continue;
397:
398: total = mods[midx].symtab->cls_def_cnt +
399: mods[midx].symtab->cat_def_cnt;
400:
401: /* add categories */
402: for (i = mods[midx].symtab->cls_def_cnt;
403: i < total; i++)
404: _objc_register_category(mods[midx].symtab->defs[i],
405: mods[midx].version);
406: }
407: }
408:
409: static const struct header_info *_headerForClass(Class class)
410: {
411: const struct mach_header *foundHeader;
412: const struct segment_command *objcSeg;
413: unsigned int hidx;
414:
415: for (foundHeader = NULL, hidx = 0;
416: !foundHeader && (hidx < header_count);
417: hidx++)
418: {
419: unsigned long slide = header_vector[hidx].image_slide;
420: objcSeg = getobjcsegmentfromheader(header_vector[hidx].mhdr);
421: if ((objcSeg->vmaddr + slide <= (unsigned long)class)
422: && ((unsigned long)class < (objcSeg->vmaddr + slide + objcSeg->vmsize)))
423: {
424: return &(header_vector[hidx]);
425: }
426: }
427:
428: return 0;
429: }
430:
431: static const struct mach_header *_getExecHeader ()
432: {
433: unsigned int hidx;
434: for (hidx = 0; hidx < header_count; hidx++)
435: if (header_vector[hidx].mhdr->filetype != MH_FVMLIB)
436: {
437: return header_vector[hidx].mhdr;
438: }
439: return NULL;
440: }
441:
442: /* private extern. */
443:
444: const char *_nameForHeader(const struct mach_header *header)
445: {
446: const struct mach_header *execHeader;
447: const struct fvmlib_command *libCmd, *endOfCmds;
448: char **argv;
449: #if defined(__DYNAMIC__)
450: extern char ***_NSGetArgv();
451: argv = *_NSGetArgv();
452: #else
453: extern char **NXArgv;
454: argv = NXArgv;
455: #endif
456: if (header && header->filetype == MH_FVMLIB) {
457: execHeader = _getExecHeader();
458: for (libCmd = (const struct fvmlib_command *)(execHeader + 1),
459: endOfCmds = ((void *)libCmd) + execHeader->sizeofcmds;
460: libCmd < endOfCmds;
461: ((void *)libCmd) += libCmd->cmdsize) {
462: if ((libCmd->cmd == LC_LOADFVMLIB)
463: && (libCmd->fvmlib.header_addr
464: == (unsigned long)header)) {
465: return (char *)libCmd
466: + libCmd->fvmlib.name.offset;
467: }
468: }
469: return NULL;
470: } else
471: return argv[0];
472: }
473:
474: static void _resolveClassConflict(NXHashTable *clsHash,
475: Class oldClass,
476: Class newClass)
477: {
478: const struct header_info *oldHeader = _headerForClass(oldClass);
479: const struct header_info *newHeader = _headerForClass(newClass);
480: const char *oldName = _nameForHeader(oldHeader->mhdr);
481: const char *newName = _nameForHeader(newHeader->mhdr);
482:
483: _objc_inform("Both %s and %s have implementations of class %s.",
484: oldName, newName, oldClass->name);
485: if (newHeader->mhdr->filetype == MH_FVMLIB) {
486: NXHashInsert(clsHash, oldClass);
487: _objc_inform("Using implementation from %s.", oldName);
488: } else
489: _objc_inform("Using implementation from %s.", newName);
490: }
491:
492: static NXHashTable *_objc_init_class_hash ()
493: {
494: return NXCreateHashTableFromZone(classHashPrototype, 8, nil, _objc_create_zone());
495: }
496:
497:
498: static NXHashTable *_objc_get_classes_from_image (NXHashTable *clsHash,
499: struct header_info* hi)
500: {
501: unsigned int i;
502: Module mods;
503: unsigned int midx;
504: Class oldCls, newCls;
505:
506: for (mods = hi->mod_ptr, midx = 0;
507: midx < hi->mod_count;
508: midx++)
509: {
510: if (mods[midx].symtab == NULL)
511: continue;
512:
513: for (i = 0; i < mods[midx].symtab->cls_def_cnt; i++) {
514: oldCls = NXHashInsert(clsHash,
515: mods[midx].symtab->defs[i]);
516: if (oldCls)
517: {
518: _resolveClassConflict(clsHash,
519: oldCls,
520: mods[midx].symtab->defs[i]);
521: newCls = objc_lookUpClass (oldCls->name);
522: }
523: else
524: {
525: newCls = mods[midx].symtab->defs[i];
526: }
527:
528: if (newCls != oldCls)
529: {
530: newCls->isa->version = mods[midx].version;
531: }
532:
533: _objc_resolve_categories_for_class (newCls);
534: }
535: }
536:
537: return clsHash;
538: }
539:
540:
541: #ifdef LITERAL_STRING_OBJECTS
542:
543: /* Initialize the isa pointers of all NXConstantString objects. */
544:
545: #include <NXString.h>
546:
547: static void _objc_fixup_string_objects_for_image (struct header_info* hi)
548: {
549: NXConstantString *section;
550: unsigned int size;
551:
552: section = getsectdatafromheaderinfo (hi,
553: SEG_OBJC, "__string_object", &size);
554: if (section != 0 && size != 0)
555: {
556: Class constantStringClass = objc_getClass ("NXConstantString");
557: unsigned int i;
558:
559: for (i = 0; i < size / sizeof (NXConstantString); i++)
560: *((Class *) §ion[i]) = constantStringClass;
561: }
562: }
563: #endif /* LITERAL_STRING_OBJECTS */
564:
565: #ifdef OBJC_CLASS_REFS
566: static void _objc_map_class_refs_for_image (struct header_info* hi)
567: {
568: Class *cls_refs;
569: unsigned int size;
570:
571: cls_refs = (Class *) getsectdatafromheaderinfo (hi,
572: SEG_OBJC,
573: "__cls_refs",
574: &size);
575:
576: if (cls_refs)
577: {
578: unsigned int i;
579:
580: for (i = 0; i < size / sizeof (Class); i++) {
581: const char *ref = (const char *) cls_refs[i];
582: Class cls = objc_lookUpClass( ref );
583: cls_refs[i] = cls;
584: }
585: }
586: }
587: #endif /* OBJC_CLASS_REFS */
588:
589:
590: static inline void map_selrefs (SEL *sels, unsigned int cnt)
591: {
592: unsigned int i;
593:
594: /* Overwrite the string with a unique identifier. */
595: for (i = 0; i < cnt; i++)
596: {
597: SEL sel = _sel_registerName ((const char *) sels[i]);
598:
599: if (sels[i] != sel)
600: sels[i] = sel;
601: }
602: }
603:
604:
605: static inline void map_methods (struct objc_method_list *methods)
606: {
607: unsigned int i;
608:
609: for (i = 0; i < methods->method_count; i++)
610: {
611: Method method = &methods->method_list[i];
612: SEL sel = _sel_registerName ((const char *) method->method_name);
613:
614: if (method->method_name != sel)
615: method->method_name = sel;
616: }
617: }
618:
619:
620: static inline void map_method_descs (struct objc_method_description_list *methods)
621: {
622: unsigned int i;
623:
624: for (i = 0; i < methods->count; i++)
625: {
626: struct objc_method_description *method = &methods->list[i];
627: SEL sel = _sel_registerName ((const char *) method->name);
628:
629: if (method->name != sel)
630: method->name = sel;
631: }
632: }
633:
634: #import "Protocol.h"
635:
636: struct objc_protocol
637: {
638: @defs(Protocol)
639: };
640:
641: @interface Protocol(RuntimePrivate)
642: + _fixup: (Protocol *)protos numElements: (int) nentries;
643: @end
644:
645: static void
646: _objc_fixup_protocol_objects_for_image (struct header_info* hi)
647: {
648: unsigned int size;
649: /* Fixup protocol objects. */
650: struct objc_protocol * protos = (struct objc_protocol *)
651: getsectdatafromheaderinfo (hi, SEG_OBJC, "__protocol", &size);
652:
653: if (protos)
654: {
655: unsigned int i;
656:
657: for (i = 0; i < size / sizeof (Protocol); i++) {
658:
659: /* can't use map_methods, the sizes differ. */
660: if (protos[i].instance_methods)
661: map_method_descs (protos[i].instance_methods);
662: if (protos[i].class_methods)
663: map_method_descs (protos[i].class_methods);
664: }
665: [Protocol _fixup: (Protocol *)protos numElements: size / sizeof (Protocol)];
666: }
667: }
668:
669:
670:
671: static const struct segment_command *
672: getobjcsegmentfromheader(const struct mach_header *mhp)
673: {
674: struct segment_command *sgp;
675: unsigned long i;
676:
677: sgp = (struct segment_command *)
678: ((char *)mhp + sizeof(struct mach_header));
679: for(i = 0; i < mhp->ncmds; i++){
680: if(sgp->cmd == LC_SEGMENT)
681: if(strncmp(sgp->segname, "__OBJC", sizeof(sgp->segname)) == 0)
682: return sgp;
683: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
684: }
685: return((struct segment_command *)0);
686: }
687:
688:
689: /* Comparison function for sorting headers. Place all headers which have
690: freeze-dried hashtables before any which don't. Otherwise sort by
691: decreasing size. */
692:
693: static int compareHeaders (const void *x1, const void *x2)
694: {
695: const struct header_info *header1 = x1, *header2 = x2;
696:
697: if (header1->frozenTable && !header2->frozenTable)
698: return -1;
699: else if (header2->frozenTable && !header1->frozenTable)
700: return 1;
701:
702: return (header2->objcSize - header1->objcSize);
703: }
704:
705:
706: /* Build the header vector, sorting it as _objc_map_selectors() expects. */
707:
708: struct header_info *_objc_headerVector (const struct mach_header * const *machhdrs)
709: {
710: unsigned int hidx;
711: struct header_info *hdrVec;
712:
713: if (header_vector)
714: return header_vector;
715:
716: for (hidx = 0; machhdrs[hidx]; hidx++)
717: header_count++;
718:
719: hdrVec = NXZoneMalloc (_objc_create_zone(),
720: header_count * sizeof (struct header_info));
721: if (!hdrVec)
722: _objc_fatal ("unable to allocate module vector");
723:
724: for (hidx = 0; hidx < header_count; hidx++)
725: {
726: int size;
727: const struct segment_command *objcSeg;
728:
729: hdrVec[hidx].mhdr = machhdrs[hidx];
730: hdrVec[hidx].image_slide = 0;
731: hdrVec[hidx].mod_ptr = (Module) getsectdatafromheader (machhdrs[hidx],
732: SEG_OBJC, SECT_OBJC_MODULES, &size);
733: hdrVec[hidx].mod_count = size / sizeof (struct objc_module);
734: hdrVec[hidx].frozenTable = getsectdatafromheader (machhdrs[hidx],
735: SEG_OBJC, "__runtime_setup", &size);
736: objcSeg = getobjcsegmentfromheader (machhdrs[hidx]);
737: if (objcSeg)
738: hdrVec[hidx].objcSize = objcSeg->filesize;
739: else
740: hdrVec[hidx].objcSize = 0;
741: }
742:
743: /* Sort the headers for _objc_map_selectors(). */
744: qsort (hdrVec, header_count, sizeof (struct header_info), &compareHeaders);
745:
746: return hdrVec;
747: }
748:
749:
750: unsigned int _objc_headerCount (void)
751: {
752: return header_count;
753: }
754:
755:
756: void _objc_addHeader (const struct mach_header *header, long vmaddr_slide)
757: {
758: header_count++;
759: if (header_vector == 0)
760: header_vector = NXZoneMalloc (_objc_create_zone(),
761: header_count * sizeof (struct header_info));
762: else
763: {
764: void *old = (void*)header_vector;
765: header_vector = NXZoneMalloc (_objc_create_zone(),
766: header_count * sizeof (struct header_info));
767:
768: memcpy ((void*)header_vector, old, (header_count-1) * sizeof (struct header_info));
769: NXZoneFree (_objc_create_zone(), old);
770: // header_vector = NXZoneRealloc (_objc_create_zone(), header_vector,
771: // header_count * sizeof (struct header_info));
772: }
773:
774: header_vector[header_count - 1].mhdr = header;
775: header_vector[header_count - 1].mod_ptr = NULL;
776: header_vector[header_count - 1].mod_count = 0;
777: header_vector[header_count - 1].frozenTable = NULL;
778: header_vector[header_count - 1].image_slide = 0;
779: header_vector[header_count - 1].objcSize = 0;
780: }
781:
782:
783: void _objc_removeHeader (const struct mach_header *header)
784: {
785: unsigned int i, j;
786:
787: for (i = 0; i < header_count; i++)
788: if (header_vector[i].mhdr == header)
789: for (j = i; j < header_count - 1; j++)
790: header_vector[j] = header_vector[j + 1];
791:
792: header_count--;
793: header_vector = NXZoneRealloc (_objc_create_zone(), header_vector,
794: header_count * sizeof (struct header_info));
795: }
796:
797:
798: /* Register all of the selectors in each image, and fix them all up.
799: We must register all images which have freeze-dried hashtables before any
800: which don't, since the freeze-dried hashtables are searched before the
801: dynamic hashtable. We also want to register the freeze-dried hashtables
802: in decreasing order of size to minimize selector lookup time. We don't
803: need to fixup the selectors in the first image we register, since those
804: strings will always be used. If the first image has a freeze-dried
805: hashtable, then we don't need to run over its selectors at all, since
806: we can register them all at once. */
807:
808: static void _objc_map_install_selectors (struct header_info* hi)
809: {
810: Module mods = hi->mod_ptr;
811: unsigned int midx;
812: unsigned int size;
813:
814: /* Register selectors from freeze-dried hashtables. */
815: if (hi->frozenTable)
816: {
817: const char *strings = (const char *)
818: getsectdatafromheaderinfo (hi,
819: SEG_OBJC, "__meth_var_names", &size);
820:
821: if (!strings)
822: {
823: /* Try old-style strings. */
824: strings = (const char *)
825: getsectdatafromheaderinfo (hi,
826: SEG_OBJC,
827: "__selector_strs", &size);
828: }
829:
830: _sel_init (hi->mhdr,
831: strings,
832: size,
833: hi->frozenTable);
834: }
835: }
836:
837: static void _objc_map_selectors_from_image (struct header_info* hi)
838: {
839: Module mods = hi->mod_ptr;
840: unsigned int midx;
841: unsigned int size;
842: SEL *messages_refs;
843: struct proto_template { @defs (Protocol) } *protos;
844:
845: /* Map message refs. */
846: messages_refs = (SEL *) getsectdatafromheaderinfo (hi,
847: SEG_OBJC,
848: "__message_refs",
849: &size);
850: if (messages_refs)
851: map_selrefs (messages_refs, size / sizeof (SEL));
852:
853: for (midx = 0; midx < hi->mod_count; midx++)
854: {
855: unsigned int i;
856: struct objc_method_list* mlist;
857:
858: if (mods[midx].symtab == NULL)
859: continue;
860:
861: /* Map class defs. */
862: for (i = 0; i < mods[midx].symtab->cls_def_cnt; i++)
863: {
864: Class cls = mods[midx].symtab->defs[i];
865:
866: if (cls->methods)
867: {
868: mlist = cls->methods;
869: while (mlist->method_next) mlist = mlist->method_next;
870: map_methods (mlist);
871: }
872:
873: if (cls->isa->methods)
874: {
875: mlist = cls->isa->methods;
876: while (mlist->method_next) mlist = mlist->method_next;
877: map_methods (mlist);
878: }
879: }
880:
881: /* Map category defs. */
882: for (i = mods[midx].symtab->cls_def_cnt;
883: i < (mods[midx].symtab->cls_def_cnt +
884: mods[midx].symtab->cat_def_cnt);
885: i++)
886: {
887: Category cat = mods[midx].symtab->defs[i];
888:
889: if (cat->instance_methods)
890: map_methods (cat->instance_methods);
891: if (cat->class_methods)
892: map_methods (cat->class_methods);
893: }
894: }
895:
896: /* Fixup protocols. */
897: protos = (struct proto_template *) getsectdatafromheaderinfo ( hi,
898: SEG_OBJC,
899: "__protocol",
900: &size);
901: if (protos)
902: {
903: unsigned int i;
904:
905: for (i = 0; i < size / sizeof (Protocol); i++)
906: {
907: if (protos[i].instance_methods)
908: map_method_descs (protos[i].instance_methods);
909: if (protos[i].class_methods)
910: map_method_descs (protos[i].class_methods);
911: }
912: }
913: }
914:
915: #if 0
916: /*
917: * Purpose: The idea here is to call objc_msgSend() with the
918: * arguments in args. The args must already be in the
919: * appropriate format for the stack (perhaps copied
920: * form some other stack frame).
921: *
922: * The final call to objc_msgSend () is thus equivalent to
923: * objc_msgSend (self, op, arg[0], arg[1], ..., arg[size - 1]).
924: *
925: * Assumptions: Do not compile this with -fomit-frame-pointer!
926: */
927: id objc_msgSendv (id self, SEL sel, unsigned size, marg_list args)
928: {
929: unsigned int i;
930:
931: size -= (sizeof(id) + sizeof(SEL));
932: args += (sizeof(id) + sizeof(SEL));
933:
934: #ifdef m68k
935: /* Push the args onto the stack. */
936: for (i = (size + 1) / sizeof (short); i > 0; i--)
937: asm ("movew %0,sp@-" : : "a" (((short *) args)[i-1]));
938: #else
939: panic ("objc_msgSendv");
940: #endif
941: return objc_msgSend (self, sel);
942: }
943: #endif
944:
945: static void _objc_call_loads_for_image (struct header_info* header)
946: {
947: extern IMP class_lookupMethodInMethodList(struct objc_method_list *mlist,
948: SEL sel);
949: Class class, *pClass;
950: Category *pCategory;
951: IMP load_method;
952: struct objc_method_list *methods;
953: unsigned int nModules, nClasses, nCategories;
954: struct objc_module *module;
955: struct objc_symtab *symtab;
956:
957: for (nModules = header->mod_count, module = header->mod_ptr;
958: nModules;
959: nModules--, module++) {
960:
961: symtab = module->symtab;
962: if (symtab == NULL)
963: continue;
964: for (nClasses = symtab->cls_def_cnt, pClass = (Class *)symtab->defs;
965: nClasses;
966: nClasses--, pClass++)
967: {
968: class = *pClass;
969:
970: if (methods = class->isa->methods)
971: {
972: while (methods->method_next)
973: methods = methods->method_next;
974:
975: load_method = class_lookupMethodInMethodList(methods,
976: @selector(load));
977: if (load_method)
978: (*load_method)((id)class, @selector(load));
979: }
980: }
981:
982: for (nCategories = symtab->cat_def_cnt,
983: pCategory = (Category *)&symtab->defs[symtab->cls_def_cnt];
984: nCategories;
985: nCategories--, pCategory++)
986: {
987: class = objc_getClass ((*pCategory)->class_name);
988:
989: if (methods = (*pCategory)->class_methods)
990: {
991: load_method = class_lookupMethodInMethodList(methods,
992: @selector(load));
993: if (load_method)
994: (*load_method)((id)class, @selector(load));
995: }
996: }
997: }
998: }
999:
1000:
1001: void objc_setMultithreaded (BOOL flag)
1002: {
1003: if (flag == YES)
1004: _objc_multithread_mask = 0;
1005: else
1006: _objc_multithread_mask = -1;
1007: }
1008:
1009:
1010: static void
1011: _objc_map_image_callback (struct header_info *h);
1012:
1013: void _objcInit (void)
1014: {
1015: int hidx;
1016: class_hash = _objc_init_class_hash();
1017:
1018: {
1019: extern struct mach_header **getmachheaders (void);
1020: struct mach_header **machheaders;
1021:
1022: if ((machheaders = getmachheaders())) {
1023: int i = -1;
1024: header_vector = _objc_headerVector( machheaders );
1025: while ( ++i < header_count )
1026: _objc_map_install_selectors (&header_vector[i]);
1027:
1028: i = -1;
1029: while ( ++i < header_count )
1030: _objc_map_image_callback (&header_vector[i]);
1031:
1032: free (machheaders);
1033: }
1034:
1035: for (hidx = 0; hidx < header_count; hidx++)
1036: {
1037: int nModules, i;
1038: struct objc_module* module;
1039:
1040: for (nModules = header_vector[hidx].mod_count, module = header_vector[hidx]. mod_ptr;
1041: nModules;
1042: nModules--, module++)
1043: {
1044: for (i = 0; i < module->symtab->cls_def_cnt; i++)
1045: {
1046: Class cls = (Class)module->symtab->defs[i];
1047: _class_install_relationships (cls, module->version);
1048: }
1049: }
1050:
1051: #ifdef LITERAL_STRING_OBJECTS
1052: _objc_fixup_string_objects_for_image (&header_vector[hidx]);
1053: #endif /* LITERAL_STRING_OBJECTS */
1054: #ifdef OBJC_CLASS_REFS
1055: _objc_map_class_refs_for_image (&header_vector[hidx]);
1056: #endif /* OBJC_CLASS_REFS */
1057: }
1058:
1059: for (hidx = 0; hidx < header_count; hidx++)
1060: _objc_fixup_protocol_objects_for_image (&header_vector[hidx]);
1061:
1062: for (hidx = 0; hidx < header_count; hidx++)
1063: _objc_call_loads_for_image (&header_vector[hidx]);
1064: }
1065: }
1066:
1067: static void
1068: _objc_map_image_callback (struct header_info *h )
1069: {
1070: class_hash = _objc_get_classes_from_image (class_hash, h);
1071:
1072: _objc_map_selectors_from_image (h);
1073: _objc_add_categories_from_image (h);
1074: }
1075:
1076:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.