美文网首页
第十篇:IOS里map_images和load_images方法

第十篇:IOS里map_images和load_images方法

作者: 坚持才会看到希望 | 来源:发表于2022-05-18 15:34 被阅读0次

    程序启动后会调用_objc_init,然后会进行一些初始的操作,如下源码显示:

    void _objc_init(void)
    {
        static bool initialized = false;
        if (initialized) return;
        initialized = true;
        
        // fixme defer initialization until an objc-using image is found?
        environ_init();
        tls_init();  -- tls是线程的局部存储
        static_init(); -- 运行c++的一些静态函数
        runtime_init();
        exception_init();
    #if __OBJC2__
        cache_t::init();
    #endif
        _imp_implementationWithBlock_init();
    
        _dyld_objc_notify_register(&map_images, load_images, unmap_image);
    
    #if __OBJC2__
        didCallDyldNotifyRegister = true;
    #endif
    }
    

    首先在我们Xcode里设置环境变量也就是打开load方法的输出,我们设置为OBJC_PRINT_LOAD_METHODS,然后看下运行代码后打印的。

    WechatIMG1967.jpeg
    
    objc[29649]: LOAD: class 'NSNotificationCenter' scheduled for +load
    objc[29649]: LOAD: category 'NSObject(NSObject)' scheduled for +load
    objc[29649]: LOAD: +[NSNotificationCenter load]
    
    objc[29649]: LOAD: +[NSObject(NSObject) load]
    
    objc[29649]: LOAD: class 'NSColor' scheduled for +load
    objc[29649]: LOAD: class 'NSApplication' scheduled for +load
    objc[29649]: LOAD: class 'NSBinder' scheduled for +load
    objc[29649]: LOAD: class 'NSColorSpaceColor' scheduled for +load
    objc[29649]: LOAD: class 'NSNextStepFrame' scheduled for +load
    objc[29649]: LOAD: +[NSColor load]
    
    objc[29649]: LOAD: +[NSApplication load]
    
    objc[29649]: LOAD: +[NSBinder load]
    
    objc[29649]: LOAD: +[NSColorSpaceColor load]
    
    objc[29649]: LOAD: +[NSNextStepFrame load]
    
    objc[29649]: LOAD: class '_DKEventQuery' scheduled for +load
    objc[29649]: LOAD: +[_DKEventQuery load]
    
    

    在控制台里我们看到有好多load方法的打印,可以看到好多类实现了load方法。

    下面是设置动态库的打印,设置环境变量为OBJC_PRINT_IMAGES,打印如下

    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/GLKit.framework/Versions/A/GLKit (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/AVFoundation.framework/Versions/A/AVFoundation (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/ModelIO.framework/Versions/A/ModelIO (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/PDFKit.framework/Versions/A/PDFKit (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/AVKit.framework/Versions/A/AVKit (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/SceneKit.framework/Versions/A/SceneKit (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/PrivateFrameworks/CoreServicesStore.framework/Versions/A/CoreServicesStore (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory (has class properties) (preoptimized)
    
    objc[29649]: IMAGES: loading image for /System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji (has class properties) (preoptimized)
    
    

    下面是一些xcode部分环境变量设置,在源码里开启help_帮助就可以打印出:

    objc[29649]: Objective-C runtime debugging. Set variable=YES to enable.
    objc[29649]: OBJC_HELP: describe available environment variables
    objc[29649]: OBJC_HELP is set
    objc[29649]: OBJC_PRINT_OPTIONS: list which options are set
    objc[29649]: OBJC_PRINT_OPTIONS is set
    objc[29649]: OBJC_PRINT_IMAGES: log image and library names as they are loaded
    objc[29649]: OBJC_PRINT_IMAGES is set
    objc[29649]: OBJC_PRINT_IMAGE_TIMES: measure duration of image loading steps
    objc[29649]: OBJC_PRINT_IMAGE_TIMES is set
    objc[29649]: OBJC_PRINT_LOAD_METHODS: log calls to class and category +load methods
    objc[29649]: OBJC_PRINT_LOAD_METHODS is set
    objc[29649]: OBJC_PRINT_INITIALIZE_METHODS: log calls to class +initialize methods
    objc[29649]: OBJC_PRINT_RESOLVED_METHODS: log methods created by +resolveClassMethod: and +resolveInstanceMethod:
    objc[29649]: OBJC_PRINT_CLASS_SETUP: log progress of class and category setup
    objc[29649]: OBJC_PRINT_PROTOCOL_SETUP: log progress of protocol setup
    objc[29649]: OBJC_PRINT_IVAR_SETUP: log processing of non-fragile ivars
    objc[29649]: OBJC_PRINT_VTABLE_SETUP: log processing of class vtables
    objc[29649]: OBJC_PRINT_VTABLE_IMAGES: print vtable images showing overridden methods
    

    下面我们重点看下 _dyld_objc_notify_register(&map_images, load_images, unmap_image);这个方法里的map_images和load_images。&map_images是引用传递,load_images是值传递。

    load_images方法就是去查找和调用load方法。load方法的调用顺序是 先找分类-->本类(子类)-->分类,如果两个分类都实现load方法,那就看编译的顺序,先编译就后执行

    void
    load_images(const char *path __unused, const struct mach_header *mh)
    {
        if (!didInitialAttachCategories && didCallDyldNotifyRegister) {
            didInitialAttachCategories = true;
            loadAllCategories();
        }
    
        // Return without taking locks if there are no +load methods here.
        if (!hasLoadMethods((const headerType *)mh)) return;
    
        recursive_mutex_locker_t lock(loadMethodLock);
    
        // Discover load methods
        {
            mutex_locker_t lock2(runtimeLock);
            prepare_load_methods((const headerType *)mh);
        }
    
        // Call +load methods (without runtimeLock - re-entrant)
        call_load_methods();
    }
    
    

    接着我们看map_images这个方法:

    void
    map_images(unsigned count, const char * const paths[],
               const struct mach_header * const mhdrs[])
    {
        mutex_locker_t lock(runtimeLock);
        return map_images_nolock(count, paths, mhdrs);
    }
    
    oid 
    map_images_nolock(unsigned mhCount, const char * const mhPaths[],
                      const struct mach_header * const mhdrs[])
    {
        static bool firstTime = YES;
        header_info *hList[mhCount];
        uint32_t hCount;
        size_t selrefCount = 0;
    
        // Perform first-time initialization if necessary.
        // This function is called before ordinary library initializers. 
        // fixme defer initialization until an objc-using image is found?
        if (firstTime) {
            preopt_init();
        }
    
        if (PrintImages) {
            _objc_inform("IMAGES: processing %u newly-mapped images...\n", mhCount);
        }
    
    
        // Find all images with Objective-C metadata.
        hCount = 0;
    
        // Count classes. Size various table based on the total.
        int totalClasses = 0;
        int unoptimizedTotalClasses = 0;
        {
            uint32_t i = mhCount;
            while (i--) {
                const headerType *mhdr = (const headerType *)mhdrs[i];
    
                auto hi = addHeader(mhdr, mhPaths[i], totalClasses, unoptimizedTotalClasses);
                if (!hi) {
                    // no objc data in this entry
                    continue;
                }
                
                if (mhdr->filetype == MH_EXECUTE) {
                    // Size some data structures based on main executable's size
    #if __OBJC2__
                    // If dyld3 optimized the main executable, then there shouldn't
                    // be any selrefs needed in the dynamic map so we can just init
                    // to a 0 sized map
                    if ( !hi->hasPreoptimizedSelectors() ) {
                      size_t count;
                      _getObjc2SelectorRefs(hi, &count);
                      selrefCount += count;
                      _getObjc2MessageRefs(hi, &count);
                      selrefCount += count;
                    }
    #else
                    _getObjcSelectorRefs(hi, &selrefCount);
    #endif
                    
    

    其实在map_images这个方法里我们主要研究read_images里的方法,方法如下,下面方法是进行层层跳转过来的。

    void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses)
    {
        header_info *hi;
        uint32_t hIndex;
        size_t count;
        size_t i;
        Class *resolvedFutureClasses = nil;
        size_t resolvedFutureClassCount = 0;
        static bool doneOnce;
        bool launchTime = NO;
        TimeLogger ts(PrintImageTimes);
    
        runtimeLock.assertLocked();
    
    #define EACH_HEADER \
        hIndex = 0;         \
        hIndex < hCount && (hi = hList[hIndex]); \
        hIndex++
    
        if (!doneOnce) {
            doneOnce = YES;
            launchTime = YES;
    
    #if SUPPORT_NONPOINTER_ISA
            // Disable non-pointer isa under some conditions.
    
    # if SUPPORT_INDEXED_ISA
            // Disable nonpointer isa if any image contains old Swift code
            for (EACH_HEADER) {
                if (hi->info()->containsSwift()  &&
                    hi->info()->swiftUnstableVersion() < objc_image_info::SwiftVersion3)
                {
                    DisableNonpointerIsa = true;
                    if (PrintRawIsa) {
                        _objc_inform("RAW ISA: disabling non-pointer isa because "
                                     "the app or a framework contains Swift code "
                                     "older than Swift 3.0");
                    }
                    break;
                }
            }
    

    相关文章

      网友评论

          本文标题:第十篇:IOS里map_images和load_images方法

          本文链接:https://www.haomeiwen.com/subject/xlmnurtx.html