enumdyld_image_states { dyld_image_state_mapped =10, // No batch notification for this dyld_image_state_dependents_mapped =20, // Only batch notification for this dyld_image_state_rebased =30, dyld_image_state_bound =40, dyld_image_state_dependents_initialized =45, // Only single notification for this dyld_image_state_initialized =50, dyld_image_state_terminated =60// Only single notification for this };
// // Note: onlyfor use by objc runtime // Register handlers to be calledwhen objc images are mapped, unmapped, and initialized. // Dyld will call back the "mapped" functionwith an arrayof images that contain an objc-image-info section. // Those images that are dylibs will have the ref-counts automatically bumped, so objc will no longer need to // call dlopen() on them to keep them from being unloaded. During the callto _dyld_objc_notify_register(), // dyld will call the "mapped" functionwith already loaded objc images. During any later dlopen() call, // dyld will alsocall the "mapped" function. Dyld will call the "init" functionwhen dyld would be called // initializers in that image. This iswhen objc calls any +load methods in that image. // 通过这个方法可以向dyld注册用于处理镜像完成映射,取消映射和初始化之后的处理方法。
void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses) { //......
// =================================查找classes================================= // Discover classes. Fix up unresolved future classes. Mark bundle classes. for (EACH_HEADER) { //从Mach-O的 __DATA区 __objc_classlist 获取所有类,并加入gdb_objc_realized_classes list中 classref_t *classlist = _getObjc2ClassList(hi, &count); //....... for (i = 0; i < count; i++) { Class cls = (Class)classlist[i]; Class newCls = readClass(cls, headerIsBundle, headerIsPreoptimized);
if (newCls != cls && newCls) { // 类被移动了但是没有被删除的情况 // Class was moved but not deleted. Currently this occurs // only when the new class resolved a future class. // Non-lazily realize the class below. resolvedFutureClasses = (Class *)realloc(resolvedFutureClasses, (resolvedFutureClassCount+1) * sizeof(Class)); resolvedFutureClasses[resolvedFutureClassCount++] = newCls; } } }
ts.log("IMAGE TIMES: discover classes");
// 修复重新映射的类 // Fix up remapped classes // Class list and nonlazy class list remain unremapped. // Class refs and super refs are remapped for message dispatching. if (!noClassesRemapped()) { for (EACH_HEADER) { Class *classrefs = _getObjc2ClassRefs(hi, &count); for (i = 0; i < count; i++) { remapClassRef(&classrefs[i]); } // fixme why doesn't test future1 catch the absence of this? classrefs = _getObjc2SuperRefs(hi, &count); for (i = 0; i < count; i++) { remapClassRef(&classrefs[i]); } } }
// 重新映射类 ts.log("IMAGE TIMES: remap classes");
// Fix up @selector references static size_t UnfixedSelectors; { mutex_locker_t lock(selLock); for (EACH_HEADER) { if (hi->isPreoptimized()) continue; bool isBundle = hi->isBundle(); SEL *sels = _getObjc2SelectorRefs(hi, &count); UnfixedSelectors += count; for (i = 0; i < count; i++) { const char *name = sel_cname(sels[i]); // 3. 注册Sel,并存储到全局变量namedSelectors的list中 sels[i] = sel_registerNameNoLock(name, isBundle); } } }
ts.log("IMAGE TIMES: fix up selector references");
//.....
// Discover protocols. Fix up protocol refs. for (EACH_HEADER) { extern objc_class OBJC_CLASS_$_Protocol; Class cls = (Class)&OBJC_CLASS_$_Protocol; assert(cls); NXMapTable *protocol_map = protocols(); bool isPreoptimized = hi->isPreoptimized(); bool isBundle = hi->isBundle(); //找到所有Protocol并处理引用 protocol_t **protolist = _getObjc2ProtocolList(hi, &count); for (i = 0; i < count; i++) { readProtocol(protolist[i], cls, protocol_map, isPreoptimized, isBundle); } }
ts.log("IMAGE TIMES: discover protocols");
// Fix up @protocol references // Preoptimized images may have the right // answer already but we don't know for sure. for (EACH_HEADER) { protocol_t **protolist = _getObjc2ProtocolRefs(hi, &count); for (i = 0; i < count; i++) { remapProtocolRef(&protolist[i]); } }
ts.log("IMAGE TIMES: fix up @protocol references");
// Realize non-lazy classes (for +load methods and static instances) for (EACH_HEADER) { classref_t *classlist = _getObjc2NonlazyClassList(hi, &count); for (i = 0; i < count; i++) { Class cls = remapClass(classlist[i]); if (!cls) continue; addClassTableEntry(cls); realizeClass(cls); } }
ts.log("IMAGE TIMES: realize non-lazy classes");
// Realize newly-resolved future classes, in case CF manipulates them if (resolvedFutureClasses) { for (i = 0; i < resolvedFutureClassCount; i++) { realizeClass(resolvedFutureClasses[i]); resolvedFutureClasses[i]->setInstancesRequireRawIsa(false/*inherited*/); } free(resolvedFutureClasses); }
for (i = 0; i < count; i++) { category_t *cat = catlist[i]; //获取到所属的类 Class cls = remapClass(cat->cls);
if (!cls) { // Category's target class is missing (probably weak-linked). // Disavow any knowledge of this category. catlist[i] = nil; if (PrintConnecting) { _objc_inform("CLASS: IGNORING category \?\?\?(%s) %p with " "missing weak-linked target class", cat->name, cat); } continue; }
// Process this category. // First, register the category with its target class. // Then, rebuild the class's method lists (etc) if // the class is realized. bool classExists = NO; //如果有实例方法,协议或者实例属性 if (cat->instanceMethods || cat->protocols || cat->instanceProperties) { addUnattachedCategoryForClass(cat, cls, hi); if (cls->isRealized()) { //将分类添到属性,方法,协议添加到对应的类中 remethodizeClass(cls); classExists = YES; } if (PrintConnecting) { _objc_inform("CLASS: found category -%s(%s) %s", cls->nameForLogging(), cat->name, classExists ? "on existing class" : ""); } } //如果有类方法,协议或者类属性 if (cat->classMethods || cat->protocols || (hasClassProperties && cat->_classProperties)) { addUnattachedCategoryForClass(cat, cls->ISA(), hi); if (cls->ISA()->isRealized()) { remethodizeClass(cls->ISA()); } if (PrintConnecting) { _objc_inform("CLASS: found category +%s(%s)", cls->nameForLogging(), cat->name); } } } }
ts.log("IMAGE TIMES: discover categories");
// Category discovery MUST BE LAST to avoid potential races // when other threads call the new category code before // this thread finishes its fixups.
// +load handled by prepare_load_methods()
if (DebugNonFragileIvars) { realizeAllClasses(); } //...... }
isMeta = ro->flags & RO_META; //判断是否是元类 rw->version = isMeta ? 7 : 0; // old runtime went up to 6 //版本信息,旧版本的版本信息为6
//..... // Realize superclass and metaclass, if they aren't already. // This needs to be done after RW_REALIZED is set above, for root classes. // This needs to be done after class index is chosen, for root metaclasses. // 【✨】为supercls,metacls 分配空间 supercls = realizeClass(remapClass(cls->superclass)); metacls = realizeClass(remapClass(cls->ISA()));
//......
// 【✨】 Update superclass and metaclass in case of remapping cls->superclass = supercls; //将supercls赋给 cls->superclass //将上面分配的metacls赋给cls cls->initClassIsa(metacls);
// 调整实例变量的偏移和布局,这个将会重新分配class_ro_t // Reconcile instance variable offsets / layout. // This may reallocate class_ro_t, updating our ro variable. if (supercls && !isMeta) reconcileInstanceVariables(cls, supercls, ro);
//设置对象尺寸 // Set fastInstanceSize if it wasn't set already. cls->setInstanceSize(ro->instanceSize);
//【✨】从ro中拷贝部分标志位到rw 字段 // Copy some flags from ro to rw if (ro->flags & RO_HAS_CXX_STRUCTORS) { cls->setHasCxxDtor(); if (! (ro->flags & RO_HAS_CXX_DTOR_ONLY)) { cls->setHasCxxCtor(); } }
// 【✨】 Connect this class to its superclass's subclass lists // 将当前class与父类相关连 if (supercls) { //将当前类作为supercls的子类添加到父类的子类列表 addSubclass(supercls, cls); } else { //将当前类作为根类 addRootClass(cls); } //【✨】实例化类结构 // Attach categories // 使得类有条理 methodizeClass(cls);
// Root classes get bonus method implementations if they don't have // them already. These apply before category replacements. if (cls->isRootMetaclass()) { // root metaclass addMethod(cls, SEL_initialize, (IMP)&objc_noop_imp, "", NO); }
/*********************************************************************** * call_load_methods * Call all pending class and category +load methods. * Class +load methods are called superclass-first. * Category +load methods are not called until after the parent class's +load. * * This method must be RE-ENTRANT, because a +load could trigger * more image mapping. In addition, the superclass-first ordering * must be preserved in the face of re-entrant calls. Therefore, * only the OUTERMOST call of this function will do anything, and * that call will handle all loadable classes, even those generated * while it was running. * * The sequence below preserves +load ordering in the face of * image loading during a +load, and make sure that no * +load method is forgotten because it was added during * a +load call. * Sequence: * 1. Repeatedly call class +loads until there aren't any more * 2. Call category +loads ONCE. * 3. Run more +loads if: * (a) there are more classes to load, OR * (b) there are some potential category +loads that have * still never been attempted. * Category +loads are only run once to ensure "parent class first" * ordering, even if a category +load triggers a new loadable class * and a new loadable category attached to that class. * * Locking: loadMethodLock must be held by the caller * All other locks must not be held. **********************************************************************/ void call_load_methods(void) { static bool loading = NO; bool more_categories; loadMethodLock.assertLocked(); // Re-entrant calls do nothing; the outermost call will finish the job. if (loading) return; loading = YES; void *pool = objc_autoreleasePoolPush(); do { // 1. Repeatedly call class +loads until there aren't any more while (loadable_classes_used > 0) { //调用类的load方法 call_class_loads(); } // 2. Call category +loads ONCE //调用分类的load方法 more_categories = call_category_loads(); // 3. Run more +loads if there are classes OR more untried categories } while (loadable_classes_used > 0 || more_categories); objc_autoreleasePoolPop(pool); loading = NO; }
staticvoidcall_class_loads(void) { // Detach current loadable list. structloadable_class *classes = loadable_classes;/*这是preppare阶段构造的*/ int used = loadable_classes_used; loadable_classes = nil; loadable_classes_allocated = 0; loadable_classes_used = 0;
// Call all +loads for the detached list. for (i = 0; i < used; i++) { Class cls = classes[i].cls;
load_method_t load_method = (load_method_t)classes[i].method; if (!cls) continue;
if (PrintLoading) { _objc_inform("LOAD: +[%s load]\n", cls->nameForLogging()); } //调用+load方法 (*load_method)(cls, SEL_load); } // Destroy the detached list. if (classes) free(classes); }
staticboolcall_category_loads(void) { int i, shift; bool new_categories_added = NO; // Detach current loadable list. structloadable_category *cats = loadable_categories;/*数据来源 在prepare阶段构建*/ int used = loadable_categories_used; int allocated = loadable_categories_allocated; loadable_categories = nil; loadable_categories_allocated = 0; loadable_categories_used = 0;
// Call all +loads for the detached list. for (i = 0; i < used; i++) { Category cat = cats[i].cat; load_method_t load_method = (load_method_t)cats[i].method; Class cls; if (!cat) continue;
// Compact detached list (order-preserving) shift = 0; for (i = 0; i < used; i++) { if (cats[i].cat) { cats[i-shift] = cats[i]; } else { shift++; } } used -= shift;
// Copy any new +load candidates from the new list to the detached list. new_categories_added = (loadable_categories_used > 0); for (i = 0; i < loadable_categories_used; i++) { if (used == allocated) { allocated = allocated*2 + 16; cats = (struct loadable_category *) realloc(cats, allocated * sizeof(struct loadable_category)); } cats[used++] = loadable_categories[i]; }
// Destroy the new list. if (loadable_categories) free(loadable_categories);
// Reattach the (now augmented) detached list. // But if there's nothing left to load, destroy the list. if (used) { loadable_categories = cats; loadable_categories_used = used; loadable_categories_allocated = allocated; } else { if (cats) free(cats); loadable_categories = nil; loadable_categories_used = 0; loadable_categories_allocated = 0; }
if (PrintLoading) { if (loadable_categories_used != 0) { _objc_inform("LOAD: %d categories still waiting for +load\n", loadable_categories_used); } }