staticintexec_activate_image(struct image_params *imgp) { /* * For exec, the translock needs to be taken on old proc and not * on new shadow proc. */ if (imgp->ip_flags & IMGPF_EXEC) { p = current_proc(); }
error = execargs_alloc(imgp); if (error) { goto bad_notrans; }
/* * Before we start the transition from binary A to binary B, make * sure another thread hasn't started exiting the process. We grab * the proc lock to check p_lflag initially, and the transition * mechanism ensures that the value doesn't change after we release * the lock. */ proc_lock(p); if (p->p_lflag & P_LEXIT) { error = EDEADLK; proc_unlock(p); goto bad_notrans; } error = proc_transstart(p, 1, 0); proc_unlock(p); if (error) { goto bad_notrans; }
error = exec_check_permissions(imgp); if (error) { goto bad; }
encapsulated_binary: /* Limit the number of iterations we will attempt on each binary */ if (++itercount > EAI_ITERLIMIT) { error = EBADEXEC; goto bad; } error = -1; for (i = 0; error == -1 && execsw[i].ex_imgact != NULL; i++) { error = (*execsw[i].ex_imgact)(imgp);
switch (error) { /* case -1: not claimed: continue */ case-2: /* Encapsulated binary, imgp->ip_XXX set for next iteration */ goto encapsulated_binary;
/* * Call out to allow 3rd party notification of exec. * Ignore result of kauth_authorize_fileop call. */ if (kauth_authorize_fileop_has_listeners()) { kauth_authorize_fileop(vfs_context_ucred(imgp->ip_vfs_context), KAUTH_FILEOP_EXEC, (uintptr_t)ndp->ni_vp, 0); } }
return error; }
execsw 符号含义
execsw符号可在开源代码中找到定义,如下。execsw是结构体常量数组,内部存放了函数地址和函数描述对,因此exec_activate_image函数可以使用循环的方式遍历该数组并调用其存放的函数。这里 Apple 开发者有一句注释,表示当前对该数组是硬编码的,后期会采用链接器集的方式实现,但这么多年来,该数组没有发生过变化,即便是 os14.0 Beta 版本的发布也没有对此进行更新。值得注意的是数组存放的第一个函数地址exec_mach_imgact,这是 Mach-o 格式的可执行文件解析、加载、执行所必经的函数。该函数相当复杂,代码接近千行,本文不对此讨论。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* * Our image activator table; this is the table of the image types we are * capable of loading. We list them in order of preference to ensure the * fastest image load speed. * * XXX hardcoded, for now; should use linker sets */ structexecsw { int(*const ex_imgact)(struct image_params *); constchar *ex_name; } const execsw[] = { { exec_mach_imgact, "Mach-o Binary" }, { exec_fat_imgact, "Fat Binary" }, { exec_shell_imgact, "Interpreter Script" }, { NULL, NULL} };