preface

The flow of alloc method was analyzed above and the conclusion was drawn that The alloc method call flow is alloc ->_objc_rootAlloc ->callAlloc ->_objc_rootAllocWithZone ->_class_createInstanceFromZone () ->_class_createInstanceFromZone (); I thought I had figured out the alloc process. But when the alloc method is broken, look at the function call stack and see the following figure

XQPerson* person = [XQPerson alloc]; You can also see that objC_alloc is displayed as the call

As shown in the function call stack, the alloc methods are also called objc_alloc and callAlloc, So the complete alloc flow would be objC_alloc ->callAlloc->alloc ->_objc_rootAlloc ->callAlloc-> _objc_rootAllocWithZone ->_class_createInstanceFromZone

How do objc_alloc and callAlloc appear in the alloc call flow? With this question in mind, begin today’s exploration.

[fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] [fixupMessageRef] Replace the IMP of alloc with objc_alloc

Next, look at the order of function calls to find out under what circumstances the IMP that replaces alloc enters

Global search fixupMessageRef, found in the _read_images call

The _read_images function is called in map_images_nolock. If we search map_images_nolock, we can find that _read_images is actually called in this method

A global search for map_images_NOLock finds this function call in map_images.

A global search for map_images finds this function in the _dyLD_OBJC_notify_register of objc_init. At this point, the fixupMessageRef function calls the process locking reverse lookup.

Through the reverse lookup above, it can be determined that The call sequence is objc_init-> _DYLD_OBJC_notify_register ->map_images-> map_images_NOLock ->_read_images->fixupMessageRef Next debug by placing breakpoints in sequence at the above method calls

Alloc is replaced with objc_alloc, and fixupMessageRef is not called. So why would Apple provide a fix function that might not be called? So let’s diverge a little bit here, the real substitution could happen at compile time, and this is just a fault tolerant thing?

Let’s grab the LLVM source and drag it to Visual Studio Code to verify.

If the MachOView validates the executable, you can also see that the objc_alloc symbol already exists at compile time:

From the above analysis, it can be concluded that alloc->objc_alloc has been replaced in the LLVM stage. As for why Apple hook this function, it is speculated that the system may monitor object creation, release and other memory-related functions.

The complete flow chart of ALLOC is as follows:

Process summary: LLVM hooks the alloc method at compile time and replaces the alloc method with objc_alloc. When the runtime creates an XQPerson object, objC_alloc is called first. Then go to callAlloc and judge for the first time if (fastPath (! CLS – > ISA () – > hasCustomAWZ ())) is false, execution ((id (*) (* * * * id, SEL)) objc_msgSend) (CLS, @ the selector (alloc)); Method to send an alloc message to XQPerson, _objc_rootAlloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFromZone Calculate how much space is needed, open up memory, and associate classes with isa Pointers.