primers

Before we get to the point, a quick tip: During App loading, dyLD is loaded. So what is dyld?

Dyld is a dynamic linker: loads all the libraries and executables

The following is a brief description of its loading process:

Step 1: Program execution starts from _dyLD_start

Step 2: Enter the dyld: main function

Step 3: Configure some environments: rebase_dyld loads the shared cache

Step 4: instantiate the main program DYLD2 / DYLD3 (closure mode)

1, load dynamic library (first, insert dynamic library) (main program and dynamic library will be added to allImages: loadAllImages)

2, link the main program, binding symbols (non-lazy loading, weak symbols) and so on the most critical: initialization method: initializeMainExecutable-> runInitializers -> processInitializers -> recursiveInitialization -> notifySingle

2.1. Within the notifySingle function, a callback is executed. This callback is Load_images, which is assigned when _objC_init is initialized

2.1.1. Execute class_load_methods in Load_images and call_class_loads, cyclic loads of each class

The doModInitFunction internally calls the C function of the global C++ object’s constructor, attribute (((constructor))

Step 5: Return the entry function of the main program. Start entering the main function of the main program!

So this is the dyLD load flow.

If you need dyLD source code of children’s shoes, you can leave a message oh ())o

With this initial understanding of dyLD, we can get down to business ~ ~ ~ GO GO GO

LLVMTo optimize thealloc

In the debug objc source code, which is available at ——–alloc, the underlying iOS explorer, a LGPerson class is declared and then called in main.m.

So let’s break here and seeallocThe implementation of the

And then intoallocMethod, which calls the_objc_rootAllocMethod, break point

And then enter_objc_rootAlloc Methods,_objc_rootAllocMethod, which calls thecallAllocMethod, but in1956Row, also calledcallAllocMethod, break point

Heh heh, after the preparation, you can enjoy digging the minefield (fun ^_^)

Now for breakpoint tracing, look carefully.

Now the breakpoint is just starting to break when alloc is about to be called. Normally, you would go right into the underlying implementation of alloc which is this code down here, but is that really how it works?

+ (id)alloc {
    return _objc_rootAlloc(self);
}
Copy the code

We then let the break point go one step down. The break point is right thereobjc_allocMethod, not break in+(id)allocMethod above.

When we let the breakpoint go one more step down, the breakpoint is executing to+(id)allocOn the way

Object initialization is executedallocAnd got there firstobjc_allocMethod, and then to+(id)allocWhy is that?

Now that we know that alloc compiles objc_alloc, we don’t know when.

At the beginning of the article, I saiddlydThe loading process of. Here, we first directly locate the class load map inside (map the current image file), find_read_imagesmethods

Inside this method, there is a code block that handles the mapping method number, which is inside the methodisaPointers andimpRelationship adjustment processing

Let’s go inside the _read_images method. In this method, there isa fix for size_t, which means that the binding of our isa pointer to imp must have happened before size_t was fixed, so _read_images is executed after the binding of isa pointer to imp, which is after LLVM compilation.

This fix method is in the same file(objc runtime - new. Mm) 8443All right, from what I can see, whenallocWhen something goes wrong, fix it. Put the crooked way back on track. whenmsg->imp == &objc_msgSend_fixupIf theMSG ->sel == @selector(alloc), MSG ->impGo back to(IMP)&objc_allocMake a mark; Of course, if there are no problems, just do itobjc_allocMethod, do not need to repair. in_read_imagesInside the method, I made a layerfixupMessageRefRepair.

As mentioned, _read_images is executed after the ISA pointer is bound to IMP, after LLVM is compiled.

Because Apple has hook processing for some methods, for example, alloc method is a direct operation on the system memory, so it will do corresponding monitoring, this is to do hook interception processing (itself is also a message mechanism). When you call alloc, instead of going directly through the underlying process of alloc, you first look at objC_alloc, and then you start marking the underlying layer; After the tag is done, look for the alloc method.

To return toobjc_allocMethod at the breakpoint

Then enter thecallAllocMethod, comecallAllocWhen you go one step further, you get there directly1940Row, middle, no entry1932Line of code, also did not enter1938Lines of code.

In this case, again, an alloc message is sent to CLS (LGPerson), objc_msgSend, so LGPerson receives the message, and then it will execute the alloc method, but the objC_alloc method was already marked, Therefore, after receiving the alloc message sent this time, it will directly enter the normal track and directly call the alloc underlying method process.

A breakpoint is then performed to enter the + (ID)alloc method and start executing the underlying process

Summarize a flow chart (draw the order ha 😄)

This iscallallocMethod, why is it executedtwoThe cause of the time

At this point, oh yeah, done, LLVM optimization alloc bottom exploration, is completed, there is no harvest ah, (do not allow no ah <( ̄▽ ̄)/)

Finally, attach a github address of LLVM: github.com/apple/llvm-…

Thank you for coming to ~ ~ ~ ~ ~ ~