应用程序加载原理 库:可执行的二进制文件,加载到内存 文件类型: 静态库 .a 动态库 .so .dll 两者是链接的区别
我们可以直接打开工程目录Products下的.app文件找到可执行文件拖到终端可以直接运行
库- 映射到内存 images
//输出
+[ViewController load]
(lldb) image list
[ 0] 404C4B96-E4D1-3501-BBDA-B6895DA2626A 0x000000010080c000
[ 1] 1AC76561-4F9A-34B1-BA7C-4516CACEAED7 0x0000000101122000 /usr/lib/dyld
[ 2] 2A92FC99-72A9-38ED-8DDD-AF4C25080124 0x0000000100820000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
[ 3] C2A18288-4AA2-3189-A1C6-5963E370DE4C 0x00007fff2071f000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation
接下来看dyld 动态链接器
dyldbootstrap jump 查找start
//重点看返回
return dyld::_main((macho_header*)appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue);
_main jump
getHostInfo jump
//instantiateFromLoadedImage 镜像文件加载器
CRSetCrashLogMessage(sLoadingCrashMessage);
// instantiate ImageLoader for main executable
sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);
gLinkContext.mainExecutable = sMainExecutable;
gLinkContext.mainExecutableCodeSigned = hasCodeSignatureLoadCommand(mainExecutableMH);
instantiateFromLoadedImage jump
addImage jump
instantiateMainExecutable jump
allImagesCount 拿到所有镜像文件个数
再执行runInitializers runInitializers jump
//重点代码
processInitializers(context, thisThread, timingInfo, up);
context.notifyBatch(dyld_image_state_initialized, false);
processInitializers jump
recursiveInitialization jump
//重点代码
context.notifySingle(dyld_image_state_dependents_initialized, this, &timingInfo);
// initialize this image
bool hasInitializers = this->doInitialization(context);
notifySingle jump
void (*notifySingle)(dyld_image_states, const ImageLoader* image, InitializerTimingList*);
单一注册通知
notifyMonitoringDyld sNotifyObjCInit
registerObjCNotifiers jump
sNotifyObjCInit = init;
单个镜像文件加载->_dyld_objc_notify_register
registerObjCNotifiers
_os_object_init jump
libdispatch_init jump
发现了_os_object_init();
libSystem_initializer jump
//重点代码 调用libdispatch_init
libdispatch_init();
_libSystem_ktrace_init_func(LIBDISPATCH);
doModInitFunctions jump
//重点代码 libSystemInitialized
if ( ! dyld::gProcessInfo->libSystemInitialized ) {
// <rdar://problem/17973316> libSystem initializer must run first
const char* installPath = getInstallPath();
if ( (installPath == NULL) || (strcmp(installPath, libSystemPath(context)) != 0) )
dyld::throwf("initializer in image (%s) that does not link with libSystem.dylib\n", this->getPath());
}
func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
ImageLoaderMachO 里调用了 doModInitFunctions 初始化镜像文件 调用doModInitFunctions
流程梳理
_os_object_init (libdispatch) -> _objc_init (libobjc)
_objc_init jump
_dyld_objc_notify_register jump
registerObjCNotifiers jump
//赋值代码
// record functions to call
sNotifyObjCMapped = mapped;
sNotifyObjCInit = init;
sNotifyObjCUnmapped = unmapped;
调用 doModInitFunctions
doInitialization 调用
// initialize this image
bool hasInitializers = this->doInitialization(context);
sNotifyObjCMapped 调用
static void notifyBatchPartial(dyld_image_states state, bool orLater, dyld_image_state_change_handler onlyHandler, bool preflightOnly, bool onlyObjCMappedNotification) 方法里调用sNotifyObjCMapped
if ( objcImageCount != 0 ) {
dyld3::ScopedTimer timer(DBG_DYLD_TIMING_OBJC_MAP, 0, 0, 0);
uint64_t t0 = mach_absolute_time();
(*sNotifyObjCMapped)(objcImageCount, paths, mhs);
uint64_t t1 = mach_absolute_time();
ImageLoader::fgTotalObjCSetupTime += (t1-t0);
}
notifyBatchPartial jump
registerObjCNotifiers 注册 调用 notifyBatchPartial
sNotifyObjCInit notifySingle 调用 sNotifyObjCInit
ImageLoader 递归循环流程 调用 notifySingle
//重点代码 先进行赋值再进行初始化
context.notifySingle(dyld_image_state_dependents_initialized, this, &timingInfo);
// initialize this image - 初始化所有images- load_images 赋值
bool hasInitializers = this->doInitialization(context);
// let anyone know we finished initializing this image
fState = dyld_image_state_initialized;
oldState = fState;
context.notifySingle(dyld_image_state_initialized, this, NULL);
run 起来 bt 首先调用的是 +[ViewController load] ,再调用doModInitFunctions,表面上看跟上面写的代码是恰好相反的
所有镜像文件内部初始化 -> load方法 -> hl_objc
load_images jump
prepare_load_methods jump
realizeClassWithoutSwift 实现分类
schedule_class_load jump
schedule_class_load(cls->getSuperclass());
add_class_to_loadable_list jump
添加到loadable_classes,就是相当 数组,里面装模型,数组的相应下标得到字典,字典相应下标得到值。loadable_classes收集所有的load方法(包括class方法、分类方法)
loadable_classes[loadable_classes_used].cls = cls;
loadable_classes[loadable_classes_used].method = method;
loadable_classes_used++;
> getLoadMethod jump
if (0 == strcmp(name, "load")) {
return meth.imp(false);
}
add_category_to_loadable_list jump
_category_getLoadMethod jump
mlist = ISA()->data()->ro()->baseMethods() //递归所有的baseMethods
return meth.imp(false); //返回过去
call_load_methods jump
call_class_loads jump 在call_load_methods被调用 (*load_method)(cls, @selector(load));
call_category_loads jump 在call_load_methods被调用 (*load_method)(cls, @selector(load));
未完待续......