// // ImageLoader is an abstract base class. To support loading a particular executable // file format, you make a concrete subclass of ImageLoader. // // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated. // // The ImageLoader base class does the work of linking together images, but it knows nothing // about any particular file format. // // class {ImageLoader ... }
// // 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, constchar* argv[], constchar* envp[], constchar* apple[], uintptr_t* startGlue) { ... //对全局变量一通操作 try { // add dyld itself to UUID list addDyldImageToUUIDList(); CRSetCrashLogMessage(sLoadingCrashMessage); // instantiate ImageLoader for main executable sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);//加载MACHO到image ... //不关心了 } }
// The kernel maps in main executable before dyld gets control. We need to // make an ImageLoader* for the already mapped in main executable. static ImageLoader* instantiateFromLoadedImage(const macho_header* mh, uintptr_t slide, constchar* path) { // try mach-o loader if ( isCompatibleMachO((constuint8_t*)mh, path) ) {//检测是否合法 ImageLoader* image = ImageLoaderMachO::instantiateMainExecutable(mh, slide, path, gLinkContext); //加载 addImage(image); return image; } throw"main executable not a known format"; }
/* skip CPU_TYPE_MIPS ((cpu_type_t) 8) */ /* skip ((cpu_type_t) 9) */ #define CPU_TYPE_MC98000 ((cpu_type_t) 10) #define CPU_TYPE_HPPA ((cpu_type_t) 11) #define CPU_TYPE_ARM ((cpu_type_t) 12) #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) #define CPU_TYPE_MC88000 ((cpu_type_t) 13) #define CPU_TYPE_SPARC ((cpu_type_t) 14) #define CPU_TYPE_I860 ((cpu_type_t) 15) /* skip CPU_TYPE_ALPHA ((cpu_type_t) 16) */ /* skip ((cpu_type_t) 17) */ #define CPU_TYPE_POWERPC ((cpu_type_t) 18) #define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) /* * Machine subtypes (these are defined here, instead of in a machine * dependent directory, so that any program can get all definitions * regardless of where is it compiled). */
/* * Capability bits used in the definition of cpu_subtype. */ #define CPU_SUBTYPE_MASK 0xff000000/* mask for feature flags */ #define CPU_SUBTYPE_LIB64 0x80000000/* 64 bit libraries */
/* * Object files that are hand-crafted to run on any * implementation of an architecture are tagged with * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as * the "ALL" subtype of an architecture except that it allows us * to easily find object files that may need to be modified * whenever a new implementation of an architecture comes out. * * It is the responsibility of the implementor to make sure the * software handles unsupported implementations elegantly. */ #define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1) #define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0) #define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1)
/* * Machine threadtypes. * This is none - not defined - for most machine types/subtypes. */ #define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0)
/* * VAX subtypes (these do *not* necessary conform to the actual cpu * ID assigned by DEC available via the SID register). */
boolisCompatibleMachO(const uint8_t* firstPage, constchar* path) { #if CPU_SUBTYPES_SUPPORTED // 支持检测CPU版本的情况 // It is deemed compatible if any of the following are true: // 1) mach_header subtype is in list of compatible subtypes for running processor // 2) mach_header subtype is same as running processor subtype // 3) mach_header subtype runs on all processor variants const mach_header* mh = (mach_header*)firstPage; if ( mh->magic == sMainExecutableMachHeader->magic ) { //传入的mach-o文件的magic是否和加载的主mach-o文件是否相同 //这一次运行到这里的时候mh与sMainExecutableMacHeader应该是指向同一个mach-o的 if ( mh->cputype == sMainExecutableMachHeader->cputype ) { if ( (mh->cputype & CPU_TYPE_MASK) == sHostCPU ) { //加载的mh是否在当前平台可以运行。 // get preference ordered list of subtypes that this machine can use constcpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(mh->cputype, sHostCPUsubtype); if ( subTypePreferenceList != NULL ) { //如果该CPU的版本存在一个检测的列表,则进行检测 // if image's subtype is in the list, it is compatible for (constcpu_subtype_t* p = subTypePreferenceList; *p != CPU_SUBTYPE_END_OF_LIST; ++p) { if ( *p == mh->cpusubtype ) returntrue; } // have list and not in list, so not compatible throwf("incompatible cpu-subtype: 0x%08X in %s", mh->cpusubtype, path); } // unknown cpu sub-type, but if exact match for current subtype then ok to use if ( mh->cpusubtype == sHostCPUsubtype ) //加载的mh与当前运行环境的CPU版本相同 returntrue; } // cpu type has no ordered list of subtypes // 这两种CPU支持所有版本的mach-o文件 switch (mh->cputype) { case CPU_TYPE_I386: case CPU_TYPE_X86_64: // subtypes are not used or these architectures returntrue; } } } #else // For architectures that don't support cpu-sub-types // this just check the cpu type. // 不支持检测CPU版本的时候,就只判断是mh的版本与CPU相同。 const mach_header* mh = (mach_header*)firstPage; if ( mh->magic == sMainExecutableMachHeader->magic ) { if ( mh->cputype == sMainExecutableMachHeader->cputype ) { returntrue; } } #endif returnfalse; }
#if __i386__ // kernel may have mapped in __IMPORT segment read-only, we need it read/write to do binding if ( image->fReadOnlyImportSegment ) { for(unsignedint i=0; i < image->fSegmentsCount; ++i) { if ( image->segIsReadOnlyImport(i) ) image->segMakeWritable(i, context); } } #endif //如果设置了context.verboseMapping,打印详细的LOG if ( context.verboseMapping ) { dyld::log("dyld: Main executable mapped %s\n", path); for(unsignedint i=0, e=image->segmentCount(); i < e; ++i) { constchar* name = image->segName(i); if ( (strcmp(name, "__PAGEZERO") == 0) || (strcmp(name, "__UNIXSTACK") == 0) ) dyld::log("%18s at 0x%08lX->0x%08lX\n", name, image->segPreferredLoadAddress(i), image->segPreferredLoadAddress(i)+image->segSize(i)); else dyld::log("%18s at 0x%08lX->0x%08lX\n", name, image->segActualLoadAddress(i), image->segActualEndAddress(i)); } }