What happened before the iOS program main function

Source: Internet
Author: User
Tags gcd uikit

I'm the preface.

The function of an iOS app is main() located main.m in, which is the program portal we know well. But knowing more about OBJC found that the program main has executed a lot of code before entering our functions, such as familiar + load methods. This article will follow the sequence of execution of the program, inquiring into, and dyld runtime seeing what happens before the main function.

Start a dynamic link library from Dyld

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 there is also an implicit link framework that can be tested: First find the executable file, I called TestMain the project, the emulator path found TestMain.app , the executable file by default, and then through the otool command:

$ otool-l Testmain

  

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

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

In addition to the more CoreGraphics (by Uikit dependency), there are two default added Lib. LIBOBJC, OBJC and Runtime,libsystem, contain a number of system-level LIB, listed in several well-known: Libdispatch (GCD), Libsystem_c (C-language library), Libsystem_blocks (Block), Libcommoncrypto (commonly used MD5 functions) 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 maintenance: Because the LIB is dependent on the implementation of the program is only link, so these lib is easy to do updates, such as libSystem.dylib libSystem.B.dylib the alias, which day to upgrade directly 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 递归 into memory, of course there are缓存机制
    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 dyldStartup.s this document, in which the Assembly implements the method named, the __dyld_start assembly is too jerky, it mainly does two things:

    1. Calling dyldbootstrap::start() methods (omitting 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, setting a 符号断点 break in _objc_init :

This function is runtime the initialization function, 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 mentioned, due libSystem to the default introduction, the stack appeared in libSystem_initializer the initialization method.

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 role is to load these files into memory, and each file corresponding to a Imageloader instance to load.
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 the libSystem_initializer gradual call to the _objc_init , This is the initial entry for the OBJC and runtime.

In addition to the initialization of the runtime environment, the _objc_init new image is bound to the callback after it is loaded:

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 of the runtime ImageLoader middle, 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, 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, it was added before and after the runtime called the Load method objc_autoreleasePoolPush() objc_autoreleasePoolPop() .

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, there are like GCD , and XPC 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.