Annotation of objc/objc-runtime.m, revision 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.