Alloc low-level exploration supplement
In the last chapter, when we started with alloc, we learned that alloc essentially gives us memory space and relates our classes, so did we see any problems? Is there anything we haven’t noticed yet or have missed? So let’s go through alloc one more time
Paste the new alloc flow chart first
To get to the point:Debug –> Debug workflow–> Always show Disaseembly
We see assembly codecallq
– jump — — >objc_alloc
?????
Why notalloc
?
We givealloc
andobjc_alloc
At the same time, set a breakpoint and see who gets called first…We go through the break point next step, and we find that the first thing that comes up isobjc_alloc
, so awkward 😓
Alloc —->objc_alloc what the hell? We all know sel—-> IMP, through the method symbol sel to find IMP, and then through IMP to find the corresponding function implementation; So what’s going on here? We can guess if the IMP corresponding to sel has been modified.
objc
Source search for objc_alloc
So with that problem we’re going to have to go through the objc source code and search for objc_alloc, one by one
We’re going to find something by looking for objc_alloc
fixupMessageRef
Literally, repair message, that means when we sendalloc
Message forwarding will be fixed asobjc_alloc
?
We continue to trace the search for the fixupMessageRef method call and find that it is called in the _read_images method
Actually, we should be able to_read_images
Call found on method description_read_images
The method tomap_images_nolock
Then let’s keep tracking the searchmap_images_nolock
And then found outmap_images
Method, then keep tracking the searchmap_images
We call fixupMessageRef in the _read_images method after retracing the process, and since the image mapping occurred after dyld, sel-IMP fixes started so early, indicating imp binding started much earlier. This is the LLVM compile phase.
LLVM explore
LLVM source
We can download the LLVM source code from the above link, open it with VSCode, and then search for objc_alloc
We’ll explore it one by one, and you’ll see
if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "alloc")
return CGF.EmitObjCAlloc(Receiver, CGF.ConvertType(ResultType));
Copy the code
If sel is alloc then you call EmitObjCAlloc
Apple’s side will be for some special methods such as alloc init, etc., as the Apple of direct operating system memory method is that it do monitoring, so direct hook to live, just the alloc method, for example, does not directly go to alloc, but under the first objc_alloc good tags, and then go to alloc:
So this is going to follow the alloc and the objc_alloc break point that we started with when we went to objc_alloc, and we’re going to keep going
When you get to this side, then follow in tocallAlloc
Method, the next step we find won’t go_objc_rootAllocWithZone
This method, instead, goes down hereobjc_msgSend
Back to theLhkhPersonSent aalloc
The message
Once again, the next step comesalloc
This method
Why is this the case?
Because in the first call to alloc, LLVM tag to call tryGenerateSpecializedMessageSend method alloc method the recipient, And when objc_alloc–>callAlloc–>objc_msgSend–>alloc this is the next alloc, LLVM has marked the alloc method on the recipient, so it will go directly to GenerateMessageSend, So I’m going to go straight to the alloc method.
According to the above exploration, this situation will occur. In fact, it is the LLVM compile-time interception optimization. That is, when the alloc method is called, LLVM will intercept and mark the Receiver through the method. When objc_alloc–>callAlloc–>objc_msgSend–>alloc, LLVM finds that the Receiver has been marked and calls alloc directly; So that’s why callAlloc goes twice.
Alloc bottom exploration to this first, the subsequent discovery of new problems in the supplement, the content of the problem or wrong hope that god can correct, learn from each other 😜!