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 giveallocandobjc_allocAt 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.

objcSource 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

fixupMessageRefLiterally, repair message, that means when we sendallocMessage 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_imagesCall found on method description_read_imagesThe method tomap_images_nolockThen let’s keep tracking the searchmap_images_nolock

And then found outmap_imagesMethod, 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 tocallAllocMethod, the next step we find won’t go_objc_rootAllocWithZoneThis method, instead, goes down hereobjc_msgSendBack to theLhkhPersonSent aallocThe message

Once again, the next step comesallocThis 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 😜!