iOS 应用程序加载
1. APP 加载分析
1.1 动静态库
-
app依赖很多底层库,底层库是很什么?
可执行的代码的二进制,可以被操作系统写入到内存
-
库分为几种?
静态库: .a .lib,动态库: framework .so .dll -
动静态库的区别?
静态库:在链接阶段,会将汇编生成的目标文件与引用的库一起链接打包到可执行文件中,可能会重复编译多次
动态库:程序编译并不会链接到目标代码中,而是程序运行时才被载入。
优势:减少打包之后APP的大小,共享内容,节约资源,通过更新动态库,达到更新程序的目的。
常见动态库:UIKit,libdispatch、libobj.dyld
编译过程:
动静态库示例:
1.2 加载过程
2._dyld_start
分析
通过在+ (void)load
方法中添断点,查看调用堆栈,通过汇编查看,在程序启动的时,调用dyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**, dyld3::MachOLoaded const*, unsigned long*)
,那么在这之前还有一系列操作,
通过bt
,查看调用堆栈
接下来我们分析一下_dyld_start
,查看dyld
源码,全局搜索_dyld_start
,发现会跳转dyldbootstrap::start
方法,为c++
方法,
全局搜索start(
,找到start
方法,
uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* argv[],
intptr_t slide, const struct macho_header* dyldsMachHeader,
uintptr_t* startGlue)
{
// if kernel had to slide dyld, we need to fix up load sensitive locations
// we have to do this before using any global variables
slide = slideOfMainExecutable(dyldsMachHeader);
bool shouldRebase = slide != 0;
#if __has_feature(ptrauth_calls)
shouldRebase = true;
#endif
if ( shouldRebase ) {
rebaseDyld(dyldsMachHeader, slide);
}
// allow dyld to use mach messaging
mach_init();
// kernel sets up env pointer to be just past end of agv array
const char** envp = &argv[argc+1];
// kernel sets up apple pointer to be just past end of envp array
const char** apple = envp;
while(*apple != NULL) { ++apple; }
++apple;
// set up random value for stack canary
__guard_setup(apple);
#if DYL