Annotation of objc/objc-runtime.m, revision 1.1.1.1

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 *) &section[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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.