What happened before the iOS program main function

Source: Internet
Author: User
Tags gcd uikit


I'm the preface.


The main () function of an iOS app is located in Main.m, which is a well-known program entry . But knowing more about OBJC found that the program had executed a lot of code before entering our main function, such as the well-known + load method. This article will follow the sequence of execution of the program, inquiring, from Dyld to runtime, to see what happened before the main function.


Starting from DyldDynamic Link Library


All of the system frameworks used in iOS are dynamically linked, analogous to plugs and inserts, statically linked code is plugged in and plugged in after a static link, and the runtime executes the binaries directly, while the dynamic link needs to complete the "plug-in" process when the program starts, So before we write the code, the dynamic connector needs to do the preparation.



This is the link list that you see in Xcode:

These frameworks will be loaded during the dynamic linking process, and the framework of the implied link can be tested: First find the executable file, I call Testmain's project, Testmain.app is found under the emulator path, the executable file defaults to the same name, and then through the Otool command:


1
Otool-Ltestmain


The- l parameter prints out the framework of all link (version information is removed):


1234567
 
TestMain: /System/Library/Frameworks/CoreGraphics.framework/CoreGraphics 
    /System/Library/Frameworks/UIKit.framework/UIKit
    /System/Library/Frameworks/Foundation.framework/Foundation
    /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation 
    /usr/lib/libobjc.A.dylib /usr/lib/libSystem.dylib


In addition to the Coregraphics (which is uikit dependent), there are two lib that are added by default. LIBOBJC is OBJC and runtime,Libsystem contains a lot of system-level LIB, listed several well-known: Libdispatch (GCD), Libsystem_c (C language Library), Libsystem_blocks (Block), libcommoncrypto (commonly used MD5 function) and so on. These lib are dylib formats (such as DLLs in Windows), and the system uses dynamic links for several advantages:


    • Code sharing: Many programs dynamically link these lib, but they have only one copy in memory and disk
    • Easy to maintain: Because the dependent Lib is the program execution link, so these lib is easy to do updates, For example, Libsystem.dylib is Libsystem.b.dylib's double, one day want to upgrade directly to Libsystem.c.dylib and then replace the avatar on the line
    • Reduce the volume of executable files: executable files are much smaller than static links
Dyld


dyld-the Dynamic Link Editor (this abbreviation corresponds to very strange, I feel is dynamic Linker daemon? Apple's dynamic linker, the system kernel the initial preparation of the start-up program, to Dyld responsible, invoke and translate "Mikeask this blog" on the Dyld of the role of the Order of the summary:


    1. Boot and start yourself from the original call stack left by kernel
    2. Load the dynamic link library that the program relies on recursively into memory, and of course there is a caching mechanism
    3. The Non-lazy symbol immediately link to the executable file, the Lazy memory table
    4. Runs static initializers for the executable
    5. Locate the main function of the executable file, prepare the parameters and invoke the
    6. It is responsible for binding the lazy symbol in program execution, providing runtime dynamic loading services, providing debugger interface
    7. Program main function return after executing static terminator
    8. The _exit function of Libsystem after the end of main function in some scenes


Thanks to the Dyld is open source, GitHub address, we can from the source of a probe.



It all stems from the Dyldstartup.s file, which uses the assembly to implement a method called __dyld_start, the assembly is too jerky, it mainly done two things:


    1. Call the Dyldbootstrap::start () method (omit parameters)
    2. The previous method returns the main function address, fills in the parameters and calls the main function


This step can be readily verified, and a symbolic breakpoint is set to break at _objc_init:

This function is the initialization function of the runtime, which is mentioned later. The program runs at a very early time and looks at the call stack:

See the bottom of the Dyldbootstrap::start () method, and then called the Dyld::_main () method, which completed the recursive loading of the dynamic library process just said, due to the Libsystem default introduction, the stack appears libsystem_ The initialization method of the initializer.


Imageloader


Of course, this image is not the meaning of the picture, it probably represents a binary file (executable or so file), which is compiled symbols, code, etc., so the Imageloader function is to load these files into memory, and Each file corresponds to a Imageloader instance that is responsible for loading .
Two-Step walk:


    1. When the program runs, it loads the dynamically linked image recursively (that is, the time of a string of recursive calls in the test stack above)
    2. Load all symbols recursively from the executable image


Of course all this happens before our real main function is executed.


Runtime and +load


Just talked about Libsystem is a set of several system lib, so it is just a container lib, and it is also open source, inside essentially a file, init.c, details do not say, by Libsystem_initializer gradually called to the _OBJC_ Init, this is the initial entry for OBJC and runtime.





 123 
" /td>
 Dyld_register_ Image_state_change_handler (Dyld_image_state_bound, 1   /*batch*/, &map_images);d Yld_register_image_state_change_handler (dyld_image_state_dependents_ Initialized, 0   /*not batch*/, &load_images); 


It is visible that Dyld serves as the coordinator between runtime and Imageloader, and when the new image is loaded, it is left to the runtime chef to parse the binary file's symbol table and code. Continue with the above breakpoint method and break the mysterious +load function:






See the entire call stack and order clearly:


    1. Dyld starts the program binary file initialization
    2. By Imageloader read the image, which contains our classes, methods and other symbols
    3. Since runtime binds a callback to Dyld, Dyld notifies runtime to process when the image is loaded into memory
    4. Runtime takes over and calls Map_images for parsing and processing, then calls the Call_load_methods method in Load_images, loops through all the loaded classes, Call the class's Load method and its category's Load method by inheritance level


At this point, all the symbols in the executable file and in the dynamic library (Class,protocol,selector,imp, ... ) have been successfully loaded into memory in the format, managed by the runtime, and after that, the runtime's methods (Dynamic Add class, method mix, etc. to take effect)


Several QA on the Load method


Q: Do I need to reload my class's Load method without needing to tune the parent?
A:runtime is responsible for recursive invocation in the order of inheritance, so we can't tune super



Q: Can I replace the method implementation of a class in the system framework (such as Uikit) in the load method of your class?
A: Yes, because all of the library-dependent classes are loaded before their classes, because of the dynamic linking process



Q: Do I need to manually add @autoreleasepool when loading load?
A: No, Objc_autoreleasepoolpush () and Objc_autoreleasepoolpop () are added before and after runtime calls to the Load method.



Q: Do you want the load method of a class to be called to import the file somewhere?
A: No, as long as the symbol of this class is compiled into the final executable, the Load method is called (The Reveal SDK uses this to work as soon as it is introduced into the project)


Brief summary


The entire event is led by Dyld, and after the initialization of the running environment is completed, the binary files are loaded into memory with Imageloader in a format.
The dynamic link relies on the library, and the runtime is responsible for loading the structure into the OBJC definition, and after all initialization work is done, Dyld invokes the true main function.
It is worth noting that this process is far more complex than written, here only refers to the runtime this branch, as well as GCD, xpc and so on the system library initialization branch did not mention (of course, there is a caching mechanism, they do not kill the initialization), summed up is the main function before the execution, The system did a lot of loading and initialization work, but are very well hidden, we do not care.


The main function of loneliness


When this is all over, Dyld will clean up the scene and return the call stack, leaving only:

The lonely main function, which appears to be the beginning of a program, is indeed a wonderful end.




What happened before the iOS program main function


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.