1 /* GNU Objective C Runtime initialization 2 Copyright (C) 1993, 1995, 1996, 1997, 2002, 2009 3 Free Software Foundation, Inc. 4 Contributed by Kresten Krab Thorup 5 +load support contributed by Ovidiu Predescu <ovidiu@net-community.com> 6 7 This file is part of GCC. 8 9 GCC is free software; you can redistribute it and/or modify it under the 10 terms of the GNU General Public License as published by the Free Software 11 Foundation; either version 3, or (at your option) any later version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 Under Section 7 of GPL version 3, you are granted additional 19 permissions described in the GCC Runtime Library Exception, version 20 3.1, as published by the Free Software Foundation. 21 22 You should have received a copy of the GNU General Public License and 23 a copy of the GCC Runtime Library Exception along with this program; 24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25 <http://www.gnu.org/licenses/>. */ 26 27 #include "objc/runtime.h" 28 29 /* The version number of this runtime. This must match the number 30 defined in gcc (objc-act.c). */ 31 #define OBJC_VERSION 8 32 #define PROTOCOL_VERSION 2 33 34 /* This list contains all modules currently loaded into the runtime. */ 35 static struct objc_list *__objc_module_list = 0; /* !T:MUTEX */ 36 37 /* This list contains all proto_list's not yet assigned class links. */ 38 static struct objc_list *unclaimed_proto_list = 0; /* !T:MUTEX */ 39 40 /* List of unresolved static instances. */ 41 static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */ 42 43 /* Global runtime "write" mutex. */ 44 objc_mutex_t __objc_runtime_mutex = 0; 45 46 /* Number of threads that are alive. */ 47 int __objc_runtime_threads_alive = 1; /* !T:MUTEX */ 48 49 /* Check compiler vs runtime version. */ 50 static void init_check_module_version (Module_t); 51 52 /* Assign isa links to protos. */ 53 static void __objc_init_protocols (struct objc_protocol_list *protos); 54 55 /* Add protocol to class. */ 56 static void __objc_class_add_protocols (Class, struct objc_protocol_list *); 57 58 /* This is a hook which is called by __objc_exec_class every time a 59 class or a category is loaded into the runtime. This may e.g. help 60 a dynamic loader determine the classes that have been loaded when 61 an object file is dynamically linked in. */ 62 void (*_objc_load_callback) (Class class, Category *category); /* !T:SAFE */ 63 64 /* Is all categories/classes resolved? */ 65 BOOL __objc_dangling_categories = NO; /* !T:UNUSED */ 66 67 extern SEL 68 __sel_register_typed_name (const char *name, const char *types, 69 struct objc_selector *orig, BOOL is_const); 70 71 /* Sends +load to all classes and categories in certain situations. */ 72 static void objc_send_load (void); 73 74 /* Inserts all the classes defined in module in a tree of classes that 75 resembles the class hierarchy. This tree is traversed in preorder 76 and the classes in its nodes receive the +load message if these 77 methods were not executed before. The algorithm ensures that when 78 the +load method of a class is executed all the superclasses have 79 been already received the +load message. */ 80 static void __objc_create_classes_tree (Module_t module); 81 82 static void __objc_call_callback (Module_t module); 83 84 /* A special version that works only before the classes are completely 85 installed in the runtime. */ 86 static BOOL class_is_subclass_of_class (Class class, Class superclass); 87 88 typedef struct objc_class_tree { 89 Class class; 90 struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */ 91 } objc_class_tree; 92 93 /* This is a linked list of objc_class_tree trees. The head of these 94 trees are root classes (their super class is Nil). These different 95 trees represent different class hierarchies. */ 96 static struct objc_list *__objc_class_tree_list = NULL; 97 98 /* Keeps the +load methods who have been already executed. This hash 99 should not be destroyed during the execution of the program. */ 100 static cache_ptr __objc_load_methods = NULL; 101 102 /* This function is used when building the class tree used to send 103 ordinately the +load message to all classes needing it. The tree 104 is really needed so that superclasses will get the message before 105 subclasses. 106 107 This tree will contain classes which are being loaded (or have just 108 being loaded), and whose super_class pointers have not yet been 109 resolved. This implies that their super_class pointers point to a 110 string with the name of the superclass; when the first message is 111 sent to the class (/an object of that class) the class links will 112 be resolved, which will replace the super_class pointers with 113 pointers to the actual superclasses. 114 115 Unfortunately, the tree might also contain classes which had been 116 loaded previously, and whose class links have already been 117 resolved. 118 119 This function returns the superclass of a class in both cases, and 120 can be used to build the determine the class relationships while 121 building the tree. 122 */ 123 static Class class_superclass_of_class (Class class) 124 { 125 char *super_class_name; 126 127 /* If the class links have been resolved, use the resolved 128 * links. */ 129 if (CLS_ISRESOLV (class)) 130 return class->super_class; 131 132 /* Else, 'class' has not yet been resolved. This means that its 133 * super_class pointer is really the name of the super class (rather 134 * than a pointer to the actual superclass). */ 135 super_class_name = (char *)class->super_class; 136 137 /* Return Nil for a root class. */ 138 if (super_class_name == NULL) 139 return Nil; 140 141 /* Lookup the superclass of non-root classes. */ 142 return objc_lookup_class (super_class_name); 143 } 144 145 146 /* Creates a tree of classes whose topmost class is directly inherited 147 from `upper' and the bottom class in this tree is 148 `bottom_class'. The classes in this tree are super classes of 149 `bottom_class'. `subclasses' member of each tree node point to the 150 next subclass tree node. */ 151 152 static objc_class_tree * 153 create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper) 154 { 155 Class superclass = bottom_class->super_class ? 156 objc_lookup_class ((char *) bottom_class->super_class) 157 : Nil; 158 159 objc_class_tree *tree, *prev; 160 161 DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:"); 162 DEBUG_PRINTF ("bottom_class = %s, upper = %s\n", 163 (bottom_class ? bottom_class->name : NULL), 164 (upper ? upper->name : NULL)); 165 166 tree = prev = objc_calloc (1, sizeof (objc_class_tree)); 167 prev->class = bottom_class; 168 169 while (superclass != upper) 170 { 171 tree = objc_calloc (1, sizeof (objc_class_tree)); 172 tree->class = superclass; 173 tree->subclasses = list_cons (prev, tree->subclasses); 174 superclass = class_superclass_of_class (superclass); 175 prev = tree; 176 } 177 178 return tree; 179 } 180 181 /* Insert the `class' into the proper place in the `tree' class 182 hierarchy. This function returns a new tree if the class has been 183 successfully inserted into the tree or NULL if the class is not 184 part of the classes hierarchy described by `tree'. This function is 185 private to objc_tree_insert_class (), you should not call it 186 directly. */ 187 188 static objc_class_tree * 189 __objc_tree_insert_class (objc_class_tree *tree, Class class) 190 { 191 DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n", 192 tree, class->name); 193 194 if (tree == NULL) 195 return create_tree_of_subclasses_inherited_from (class, NULL); 196 else if (class == tree->class) 197 { 198 /* `class' has been already inserted */ 199 DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name); 200 return tree; 201 } 202 else if (class_superclass_of_class (class) == tree->class) 203 { 204 /* If class is a direct subclass of tree->class then add class to the 205 list of subclasses. First check to see if it wasn't already 206 inserted. */ 207 struct objc_list *list = tree->subclasses; 208 objc_class_tree *node; 209 210 while (list) 211 { 212 /* Class has been already inserted; do nothing just return 213 the tree. */ 214 if (((objc_class_tree *) list->head)->class == class) 215 { 216 DEBUG_PRINTF ("2. class %s was previously inserted\n", 217 class->name); 218 return tree; 219 } 220 list = list->tail; 221 } 222 223 /* Create a new node class and insert it into the list of subclasses */ 224 node = objc_calloc (1, sizeof (objc_class_tree)); 225 node->class = class; 226 tree->subclasses = list_cons (node, tree->subclasses); 227 DEBUG_PRINTF ("3. class %s inserted\n", class->name); 228 return tree; 229 } 230 else 231 { 232 /* The class is not a direct subclass of tree->class. Search for 233 class's superclasses in the list of subclasses. */ 234 struct objc_list *subclasses = tree->subclasses; 235 236 /* Precondition: the class must be a subclass of tree->class; 237 otherwise return NULL to indicate our caller that it must 238 take the next tree. */ 239 if (! class_is_subclass_of_class (class, tree->class)) 240 return NULL; 241 242 for (; subclasses != NULL; subclasses = subclasses->tail) 243 { 244 Class aClass = ((objc_class_tree *) (subclasses->head))->class; 245 246 if (class_is_subclass_of_class (class, aClass)) 247 { 248 /* If we found one of class's superclasses we insert the 249 class into its subtree and return the original tree 250 since nothing has been changed. */ 251 subclasses->head 252 = __objc_tree_insert_class (subclasses->head, class); 253 DEBUG_PRINTF ("4. class %s inserted\n", class->name); 254 return tree; 255 } 256 } 257 258 /* We haven't found a subclass of `class' in the `subclasses' 259 list. Create a new tree of classes whose topmost class is a 260 direct subclass of tree->class. */ 261 { 262 objc_class_tree *new_tree 263 = create_tree_of_subclasses_inherited_from (class, tree->class); 264 tree->subclasses = list_cons (new_tree, tree->subclasses); 265 DEBUG_PRINTF ("5. class %s inserted\n", class->name); 266 return tree; 267 } 268 } 269 } 270 271 /* This function inserts `class' in the right tree hierarchy classes. */ 272 273 static void 274 objc_tree_insert_class (Class class) 275 { 276 struct objc_list *list_node; 277 objc_class_tree *tree; 278 279 list_node = __objc_class_tree_list; 280 while (list_node) 281 { 282 tree = __objc_tree_insert_class (list_node->head, class); 283 if (tree) 284 { 285 list_node->head = tree; 286 break; 287 } 288 else 289 list_node = list_node->tail; 290 } 291 292 /* If the list was finished but the class hasn't been inserted, 293 insert it here. */ 294 if (! list_node) 295 { 296 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list); 297 __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class); 298 } 299 } 300 301 /* Traverse tree in preorder. Used to send +load. */ 302 303 static void 304 objc_preorder_traverse (objc_class_tree *tree, 305 int level, 306 void (*function) (objc_class_tree *, int)) 307 { 308 struct objc_list *node; 309 310 (*function) (tree, level); 311 for (node = tree->subclasses; node; node = node->tail) 312 objc_preorder_traverse (node->head, level + 1, function); 313 } 314 315 /* Traverse tree in postorder. Used to destroy a tree. */ 316 317 static void 318 objc_postorder_traverse (objc_class_tree *tree, 319 int level, 320 void (*function) (objc_class_tree *, int)) 321 { 322 struct objc_list *node; 323 324 for (node = tree->subclasses; node; node = node->tail) 325 objc_postorder_traverse (node->head, level + 1, function); 326 (*function) (tree, level); 327 } 328 329 /* Used to print a tree class hierarchy. */ 330 331 #ifdef DEBUG 332 static void 333 __objc_tree_print (objc_class_tree *tree, int level) 334 { 335 int i; 336 337 for (i = 0; i < level; i++) 338 printf (" "); 339 printf ("%s\n", tree->class->name); 340 } 341 #endif 342 343 /* Walks on a linked list of methods in the reverse order and executes 344 all the methods corresponding to `op' selector. Walking in the 345 reverse order assures the +load of class is executed first and then 346 +load of categories because of the way in which categories are 347 added to the class methods. */ 348 349 static void 350 __objc_send_message_in_list (MethodList_t method_list, Class class, SEL op) 351 { 352 int i; 353 354 if (! method_list) 355 return; 356 357 /* First execute the `op' message in the following method lists */ 358 __objc_send_message_in_list (method_list->method_next, class, op); 359 360 /* Search the method list. */ 361 for (i = 0; i < method_list->method_count; i++) 362 { 363 Method_t mth = &method_list->method_list[i]; 364 365 if (mth->method_name && sel_eq (mth->method_name, op) 366 && ! objc_hash_is_key_in_hash (__objc_load_methods, mth->method_imp)) 367 { 368 /* Add this method into the +load hash table */ 369 objc_hash_add (&__objc_load_methods, 370 mth->method_imp, 371 mth->method_imp); 372 373 DEBUG_PRINTF ("sending +load in class: %s\n", class->name); 374 375 /* The method was found and wasn't previously executed. */ 376 (*mth->method_imp) ((id)class, mth->method_name); 377 378 break; 379 } 380 } 381 } 382 383 static void 384 __objc_send_load (objc_class_tree *tree, 385 int level __attribute__ ((__unused__))) 386 { 387 static SEL load_sel = 0; 388 Class class = tree->class; 389 MethodList_t method_list = class->class_pointer->methods; 390 391 if (! load_sel) 392 load_sel = sel_register_name ("load"); 393 394 __objc_send_message_in_list (method_list, class, load_sel); 395 } 396 397 static void 398 __objc_destroy_class_tree_node (objc_class_tree *tree, 399 int level __attribute__ ((__unused__))) 400 { 401 objc_free (tree); 402 } 403 404 /* This is used to check if the relationship between two classes 405 before the runtime completely installs the classes. */ 406 407 static BOOL 408 class_is_subclass_of_class (Class class, Class superclass) 409 { 410 for (; class != Nil;) 411 { 412 if (class == superclass) 413 return YES; 414 class = class_superclass_of_class (class); 415 } 416 417 return NO; 418 } 419 420 /* This list contains all the classes in the runtime system for whom 421 their superclasses are not yet known to the runtime. */ 422 static struct objc_list *unresolved_classes = 0; 423 424 /* Extern function used to reference the Object and NXConstantString 425 classes. */ 426 427 extern void __objc_force_linking (void); 428 429 void 430 __objc_force_linking (void) 431 { 432 extern void __objc_linking (void); 433 __objc_linking (); 434 } 435 436 /* Run through the statics list, removing modules as soon as all its 437 statics have been initialized. */ 438 439 static void 440 objc_init_statics (void) 441 { 442 struct objc_list **cell = &uninitialized_statics; 443 struct objc_static_instances **statics_in_module; 444 445 objc_mutex_lock (__objc_runtime_mutex); 446 447 while (*cell) 448 { 449 int module_initialized = 1; 450 451 for (statics_in_module = (*cell)->head; 452 *statics_in_module; statics_in_module++) 453 { 454 struct objc_static_instances *statics = *statics_in_module; 455 Class class = objc_lookup_class (statics->class_name); 456 457 if (! class) 458 module_initialized = 0; 459 /* Actually, the static's class_pointer will be NULL when we 460 haven't been here before. However, the comparison is to be 461 reminded of taking into account class posing and to think about 462 possible semantics... */ 463 else if (class != statics->instances[0]->class_pointer) 464 { 465 id *inst; 466 467 for (inst = &statics->instances[0]; *inst; inst++) 468 { 469 (*inst)->class_pointer = class; 470 471 /* ??? Make sure the object will not be freed. With 472 refcounting, invoke `-retain'. Without refcounting, do 473 nothing and hope that `-free' will never be invoked. */ 474 475 /* ??? Send the object an `-initStatic' or something to 476 that effect now or later on? What are the semantics of 477 statically allocated instances, besides the trivial 478 NXConstantString, anyway? */ 479 } 480 } 481 } 482 if (module_initialized) 483 { 484 /* Remove this module from the uninitialized list. */ 485 struct objc_list *this = *cell; 486 *cell = this->tail; 487 objc_free (this); 488 } 489 else 490 cell = &(*cell)->tail; 491 } 492 493 objc_mutex_unlock (__objc_runtime_mutex); 494 } /* objc_init_statics */ 495 496 /* This function is called by constructor functions generated for each 497 module compiled. (_GLOBAL_$I$...) The purpose of this function is 498 to gather the module pointers so that they may be processed by the 499 initialization routines as soon as possible. */ 500 501 void 502 __objc_exec_class (Module_t module) 503 { 504 /* Have we processed any constructors previously? This flag is used to 505 indicate that some global data structures need to be built. */ 506 static BOOL previous_constructors = 0; 507 508 static struct objc_list *unclaimed_categories = 0; 509 510 /* The symbol table (defined in objc-api.h) generated by gcc */ 511 Symtab_t symtab = module->symtab; 512 513 /* The statics in this module */ 514 struct objc_static_instances **statics 515 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt]; 516 517 /* Entry used to traverse hash lists */ 518 struct objc_list **cell; 519 520 /* The table of selector references for this module */ 521 SEL selectors = symtab->refs; 522 523 /* dummy counter */ 524 int i; 525 526 DEBUG_PRINTF ("received module: %s\n", module->name); 527 528 /* check gcc version */ 529 init_check_module_version (module); 530 531 /* On the first call of this routine, initialize some data structures. */ 532 if (! previous_constructors) 533 { 534 /* Initialize thread-safe system */ 535 __objc_init_thread_system (); 536 __objc_runtime_threads_alive = 1; 537 __objc_runtime_mutex = objc_mutex_allocate (); 538 539 __objc_init_selector_tables (); 540 __objc_init_class_tables (); 541 __objc_init_dispatch_tables (); 542 __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list); 543 __objc_load_methods = objc_hash_new (128, 544 (hash_func_type)objc_hash_ptr, 545 objc_compare_ptrs); 546 previous_constructors = 1; 547 } 548 549 /* Save the module pointer for later processing. (not currently used) */ 550 objc_mutex_lock (__objc_runtime_mutex); 551 __objc_module_list = list_cons (module, __objc_module_list); 552 553 /* Replace referenced selectors from names to SEL's. */ 554 if (selectors) 555 { 556 for (i = 0; selectors[i].sel_id; ++i) 557 { 558 const char *name, *type; 559 name = (char *) selectors[i].sel_id; 560 type = (char *) selectors[i].sel_types; 561 /* Constructors are constant static data so we can safely store 562 pointers to them in the runtime structures. is_const == YES */ 563 __sel_register_typed_name (name, type, 564 (struct objc_selector *) &(selectors[i]), 565 YES); 566 } 567 } 568 569 /* Parse the classes in the load module and gather selector information. */ 570 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name); 571 for (i = 0; i < symtab->cls_def_cnt; ++i) 572 { 573 Class class = (Class) symtab->defs[i]; 574 const char *superclass = (char *) class->super_class; 575 576 /* Make sure we have what we think. */ 577 assert (CLS_ISCLASS (class)); 578 assert (CLS_ISMETA (class->class_pointer)); 579 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name); 580 581 /* Initialize the subclass list to be NULL. 582 In some cases it isn't and this crashes the program. */ 583 class->subclass_list = NULL; 584 585 /* Store the class in the class table and assign class numbers. */ 586 __objc_add_class_to_hash (class); 587 588 /* Register all of the selectors in the class and meta class. */ 589 __objc_register_selectors_from_class (class); 590 __objc_register_selectors_from_class ((Class) class->class_pointer); 591 592 /* Install the fake dispatch tables */ 593 __objc_install_premature_dtable (class); 594 __objc_install_premature_dtable (class->class_pointer); 595 596 /* Register the instance methods as class methods, this is 597 only done for root classes. */ 598 __objc_register_instance_methods_to_class (class); 599 600 if (class->protocols) 601 __objc_init_protocols (class->protocols); 602 603 /* Check to see if the superclass is known in this point. If it's not 604 add the class to the unresolved_classes list. */ 605 if (superclass && ! objc_lookup_class (superclass)) 606 unresolved_classes = list_cons (class, unresolved_classes); 607 } 608 609 /* Process category information from the module. */ 610 for (i = 0; i < symtab->cat_def_cnt; ++i) 611 { 612 Category_t category = symtab->defs[i + symtab->cls_def_cnt]; 613 Class class = objc_lookup_class (category->class_name); 614 615 /* If the class for the category exists then append its methods. */ 616 if (class) 617 { 618 619 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n", 620 module->name, 621 class->name); 622 623 /* Do instance methods. */ 624 if (category->instance_methods) 625 class_add_method_list (class, category->instance_methods); 626 627 /* Do class methods. */ 628 if (category->class_methods) 629 class_add_method_list ((Class) class->class_pointer, 630 category->class_methods); 631 632 if (category->protocols) 633 { 634 __objc_init_protocols (category->protocols); 635 __objc_class_add_protocols (class, category->protocols); 636 } 637 638 /* Register the instance methods as class methods, this is 639 only done for root classes. */ 640 __objc_register_instance_methods_to_class (class); 641 } 642 else 643 { 644 /* The object to which the category methods belong can't be found. 645 Save the information. */ 646 unclaimed_categories = list_cons (category, unclaimed_categories); 647 } 648 } 649 650 if (statics) 651 uninitialized_statics = list_cons (statics, uninitialized_statics); 652 if (uninitialized_statics) 653 objc_init_statics (); 654 655 /* Scan the unclaimed category hash. Attempt to attach any unclaimed 656 categories to objects. */ 657 for (cell = &unclaimed_categories; *cell; ) 658 { 659 Category_t category = (*cell)->head; 660 Class class = objc_lookup_class (category->class_name); 661 662 if (class) 663 { 664 DEBUG_PRINTF ("attaching stored categories to object: %s\n", 665 class->name); 666 667 list_remove_head (cell); 668 669 if (category->instance_methods) 670 class_add_method_list (class, category->instance_methods); 671 672 if (category->class_methods) 673 class_add_method_list ((Class) class->class_pointer, 674 category->class_methods); 675 676 if (category->protocols) 677 { 678 __objc_init_protocols (category->protocols); 679 __objc_class_add_protocols (class, category->protocols); 680 } 681 682 /* Register the instance methods as class methods, this is 683 only done for root classes. */ 684 __objc_register_instance_methods_to_class (class); 685 } 686 else 687 cell = &(*cell)->tail; 688 } 689 690 if (unclaimed_proto_list && objc_lookup_class ("Protocol")) 691 { 692 list_mapcar (unclaimed_proto_list, 693 (void (*) (void *))__objc_init_protocols); 694 list_free (unclaimed_proto_list); 695 unclaimed_proto_list = 0; 696 } 697 698 objc_send_load (); 699 700 objc_mutex_unlock (__objc_runtime_mutex); 701 } 702 703 static void 704 objc_send_load (void) 705 { 706 if (! __objc_module_list) 707 return; 708 709 /* Try to find out if all the classes loaded so far also have their 710 superclasses known to the runtime. We suppose that the objects 711 that are allocated in the +load method are in general of a class 712 declared in the same module. */ 713 if (unresolved_classes) 714 { 715 Class class = unresolved_classes->head; 716 717 while (objc_lookup_class ((char *) class->super_class)) 718 { 719 list_remove_head (&unresolved_classes); 720 if (unresolved_classes) 721 class = unresolved_classes->head; 722 else 723 break; 724 } 725 726 /* If we still have classes for whom we don't have yet their 727 super classes known to the runtime we don't send the +load 728 messages. */ 729 if (unresolved_classes) 730 return; 731 } 732 733 /* Special check to allow creating and sending messages to constant 734 strings in +load methods. If these classes are not yet known, 735 even if all the other classes are known, delay sending of +load. */ 736 if (! objc_lookup_class ("NXConstantString") || 737 ! objc_lookup_class ("Object")) 738 return; 739 740 /* Iterate over all modules in the __objc_module_list and call on 741 them the __objc_create_classes_tree function. This function 742 creates a tree of classes that resembles the class hierarchy. */ 743 list_mapcar (__objc_module_list, 744 (void (*) (void *)) __objc_create_classes_tree); 745 746 while (__objc_class_tree_list) 747 { 748 #ifdef DEBUG 749 objc_preorder_traverse (__objc_class_tree_list->head, 750 0, __objc_tree_print); 751 #endif 752 objc_preorder_traverse (__objc_class_tree_list->head, 753 0, __objc_send_load); 754 objc_postorder_traverse (__objc_class_tree_list->head, 755 0, __objc_destroy_class_tree_node); 756 list_remove_head (&__objc_class_tree_list); 757 } 758 759 list_mapcar (__objc_module_list, (void (*) (void *)) __objc_call_callback); 760 list_free (__objc_module_list); 761 __objc_module_list = NULL; 762 } 763 764 static void 765 __objc_create_classes_tree (Module_t module) 766 { 767 /* The runtime mutex is locked in this point */ 768 769 Symtab_t symtab = module->symtab; 770 int i; 771 772 /* Iterate thru classes defined in this module and insert them in 773 the classes tree hierarchy. */ 774 for (i = 0; i < symtab->cls_def_cnt; i++) 775 { 776 Class class = (Class) symtab->defs[i]; 777 778 objc_tree_insert_class (class); 779 } 780 } 781 782 static void 783 __objc_call_callback (Module_t module) 784 { 785 /* The runtime mutex is locked in this point. */ 786 787 Symtab_t symtab = module->symtab; 788 int i; 789 790 /* Iterate thru classes defined in this module and call the callback 791 for each one. */ 792 for (i = 0; i < symtab->cls_def_cnt; i++) 793 { 794 Class class = (Class) symtab->defs[i]; 795 796 /* Call the _objc_load_callback for this class. */ 797 if (_objc_load_callback) 798 _objc_load_callback (class, 0); 799 } 800 801 /* Call the _objc_load_callback for categories. Don't register the 802 instance methods as class methods for categories to root classes 803 since they were already added in the class. */ 804 for (i = 0; i < symtab->cat_def_cnt; i++) 805 { 806 Category_t category = symtab->defs[i + symtab->cls_def_cnt]; 807 Class class = objc_lookup_class (category->class_name); 808 809 if (_objc_load_callback) 810 _objc_load_callback (class, category); 811 } 812 } 813 814 /* Sanity check the version of gcc used to compile `module'. */ 815 816 static void 817 init_check_module_version (Module_t module) 818 { 819 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module))) 820 { 821 int code; 822 823 if (module->version > OBJC_VERSION) 824 code = OBJC_ERR_OBJC_VERSION; 825 else if (module->version < OBJC_VERSION) 826 code = OBJC_ERR_GCC_VERSION; 827 else 828 code = OBJC_ERR_MODULE_SIZE; 829 830 objc_error (nil, code, "Module %s version %d doesn't match runtime %d\n", 831 module->name, (int)module->version, OBJC_VERSION); 832 } 833 } 834 835 static void 836 __objc_init_protocols (struct objc_protocol_list *protos) 837 { 838 size_t i; 839 static Class proto_class = 0; 840 841 if (! protos) 842 return; 843 844 objc_mutex_lock (__objc_runtime_mutex); 845 846 if (! proto_class) 847 proto_class = objc_lookup_class ("Protocol"); 848 849 if (! proto_class) 850 { 851 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list); 852 objc_mutex_unlock (__objc_runtime_mutex); 853 return; 854 } 855 856 #if 0 857 assert (protos->next == 0); /* only single ones allowed */ 858 #endif 859 860 for (i = 0; i < protos->count; i++) 861 { 862 struct objc_protocol *aProto = protos->list[i]; 863 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION) 864 { 865 /* assign class pointer */ 866 aProto->class_pointer = proto_class; 867 868 /* init super protocols */ 869 __objc_init_protocols (aProto->protocol_list); 870 } 871 else if (protos->list[i]->class_pointer != proto_class) 872 { 873 objc_error (nil, OBJC_ERR_PROTOCOL_VERSION, 874 "Version %d doesn't match runtime protocol version %d\n", 875 (int) ((char *) protos->list[i]->class_pointer 876 - (char *) 0), 877 PROTOCOL_VERSION); 878 } 879 } 880 881 objc_mutex_unlock (__objc_runtime_mutex); 882 } 883 884 static void 885 __objc_class_add_protocols (Class class, struct objc_protocol_list *protos) 886 { 887 /* Well... */ 888 if (! protos) 889 return; 890 891 /* Add it... */ 892 protos->next = class->protocols; 893 class->protocols = protos; 894 } 895