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
LLVM
To 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 seealloc
The implementation of the
And then intoalloc
Method, which calls the_objc_rootAlloc
Method, break point
And then enter_objc_rootAlloc
Methods,_objc_rootAlloc
Method, which calls thecallAlloc
Method, but in1956
Row, also calledcallAlloc
Method, 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_alloc
Method, not break in+(id)alloc
Method above.
When we let the breakpoint go one more step down, the breakpoint is executing to+(id)alloc
On the way
Object initialization is executedalloc
And got there firstobjc_alloc
Method, and then to+(id)alloc
Why is that?
Now that we know that alloc compiles objc_alloc, we don’t know when.
At the beginning of the article, I saiddlyd
The loading process of. Here, we first directly locate the class load map inside (map the current image file), find_read_images
methods
Inside this method, there is a code block that handles the mapping method number, which is inside the methodisa
Pointers andimp
Relationship 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) 8443
All right, from what I can see, whenalloc
When something goes wrong, fix it. Put the crooked way back on track. whenmsg->imp == &objc_msgSend_fixup
If theMSG ->sel == @selector(alloc), MSG ->imp
Go back to(IMP)&objc_alloc
Make a mark; Of course, if there are no problems, just do itobjc_alloc
Method, do not need to repair. in_read_images
Inside the method, I made a layerfixupMessageRef
Repair.
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_alloc
Method at the breakpoint
Then enter thecallAlloc
Method, comecallAlloc
When you go one step further, you get there directly1940
Row, middle, no entry1932
Line of code, also did not enter1938
Lines 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 iscallalloc
Method, why is it executedtwo
The 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 ~ ~ ~ ~ ~ ~