--- gcc/objc/init.c 2018/04/24 18:10:13 1.1 +++ gcc/objc/init.c 2018/04/24 18:26:38 1.1.1.3 @@ -1,22 +1,21 @@ /* GNU Objective C Runtime initialization - Copyright (C) 1993 Free Software Foundation, Inc. - -Author: Kresten Krab Thorup + Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by Kresten Krab Thorup This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 2, or (at your option) any later version. +terms of the GNU General Public License as published by the Free Software +Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. You should have received a copy of the GNU General Public License along with - GNU CC; see the file COPYING. If not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +GNU CC; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, if you link this library with files compiled with GCC to produce an executable, this does not cause the resulting executable @@ -28,7 +27,7 @@ You should have received a copy of the G /* The version number of this runtime. This must match the number defined in gcc (objc-act.c) */ -#define OBJC_VERSION 5 +#define OBJC_VERSION 7 #define PROTOCOL_VERSION 2 /* This list contains all modules currently loaded into the runtime */ @@ -37,18 +36,86 @@ static struct objc_list* __objc_module_l /* This list contains all proto_list's not yet assigned class links */ static struct objc_list* unclaimed_proto_list = 0; +/* List of unresolved static instances. */ +static struct objc_list *uninitialized_statics; + /* Check compiler vs runtime version */ -static void init_check_module_version(Module_t); +static void init_check_module_version (Module_t); /* Assign isa links to protos */ static void __objc_init_protocols (struct objc_protocol_list* protos); /* Add protocol to class */ -static void __objc_class_add_protocols (Class*, struct objc_protocol_list*); +static void __objc_class_add_protocols (Class, struct objc_protocol_list*); + +/* This is a hook which is called by __objc_exec_class every time a class + or a category is loaded into the runtime. This may e.g. help a + dynamic loader determine the classes that have been loaded when + an object file is dynamically linked in */ +void (*_objc_load_callback)(Class class, Category* category) = 0; /* Is all categories/classes resolved? */ BOOL __objc_dangling_categories = NO; +extern SEL +__sel_register_typed_name (const char *name, const char *types, + struct objc_selector *orig); + +/* Run through the statics list, removing modules as soon as all its statics + have been initialized. */ +static void +objc_init_statics () +{ + struct objc_list **cell = &uninitialized_statics; + struct objc_static_instances **statics_in_module; + + while (*cell) + { + int module_initialized = 1; + + for (statics_in_module = (*cell)->head; + *statics_in_module; statics_in_module++) + { + struct objc_static_instances *statics = *statics_in_module; + Class class = objc_lookup_class (statics->class_name); + + if (!class) + module_initialized = 0; + /* Actually, the static's class_pointer will be NULL when we + haven't been here before. However, the comparison is to be + reminded of taking into account class posing and to think about + possible semantics... */ + else if (class != statics->instances[0]->class_pointer) + { + id *inst; + + for (inst = &statics->instances[0]; *inst; inst++) + { + (*inst)->class_pointer = class; + + /* ??? Make sure the object will not be freed. With + refcounting, invoke `-retain'. Without refcounting, do + nothing and hope that `-free' will never be invoked. */ + + /* ??? Send the object an `-initStatic' or something to + that effect now or later on? What are the semantics of + statically allocated instances, besides the trivial + NXConstantString, anyway? */ + } + } + } + if (module_initialized) + { + /* Remove this module from the uninitialized list. */ + struct objc_list *this = *cell; + *cell = this->tail; + free (this); + } + else + cell = &(*cell)->tail; + } +} /* objc_init_statics */ + /* This function is called by constructor functions generated for each module compiled. (_GLOBAL_$I$...) The purpose of this function is to gather the module pointers so that they may be processed by the @@ -57,25 +124,26 @@ BOOL __objc_dangling_categories = NO; void __objc_exec_class (Module_t module) { - /* Has we processed any constructors previously? This flag used to - indicate that some global data structures need to be built. */ + /* Have we processed any constructors previously? This flag is used to + indicate that some global data structures need to be built. */ static BOOL previous_constructors = 0; static struct objc_list* unclaimed_categories = 0; - /* The symbol table (defined in objc.h) generated by gcc */ + /* The symbol table (defined in objc-api.h) generated by gcc */ Symtab_t symtab = module->symtab; /* Entry used to traverse hash lists */ struct objc_list** cell; /* The table of selector references for this module */ - SEL *selectors = symtab->refs; + SEL selectors = symtab->refs; /* dummy counter */ int i; DEBUG_PRINTF ("received module: %s\n", module->name); + /* check gcc version */ init_check_module_version(module); @@ -91,11 +159,24 @@ __objc_exec_class (Module_t module) /* Save the module pointer for later processing. (not currently used) */ __objc_module_list = list_cons(module, __objc_module_list); + /* Replace referenced selectors from names to SEL's. */ + if (selectors) + { + for (i = 0; selectors[i].sel_id; ++i) + { + const char *name, *type; + name = (char*)selectors[i].sel_id; + type = (char*)selectors[i].sel_types; + __sel_register_typed_name (name, type, + (struct objc_selector*)&(selectors[i])); + } + } + /* Parse the classes in the load module and gather selector information. */ DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name); for (i = 0; i < symtab->cls_def_cnt; ++i) { - Class* class = (Class*) symtab->defs[i]; + Class class = (Class) symtab->defs[i]; /* Make sure we have what we think. */ assert (CLS_ISCLASS(class)); @@ -107,7 +188,7 @@ __objc_exec_class (Module_t module) /* Register all of the selectors in the class and meta class. */ __objc_register_selectors_from_class (class); - __objc_register_selectors_from_class ((Class*) class->class_pointer); + __objc_register_selectors_from_class ((Class) class->class_pointer); /* Install the fake dispatch tables */ __objc_install_premature_dtable(class); @@ -115,20 +196,16 @@ __objc_exec_class (Module_t module) if (class->protocols) __objc_init_protocols (class->protocols); - } - /* Replace referenced selectors from names to SEL's. */ - if (selectors) - { - for (i = 0; selectors[i]; ++i) - selectors[i] = sel_register_name ((const char *) selectors[i]); - } + if (_objc_load_callback) + _objc_load_callback(class, 0); + } /* Process category information from the module. */ for (i = 0; i < symtab->cat_def_cnt; ++i) { Category_t category = symtab->defs[i + symtab->cls_def_cnt]; - Class* class = objc_lookup_class (category->class_name); + Class class = objc_lookup_class (category->class_name); /* If the class for the category exists then append its methods. */ if (class) @@ -144,7 +221,7 @@ __objc_exec_class (Module_t module) /* Do class methods. */ if (category->class_methods) - class_add_method_list ((Class*) class->class_pointer, + class_add_method_list ((Class) class->class_pointer, category->class_methods); if (category->protocols) @@ -153,6 +230,8 @@ __objc_exec_class (Module_t module) __objc_class_add_protocols (class, category->protocols); } + if (_objc_load_callback) + _objc_load_callback(class, category); } else { @@ -162,14 +241,19 @@ __objc_exec_class (Module_t module) } } + if (module->statics) + uninitialized_statics = list_cons (module->statics, uninitialized_statics); + if (uninitialized_statics) + objc_init_statics (); + /* Scan the unclaimed category hash. Attempt to attach any unclaimed categories to objects. */ for (cell = &unclaimed_categories; *cell; - *cell && ((cell = &(*cell)->tail))) + ({ if (*cell) cell = &(*cell)->tail; })) { Category_t category = (*cell)->head; - Class* class = objc_lookup_class (category->class_name); + Class class = objc_lookup_class (category->class_name); if (class) { @@ -182,7 +266,7 @@ __objc_exec_class (Module_t module) class_add_method_list (class, category->instance_methods); if (category->class_methods) - class_add_method_list ((Class*) class->class_pointer, + class_add_method_list ((Class) class->class_pointer, category->class_methods); if (category->protocols) @@ -191,6 +275,8 @@ __objc_exec_class (Module_t module) __objc_class_add_protocols (class, category->protocols); } + if (_objc_load_callback) + _objc_load_callback(class, category); } } @@ -209,7 +295,7 @@ static void init_check_module_version(Mo if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module))) { fprintf (stderr, "Module %s version %d doesn't match runtime %d\n", - module->name, module->version, OBJC_VERSION); + module->name, (int)module->version, OBJC_VERSION); if(module->version > OBJC_VERSION) fprintf (stderr, "Runtime (libobjc.a) is out of date\n"); else if (module->version < OBJC_VERSION) @@ -224,7 +310,7 @@ static void __objc_init_protocols (struct objc_protocol_list* protos) { int i; - static Class* proto_class = 0; + static Class proto_class = 0; if (! protos) return; @@ -238,7 +324,9 @@ __objc_init_protocols (struct objc_proto return; } +#if 0 assert (protos->next == 0); /* only single ones allowed */ +#endif for(i = 0; i < protos->count; i++) { @@ -255,14 +343,14 @@ __objc_init_protocols (struct objc_proto { fprintf (stderr, "Version %d doesn't match runtime protocol version %d\n", - ((size_t)protos->list[i]->class_pointer), + (int)((char*)protos->list[i]->class_pointer-(char*)0), PROTOCOL_VERSION); abort (); } } } -static void __objc_class_add_protocols (Class* class, +static void __objc_class_add_protocols (Class class, struct objc_protocol_list* protos) { /* Well... */