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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.0 (the 'License').  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License."
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*
                     25:  *     objc-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.