iOS dyld详解

// kernel sets up apple pointer to be just past end of envp arrayconst char** apple = envp;while(*apple != NULL) { ++apple; }++apple;// set up random value for stack canary// 栈溢出保护__guard_setup(apple);// now that we are done bootstrapping dyld, call
摘要由CSDN通过智能技术生成

// 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);

// now that we are done bootstrapping dyld, call dyld’s main

uintptr_t appsSlide = slideOfMainExecutable(appsMachHeader);

// 进入dyld::_main()函数

return dyld::_main(appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue);

}

dyld::_main()是整个App启动的关键函数,此函数里面做了很多事情,代码如下:

//

// Entry point for dyld. The kernel loads dyld and jumps to __dyld_start which

// sets up some registers and call this function.

//

// Returns address of main() in target program which __dyld_start jumps to

//

uintptr_t

_main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide,

int argc, const char* argv[], const char* envp[], const char* apple[],

uintptr_t* startGlue)

{

// Grab the cdHash of the main executable from the environment

// 第一步,设置运行环境

uint8_t mainExecutableCDHashBuffer[20];

const uint8_t* mainExecutableCDHash = nullptr;

if ( hexToBytes(_simple_getenv(apple, “executable_cdhash”), 40, mainExecutableCDHashBuffer) )

// 获取主程序的hash

mainExecutableCDHash = mainExecutableCDHashBuffer;

// Trace dyld’s load

notifyKernelAboutImage((macho_header*)&__dso_handle, _simple_getenv(apple, “dyld_file”));

#if !TARGET_IPHONE_SIMULATOR

// Trace the main executable’s load

notifyKernelAboutImage(mainExecutableMH, _simple_getenv(apple, “executable_file”));

#endif

uintptr_t result = 0;

// 获取主程序的macho_header结构

sMainExecutableMachHeader = mainExecutableMH;

// 获取主程序的slide值

sMainExecutableSlide = mainExecutableSlide;

CRSetCrashLogMessage(“dyld: launch started”);

// 设置上下文信息

setContext(mainExecutableMH, argc, argv, envp, apple);

// Pickup the pointer to the exec path.

// 获取主程序路径

sExecPath = _simple_getenv(apple, “executable_path”);

// rdar://problem/13868260 Remove interim apple[0] transition code from dyld

if (!sExecPath) sExecPath = apple[0];

if ( sExecPath[0] != ‘/’ ) {

// have relative path, use cwd to make absolute

char cwdbuff[MAXPATHLEN];

if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {

// maybe use static buffer to avoid calling malloc so early…

char* s = new char[strlen(cwdbuff) + strlen(sExecPath) + 2];

strcpy(s, cwdbuff);

strcat(s, “/”);

strcat(s, sExecPath);

sExecPath = s;

}

}

// Remember short name of process for later logging

// 获取进程名称

sExecShortName = ::strrchr(sExecPath, ‘/’);

if ( sExecShortName != NULL )

++sExecShortName;

else

sExecShortName = sExecPath;

// 配置进程受限模式

configureProcessRestrictions(mainExecutableMH);

// 检测环境变量

checkEnvironmentVariables(envp);

defaultUninitializedFallbackPaths(envp);

// 如果设置了DYLD_PRINT_OPTS则调用printOptions()打印参数

if ( sEnv.DYLD_PRINT_OPTS )

printOptions(argv);

// 如果设置了DYLD_PRINT_ENV则调用printEnvironmentVariables()打印环境变量

if ( sEnv.DYLD_PRINT_ENV )

printEnvironmentVariables(envp);

// 获取当前程序架构

getHostInfo(mainExecutableMH, mainExecutableSlide);

//-------------第一步结束-------------

// load shared cache

// 第二步,加载共享缓存

// 检查共享缓存是否开启,iOS必须开启

checkSharedRegionDisable((mach_header*)mainExecutableMH);

if ( gLinkContext.sharedRegionMode != ImageLoader::kDontUseSharedRegion ) {

mapSharedCache();

}

try {

// add dyld itself to UUID list

addDyldImageToUUIDList();

// instantiate ImageLoader for main executable

// 第三步 实例化主程序

sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);

gLinkContext.mainExecutable = sMainExecutable;

gLinkContext.mainExecutableCodeSigned = hasCodeSignatureLoadCommand(mainExecutableMH);

// Now that shared cache is loaded, setup an versioned dylib overrides

#if SUPPORT_VERSIONED_PATHS

checkVersionedPaths();

#endif

// dyld_all_image_infos image list does not contain dyld

// add it as dyldPath field in dyld_all_image_infos

// for simulator, dyld_sim is in image list, need host dyld added

#if TARGET_IPHONE_SIMULATOR

// get path of host dyld from table of syscall vectors in host dyld

void* addressInDyld = gSyscallHelpers;

#else

// get path of dyld itself

void* addressInDyld = (void*)&__dso_handle;

#endif

char dyldPathBuffer[MAXPATHLEN+1];

int len = proc_regionfilename(getpid(), (uint64_t)(long)addressInDyld, dyldPathBuffer, MAXPATHLEN);

if ( len > 0 ) {

dyldPathBuffer[len] = ‘\0’; // proc_regionfilename() does not zero terminate returned string

if ( strcmp(dyldPathBuffer, gProcessInfo->dyldPath) != 0 )

gProcessInfo->dyldPath = strdup(dyldPathBuffer);

}

// load any inserte

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值