Applications rely on a number of libraries, including systemic ones such as UIKit, CoreFoundation, and third-party ones.

What is a library?

  • Libraries are executable binaries that can be loaded into memory by the operating system.
  • Libraries are divided into static libraries and dynamic libraries.

The build process

  1. Source files are precompiled for lexical and syntactic analysis
  2. Compiles the precompiled results into assembly
  3. Link library files generate executables

Dynamic linker dyLD elicits

When we use a breakpoint to break the program, xCode will call the start function at the bottom of Thread1 on the left. This function comes from libdyld. Dylib

Dynamic linker dyLD source analysis

1. Download the latest source code of DYLD, which is currently 852. Dyld source code download

2. Global search _dyLD_start

3. Search the c++ function namespace dyldbootstrap globally, and search the start function in the file where the namespace resides

4. In the last step of the start function, return to dyld::_main to enter the main function.

Can seemainThe function takes up over 800 lines of code. Instead of starting the analysis line by line from top to bottom, work backwards to understand the main flow.

Dyld ::_main function source analysis of the main process

1. Result is returned at the end of the function.

2. The following two places are the return values of the sMainExecutable call function

3. Check the provenance of sMainExecutable in the _main function

Check the instantiateFromLoadedImage initialization function

returnmachORead objects.

4. Link sMainExecutable

5. Weak reference binding main program

6. Run everything that has been initialized

7. Notify the main program to enter the main() function

The main flow has been analyzed. Let’s follow the main flow for details

Dyld ::_main function source analysis process details added

1. First of all, the first 200 lines of code of _main function are conditional preparation, including the processing of environment, platform, version, path, host and other information, loading and inserting the dynamic library

2. Read the shared cache

3. Read the inserted dynamic library before linking the main program

4. After the link main program, link the inserted dynamic library

InitializeMainExecutable analysis

Insert the dynamic library, the main program are calledrunInitializersfunction

Because gLinkContext. NotifySingle = & notifySingle;

Global search for registerObjCNotifiers calls

It is found that _dyLD_OBJC_notify_register is called, and that this function is called by _objc_init in objC source code

The next inobjcIn the source_objc_initPress a breakpoint and print the call stack

Using the backward method again:

Libdispatch source code download

LibSystem source code download

This can be seen by the function call stack

  • libobjc.A.dylibCall the_objc_init
  • libdispatch.dylibCall the_os_object_init
    • Analysis of the_os_object_initImplementation:

_os_object_initThe function is called internally_objc_init

  • libdispatch.dylibCall thelibdispatch_init
    • Analysis of thelibdispatch_initImplementation:

libdispatch_initCall the_os_object_init

  • libSystem.B.dylibCall thelibSystem_initializer
    • Analysis of thelibSystem_initializerImplementation:

LibSystem_initializer calls libdispatch_init

  • Call thedyld ImageLoaderMachO::doModInitFunctionsfunction
    • Analysis of thedoModInitFunctionsImplementation:

That is to say,doModInitFunctionsMake sure thatlibSystemInitialize the

  • dyld ImageLoaderMachO::doInitialization
    • Analysis of thedoInitializationImplementation:

doInitializationCall thedoModInitFunctions

  • dyld ImageLoader::recursiveInitialization
    • Analysis of therecursiveInitializationImplementation:

This piece ofinitializeMainExecutableThe analysis process is also mentioned

_dyld_objc_notify_register

_dyld_objc_notify_register(&map_images, load_images, unmap_image);

In _objc_init, _dyLD_OBJC_notify_register has three parameters: map_images, load_images, unmap_image, _dyLD_OBJC_notify_register passes the parameter to the registerObjCNotifiers as it were

registerObjCNotifiersInternal:

  • sNotifyObjCMapped = mapped
  • sNotifyObjCInit = init
  • sNotifyObjCUnmapped = unmapped
  • somap_imagesCall issNotifyObjCMappedThe call

Where is the global search sNotifyObjCMapped called?

Where is notifyBatchPartial called for the global search?

Map_images (sNotifyObjCMapped) is called in the registerObjCNotifiers->notifyBatchPartial function

  • In the same wayload_imagesCall issNotifyObjCInitThe call

Where is the global search sNotifyObjCInit called?

Where is the global search notifySingle called?

Load, c++ function, main function call sequence analysis

Test code preparation:

int main(int argc, char * argv[]) {
    printf("Main call %s \n",__func__);
    NSString * appDelegateClassName;
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
__attribute__((constructor)) void cppFunc(a){
    printf(C++ function call: %s \n,__func__);
}

Copy the code
@implementation ViewController
+ (void)load{
    NSLog(@"\n %s function call",__func__);
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
@end
Copy the code

The result is as follows:The invocation sequence isload,c++The function,mainfunction

Load method call timing analysis

_dyLD_OBJC_notify_register the second parameter load_images is defined as follows:

  • To find theloadMethod:

  • Call allloadmethods

soloadThe method of in_objc_initCalled just before the end.

C++ function call timing analysis

Break point inside c++ function to view function call stack

In the calldoModInitFunctionsAfter the callcppFunc.doModInitFunctionsIs readmachOStudent: So thisc++The function is written inmachOIn the

Main function call timing analysis

indyldSource search_dyld_startThe assembly ofAfter callingdyldbootstrap::startAfter will be transferred tomainfunction

Practical operation verification:

  • Breakpoint pastdyldbootstrap::start
  • register readRead register
  • raxismainfunction

The flow chart of dyld