Annotation of objc/objc-load.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-load.m
        !            26:  *     Copyright 1988, NeXT, Inc.
        !            27:  *     Author: s. naroff
        !            28:  *
        !            29:  */
        !            30: #ifdef SHLIB
        !            31: #import "shlib.h"
        !            32: #endif SHLIB
        !            33: 
        !            34: #import "objc-private.h"
        !            35: #import "objc-load.h"  
        !            36: #import "objc-runtime.h"
        !            37: #import "hashtable.h"
        !            38: #import "Object.h"
        !            39: #import "Protocol.h"
        !            40: #include <NXString.h>
        !            41: #include <mach-o/rld.h>
        !            42: 
        !            43: #ifdef RUNTIME_DYLD
        !            44: #include <mach-o/dyld.h>
        !            45: #endif
        !            46: 
        !            47: #ifdef KERNEL
        !            48: extern char *getsectdatafromheader(
        !            49:         const struct mach_header *mhp,
        !            50:         const char *segname,
        !            51:         const char *sectname,
        !            52:         int *size);
        !            53: #endif
        !            54: 
        !            55: @interface Protocol(Private)
        !            56: + _fixup: (void *)protos numElements: (int) nentries;
        !            57: @end
        !            58: 
        !            59: /* Private extern */
        !            60: extern struct mach_header *rld_get_current_header(void);
        !            61: extern void (*callbackFunction)( Class, Category );
        !            62: 
        !            63: static inline void map_selrefs (SEL *sels, unsigned int cnt)
        !            64: { 
        !            65:   unsigned int i;
        !            66:   
        !            67:   /* Overwrite the string with a unique identifier. */
        !            68:   for (i = 0; i < cnt; i++)
        !            69:     {
        !            70:       SEL sel = sel_registerName ((const char *) sels[i]);
        !            71:       
        !            72:       if (sels[i] != sel)
        !            73:        sels[i] = sel;
        !            74:     }
        !            75: }
        !            76: 
        !            77: 
        !            78: static inline void map_methods (struct objc_method_list *methods)
        !            79: {
        !            80:   unsigned int i;
        !            81:   
        !            82:   for (i = 0; i < methods->method_count; i++)
        !            83:     {
        !            84:       Method method = &methods->method_list[i];
        !            85:       SEL sel = sel_registerName ((const char *) method->method_name);
        !            86:       
        !            87:       if (method->method_name != sel)
        !            88:        method->method_name = sel;
        !            89:     }            
        !            90: }
        !            91: 
        !            92: 
        !            93: static inline void map_method_descs (struct objc_method_description_list *methods)
        !            94: {
        !            95:   unsigned int i;
        !            96:   
        !            97:   for (i = 0; i < methods->count; i++)
        !            98:     {
        !            99:       struct objc_method_description *method = &methods->list[i];
        !           100:       SEL sel = sel_registerName ((const char *) method->name);
        !           101:       
        !           102:       if (method->name != sel)
        !           103:        method->name = sel;
        !           104:     }            
        !           105: }
        !           106: 
        !           107: 
        !           108: static struct objc_method_list *get_base_method_list(Class cls)
        !           109: {
        !           110:        struct objc_method_list *mlist, *prev = 0;
        !           111: 
        !           112:        for (mlist = cls->methods; mlist; mlist = mlist->method_next)
        !           113:                prev = mlist;
        !           114: 
        !           115:        return prev;
        !           116: }
        !           117: 
        !           118: static void send_load_message_to_class(Class cls, void *header_addr)
        !           119: {
        !           120:        struct objc_method_list *mlist = get_base_method_list(cls->isa);
        !           121:        IMP load_method;
        !           122: 
        !           123:        if (mlist) {
        !           124:                load_method = 
        !           125:                   class_lookupMethodInMethodList(mlist, 
        !           126:                                @selector(finishLoading:));
        !           127: 
        !           128:                /* go directly there, we do not want to accidentally send
        !           129:                   the finishLoading: message to one of its categories...
        !           130:                */
        !           131:                if (load_method)
        !           132:                        (*load_method)((id)cls, @selector(finishLoading:), 
        !           133:                                header_addr);
        !           134:        }
        !           135: }
        !           136: 
        !           137: static void send_load_message_to_category(Category cat, void *header_addr)
        !           138: {
        !           139:        struct objc_method_list *mlist = cat->class_methods;
        !           140:        IMP load_method;
        !           141:        Class cls;
        !           142: 
        !           143:        if (mlist) {
        !           144:                load_method = 
        !           145:                   class_lookupMethodInMethodList(mlist, 
        !           146:                                @selector(finishLoading:));
        !           147: 
        !           148:                cls = objc_getClass (cat->class_name);
        !           149: 
        !           150:                /* go directly there, we do not want to accidentally send
        !           151:                   the finishLoading: message to one of its categories...
        !           152:                */
        !           153:                if (load_method)
        !           154:                        (*load_method)(cls, @selector(finishLoading:), 
        !           155:                                header_addr);
        !           156:        }
        !           157: }
        !           158: 
        !           159: static void send_unload_message_to_class(Class cls)
        !           160: {
        !           161:        struct objc_method_list *mlist = get_base_method_list(cls->isa);
        !           162:        IMP load_method;
        !           163: 
        !           164:        if (mlist) {
        !           165:                load_method = 
        !           166:                   class_lookupMethodInMethodList(mlist, 
        !           167:                                @selector(startUnloading));
        !           168: 
        !           169:                /* go directly there, we do not want to accidentally send
        !           170:                   the finishLoading: message to one of its categories...
        !           171:                */
        !           172:                if (load_method)
        !           173:                        (*load_method)((id)cls, 
        !           174:                                @selector(startUnloading));
        !           175:        }
        !           176: }
        !           177: 
        !           178: static void send_unload_message_to_category(Category cat)
        !           179: {
        !           180:        struct objc_method_list *mlist = cat->class_methods;
        !           181:        IMP load_method;
        !           182:        Class cls;
        !           183: 
        !           184:        if (mlist) {
        !           185:                load_method = 
        !           186:                   class_lookupMethodInMethodList(mlist, 
        !           187:                                @selector(startUnloading));
        !           188: 
        !           189:                cls = objc_getClass (cat->class_name);
        !           190: 
        !           191:                /* go directly there, we do not want to accidentally send
        !           192:                   the finishLoading: message to one of its categories...
        !           193:                */
        !           194:                if (load_method)
        !           195:                        (*load_method)((id)cls, 
        !           196:                                @selector(startUnloading));
        !           197:        }
        !           198: }
        !           199: 
        !           200: static void _objc_fixup_string_objects_from_header(struct mach_header *header)
        !           201: {
        !           202:     NXConstantString *section;
        !           203:     unsigned int size;
        !           204:     
        !           205:     section = (NXConstantString *) getsectdatafromheader (header,
        !           206:                SEG_OBJC, "__string_object", &size);
        !           207:     if (section != 0 && size != 0)
        !           208:     {
        !           209:        Class constantStringClass = objc_getClass ("NXConstantString");
        !           210:        unsigned int i;
        !           211:        
        !           212:        for (i = 0; i < size / sizeof (NXConstantString); i++)
        !           213:        *((Class *) &section[i]) = constantStringClass;
        !           214:     }
        !           215: }
        !           216: 
        !           217: 
        !           218: int objc_registerModule (struct mach_header *header_addr,
        !           219:                    void (*class_callback) (Class, Category))
        !           220: {
        !           221:   Module mod, modhdr;
        !           222:   int size, saveSize, i;
        !           223:   SEL *sels;
        !           224:   // this isn't very object oriented!...bypass ivar protection.
        !           225:   struct proto_template { @defs(Protocol) } *protos;
        !           226:   Class *cls_refs;
        !           227:   int errflag = 0;
        !           228: 
        !           229: #ifdef RUNTIME_DYLD
        !           230:   if (_dyld_present ())
        !           231:     {
        !           232:       fprintf (stderr, "objc_registerModule not supported in dynamic programs\n");
        !           233:       return 1;
        !           234:     }
        !           235: #endif
        !           236: 
        !           237:   modhdr = (Module) getsectdatafromheader (header_addr,
        !           238:                    SEG_OBJC, "__module_info", &saveSize);
        !           239: 
        !           240:   /* Check for duplicate classes.
        !           241:       This should never happen since rld should detect multiple
        !           242:       definitions of the .objc_class_name_XXX symbols. */
        !           243:   for (mod = modhdr, size = saveSize;
        !           244:        mod && size;
        !           245:        size -= mod->size, (char *) mod += mod->size)
        !           246:     {
        !           247:       for (i = 0; i < mod->symtab->cls_def_cnt; i++)
        !           248:        {
        !           249:          Class cls = mod->symtab->defs[i];
        !           250: 
        !           251:          if ((cls = objc_lookUpClass (mod->symtab->defs[i])))
        !           252:            {
        !           253: #if 0
        !           254:              NXPrintf (errStream, "objc_loadModules(): "
        !           255:                        "Duplicate definition for class `%s'\n",
        !           256:                        [cls name]);
        !           257: #endif
        !           258:              errflag = 1;
        !           259:            }
        !           260:        }
        !           261:     }
        !           262: 
        !           263:   if (errflag)
        !           264:     return 1;
        !           265: 
        !           266:   _objc_addHeader (header_addr, 0);
        !           267: 
        !           268:   /* Fixup string objects. */
        !           269:   _objc_fixup_string_objects_from_header (header_addr);
        !           270: 
        !           271:   /* Map selectors. */
        !           272:   sels = (SEL *) getsectdatafromheader (header_addr,
        !           273:                    SEG_OBJC, "__message_refs", &size);
        !           274:   if (sels)
        !           275:     map_selrefs (sels, size / sizeof (SEL));
        !           276: 
        !           277:   /* Fixup protocol objects. */
        !           278:   protos = (struct proto_template *) getsectdatafromheader (
        !           279:                header_addr, SEG_OBJC, "__protocol", &size);
        !           280:   if (protos)
        !           281:     {
        !           282:       unsigned int i;
        !           283:       
        !           284:       for (i = 0; i < size / sizeof (Protocol); i++) {
        !           285: 
        !           286:          /* can't use map_methods, the sizes differ. */
        !           287:          if (protos[i].instance_methods)
        !           288:            map_method_descs (protos[i].instance_methods);
        !           289:          if (protos[i].class_methods)
        !           290:            map_method_descs (protos[i].class_methods);
        !           291:        }
        !           292:       [Protocol _fixup: protos numElements: size / sizeof (Protocol)];
        !           293:     }
        !           294: 
        !           295:   /* Insert classes into class hashtable */
        !           296:   for (mod = modhdr, size = saveSize;
        !           297:        mod && size;
        !           298:        size -= mod->size, (char *) mod += mod->size)
        !           299:     {
        !           300:       for (i = 0; i < mod->symtab->cls_def_cnt; i++)
        !           301:        {
        !           302:          objc_addClass (mod->symtab->defs[i]);
        !           303:        }
        !           304:     }
        !           305: 
        !           306:   /* Process class definitions. */
        !           307:   for (mod = modhdr, size = saveSize;
        !           308:        mod && size;
        !           309:        size -= mod->size, (char *) mod += mod->size)
        !           310:     {
        !           311:       for (i = 0; i < mod->symtab->cls_def_cnt; i++)
        !           312:        {
        !           313:          Class cls = mod->symtab->defs[i];
        !           314: 
        !           315:          if (cls->methods)
        !           316:            map_methods (cls->methods);
        !           317:          if (cls->isa->methods)
        !           318:            map_methods (cls->isa->methods);
        !           319: 
        !           320:          _class_install_relationships (cls, mod->version);
        !           321: 
        !           322:          /* Versions 3 and 4 will never ship; internal compatibility only.
        !           323:              Compensate for "next" field in struct objc_protocol_list. */
        !           324:          if (cls->isa->version >= 3 && cls->isa->version <= 4
        !           325:              && cls->protocols)
        !           326:            {
        !           327:              (char *) cls->protocols -= 4;
        !           328:              (char *) cls->isa->protocols -= 4;
        !           329:            }
        !           330: 
        !           331:          /* for internal compatibility...should remove! */
        !           332:          if ((cls->isa->version == 3) && cls->protocols)
        !           333:            {
        !           334:              _objc_inform ("Unable to install protocols by name...\n");
        !           335:              _objc_inform ("Class %s must be recompiled.\n",
        !           336:                            cls->name);
        !           337:              cls->protocols = 0;
        !           338:              cls->isa->protocols = 0;
        !           339:            }
        !           340:        }
        !           341:     }
        !           342: 
        !           343:   /* We must process all classes before any categories, or else
        !           344:       we might map the selectors for a category method twice. */
        !           345: 
        !           346:   /* Process category definitions. */
        !           347:   for (mod = modhdr, size = saveSize;
        !           348:        mod && size;
        !           349:        size -= mod->size, (char *) mod += mod->size)
        !           350:     {
        !           351:       for (i = mod->symtab->cls_def_cnt;
        !           352:            i < mod->symtab->cls_def_cnt + mod->symtab->cat_def_cnt;
        !           353:            i++)
        !           354:        {
        !           355:          Category cat = mod->symtab->defs[i];
        !           356: 
        !           357:          if (cat->instance_methods)
        !           358:            map_methods (cat->instance_methods);
        !           359:          if (cat->class_methods)
        !           360:            map_methods (cat->class_methods);
        !           361: 
        !           362:          _objc_add_category (mod->symtab->defs[i], mod->version);
        !           363:        }
        !           364:     }
        !           365: 
        !           366:   /* Handle v1.0 mapping of selector references */
        !           367:   for (mod = modhdr, size = saveSize;
        !           368:        mod && size;
        !           369:        size -= mod->size, (char *) mod += mod->size)
        !           370:     {
        !           371:       if (mod->version == 1)
        !           372:        map_selrefs (mod->symtab->refs, mod->symtab->sel_ref_cnt);
        !           373:     }
        !           374: 
        !           375: #ifdef OBJC_CLASS_REFS
        !           376:   /* Fixup class references. */
        !           377:   cls_refs = (Class *) getsectdatafromheader (
        !           378:                header_addr, SEG_OBJC, "__cls_refs", &size);
        !           379:   if (cls_refs)
        !           380:     {
        !           381:       unsigned int i;
        !           382:       
        !           383:       for (i = 0; i < size / sizeof (Class); i++)
        !           384:        cls_refs[i] = objc_getClass ((const char *) cls_refs[i]);
        !           385:     }
        !           386: #endif /* OBJC_CLASS_REFS */
        !           387: 
        !           388:   /* Do we guarantee any ordering of load messages?
        !           389:       We might send a load message to a subclass before its superclass.
        !           390: 
        !           391:       Also, a load method might send a message to a class which hasn't
        !           392:       received its load message yet by using objc_getClass ().
        !           393: 
        !           394:       To solve these problems properly, we probably need to add a
        !           395:       "loaded" bit to the class structure in addition to the
        !           396:       "initialized" bit. */
        !           397: 
        !           398:   /* Send load messages and activate call backs to classes. */
        !           399:   for (mod = modhdr, size = saveSize;
        !           400:        mod && size;
        !           401:        size -= mod->size, (char *) mod += mod->size)
        !           402:     {
        !           403:       for (i = 0; i < mod->symtab->cls_def_cnt; i++)
        !           404:        {
        !           405:          if (class_callback)
        !           406:            (*class_callback) (mod->symtab->defs[i], 0);
        !           407: 
        !           408:          send_load_message_to_class (mod->symtab->defs[i],
        !           409:                                      header_addr);
        !           410:        }
        !           411:     }
        !           412: 
        !           413:   /* Send load messages and activate call backs to categories. */
        !           414:   for (mod = modhdr, size = saveSize;
        !           415:        mod && size;
        !           416:        size -= mod->size, (char *) mod += mod->size)
        !           417:     {
        !           418:       for (i = mod->symtab->cls_def_cnt;
        !           419:            i < mod->symtab->cls_def_cnt + mod->symtab->cat_def_cnt;
        !           420:            i++)
        !           421:        {
        !           422:          if (class_callback)
        !           423:            (*class_callback) (objc_getClass(((Category)mod->symtab->defs[i])->class_name),
        !           424:                    (Category)mod->symtab->defs[i]);
        !           425: 
        !           426:          send_load_message_to_category((Category)mod->symtab->defs[i],
        !           427:                    header_addr);
        !           428:        }
        !           429:     }
        !           430: 
        !           431:   return 0;
        !           432: }
        !           433: 
        !           434: 
        !           435: #ifndef KERNEL
        !           436: static
        !           437: #endif
        !           438: void objc_unregisterModule (struct mach_header *header_addr,
        !           439:                        void (*unload_callback) (Class, Category))
        !           440: {
        !           441:   Module mod, modhdr;
        !           442:   int size, i, saveSize, strsize;
        !           443:   const char *strs;
        !           444: 
        !           445: #ifdef RUNTIME_DYLD
        !           446:   if (_dyld_present ())
        !           447:     {
        !           448:       fprintf (stderr, "objc_unregisterModule not supported in dynamic programs\n");
        !           449:       return;
        !           450:     }
        !           451: #endif
        !           452: 
        !           453: 
        !           454:   modhdr = (Module) getsectdatafromheader (header_addr,
        !           455:                    SEG_OBJC, "__module_info", &saveSize);
        !           456: 
        !           457:   /* Send unload messages and deactivate call backs to categories. */
        !           458:   for (mod = modhdr, size = saveSize;
        !           459:        mod && size;
        !           460:        size -= mod->size, (char *) mod += mod->size)
        !           461:     {
        !           462:       for (i = mod->symtab->cls_def_cnt;
        !           463:            i < mod->symtab->cls_def_cnt + mod->symtab->cat_def_cnt;
        !           464:            i++)
        !           465:        {
        !           466:          Category cat = mod->symtab->defs[i];
        !           467: 
        !           468:          if (unload_callback)
        !           469:            (*unload_callback) (objc_getClass (cat->class_name), cat);
        !           470: 
        !           471:          send_unload_message_to_category (cat);
        !           472:        }
        !           473:     }
        !           474: 
        !           475:   /* Send unload messages and deactivate call backs to classes. */
        !           476:   for (mod = modhdr, size = saveSize;
        !           477:        mod && size;
        !           478:        size -= mod->size, (char *) mod += mod->size)
        !           479:     {
        !           480:       for (i = 0; i < mod->symtab->cls_def_cnt; i++)
        !           481:        {
        !           482:          Class cls = mod->symtab->defs[i];
        !           483: 
        !           484:          if (unload_callback)
        !           485:            (*unload_callback) (cls, 0);
        !           486: 
        !           487:          send_unload_message_to_class (cls);
        !           488:        }
        !           489:     }
        !           490: 
        !           491:   /* Remove categories. */
        !           492:   for (mod = modhdr, size = saveSize;
        !           493:        mod && size;
        !           494:        size -= mod->size, (char *) mod += mod->size)
        !           495:     {
        !           496:       for (i = mod->symtab->cls_def_cnt;
        !           497:            i < mod->symtab->cls_def_cnt + mod->symtab->cat_def_cnt;
        !           498:            i++)
        !           499:        {
        !           500:          Category cat = mod->symtab->defs[i];
        !           501: 
        !           502:          _objc_remove_category (cat, mod->version);
        !           503:        }
        !           504:     }
        !           505: 
        !           506:   /* Remove classes. */
        !           507:   for (mod = modhdr, size = saveSize;
        !           508:        mod && size;
        !           509:        size -= mod->size, (char *) mod += mod->size)
        !           510:     {
        !           511:       for (i = 0; i < mod->symtab->cls_def_cnt; i++)
        !           512:        {
        !           513:          Class cls = mod->symtab->defs[i];
        !           514: 
        !           515:          _objc_removeClass (cls);
        !           516:        }
        !           517:     }
        !           518: 
        !           519:   /* Do we really want to do this?
        !           520:       What if I load Foo.o which contains a new selector "foo",
        !           521:       then I unload Foo.o and load Bar.o which also contains the
        !           522:       selector "foo".  The value of the selector may change!
        !           523:       I think that selector mappings need to be permanent. */
        !           524: 
        !           525:   /* Unload any selectors that might have been unique to this module. */
        !           526:   strs = (const char *) getsectdatafromheader (header_addr,
        !           527:                            SEG_OBJC, "__meth_var_names", &strsize);
        !           528: 
        !           529:   if (strs)
        !           530:     _sel_unloadSelectors (strs, strs + strsize);
        !           531: 
        !           532:   /* Unload old-style strings too. */
        !           533:   strs = (const char *) getsectdatafromheader (header_addr,
        !           534:                            SEG_OBJC, "__selector_strs", &strsize);
        !           535: 
        !           536:   if (strs)
        !           537:     _sel_unloadSelectors (strs, strs + strsize);
        !           538: 
        !           539:   _objc_removeHeader (header_addr);
        !           540: }
        !           541: 
        !           542: 
        !           543: #ifndef KERNEL
        !           544: 
        !           545: /* Lock for dynamic loading and unloading. */
        !           546: 
        !           547: static OBJC_DECLARE_LOCK (loadLock);
        !           548: 
        !           549: /* Loading isn't really thread safe.  If a load message recursively calls
        !           550:    objc_loadModules() both sets will be loaded correctly, but if the original
        !           551:    caller calls objc_unloadModules() it will probably unload the wrong modules.
        !           552:    If a load message calls objc_unloadModules(), then it will unload
        !           553:    the modules currently being loaded, which will probably cause a crash. */
        !           554: 
        !           555: /* Error handling is still somewhat crude.  If we encounter errors while
        !           556:    linking up classes or categories, we will not recover correctly.
        !           557:    Hopefully rld_load () will detect these problems for us. */
        !           558: 
        !           559: /* I removed atempts to lock the class hashtable, since this introduced
        !           560:    deadlock which was hard to remove.  The only way you can get into trouble
        !           561:    is if one thread loads a module while another thread tries to access the
        !           562:    loaded classes (using objc_lookUpClass) before the load is complete. */
        !           563: 
        !           564: long objc_loadModules (
        !           565:        char *modlist[], 
        !           566:        NXStream *errStream,
        !           567:        void (*class_callback) (Class, Category),
        !           568:        struct mach_header **hdr_addr,
        !           569:        char *debug_file)
        !           570: {
        !           571:   struct mach_header *header_addr;
        !           572:   int errflag = 0;
        !           573: 
        !           574: #ifdef RUNTIME_DYLD
        !           575:   if (_dyld_present ())
        !           576:     {
        !           577:       NSObjectFileImage objectFileImage;
        !           578:       NSModule module;
        !           579: 
        !           580:       char **modules;
        !           581: 
        !           582:       callbackFunction = class_callback;
        !           583:       for (modules = &modlist[0]; *modules != 0; modules++)
        !           584:         {
        !           585:           NSObjectFileImageReturnCode code
        !           586:               = NSCreateObjectFileImageFromFile (*modules, &objectFileImage);
        !           587: 
        !           588:           if (code != NSObjectFileImageSuccess)
        !           589:             {
        !           590:               if (errStream)
        !           591:                   NXPrintf (errStream,
        !           592:                             "objc_loadModules(%s) NSObjectFileImageReturnCode = %d\n", *modules, code);
        !           593: 
        !           594:               errflag = 1;
        !           595:               continue;
        !           596:             }
        !           597: 
        !           598:           module = NSLinkModule(objectFileImage, *modules, 0);
        !           599:        }
        !           600:       callbackFunction = 0;
        !           601:     }
        !           602:   else
        !           603: #endif
        !           604: 
        !           605:     {
        !           606: 
        !           607:         OBJC_LOCK (&loadLock);
        !           608: 
        !           609:         if (rld_load (errStream, &header_addr, modlist, debug_file))
        !           610:           {
        !           611:             errflag = objc_registerModule (header_addr, class_callback);
        !           612: 
        !           613:             /* Unload everything on errors. */
        !           614:             if (errflag)
        !           615:                 rld_unload (errStream);
        !           616:             else
        !           617:               {
        !           618:                   /* Return optional output parameter */
        !           619:                   if (hdr_addr)
        !           620:                       *hdr_addr = header_addr;
        !           621:               }
        !           622:           }
        !           623:         else
        !           624:             errflag = 1;
        !           625: 
        !           626:         OBJC_UNLOCK (&loadLock);
        !           627:     }
        !           628: 
        !           629:   return errflag;
        !           630: }
        !           631: 
        !           632: 
        !           633: /* Unloading isn't really thread safe.  If an unload message calls
        !           634:    objc_loadModules() or objc_unloadModules(), then the current call
        !           635:    to objc_unloadModules() will probably unload the wrong stuff. */
        !           636: 
        !           637: long objc_unloadModules (
        !           638:        NXStream *errStream,
        !           639:        void (*unload_callback) (Class, Category))
        !           640: {
        !           641:   struct mach_header *header_addr = rld_get_current_header ();
        !           642:   int errflag = 0;
        !           643: 
        !           644:   if (header_addr)
        !           645:     {
        !           646:       objc_unregisterModule (header_addr, unload_callback);
        !           647: 
        !           648:       OBJC_LOCK (&loadLock);
        !           649: 
        !           650:       if (rld_unload (errStream) == 0)
        !           651:         errflag = 1;
        !           652: 
        !           653:       OBJC_UNLOCK (&loadLock);
        !           654:     }
        !           655:   else
        !           656:     {
        !           657:       NXPrintf (errStream, "objc_unloadModules(): No modules to unload\n");
        !           658:       errflag = 1;
        !           659:     }
        !           660: 
        !           661:   return errflag;
        !           662: }
        !           663: 
        !           664: #endif /* not KERNEL */

unix.superglobalmegacorp.com

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