This is the 30th day of my participation in the August Challenge
Assembles and analyzes block processes
In the last article, we analyzed the underlying structure of blocks. In the next article, we will analyze the execution flow of blocks.
Let’s create a new iOS project and write the following code:
Create a breakpoint at the block and run the project to open the assembly screen:
In assembly code, we locate the objc_retainBlock symbol; We add the symbolic breakpoint objc_retainBlock and continue with the code:
Next, _Block_copy is called, and the symbolic breakpoint _Block_copy is added to execute the code down:
_Block_copy comes from libsystem_blocks. Dylib. The same call can be found in objc source code:
After _Block_copy is located, we can’t go any further because libsystem_blocks is not open source; But you can find an implementation of _Block_copy in libclosure’s source code:
Struct Block_layout *aBlock; struct Block_layout *aBlock; , its structure is as follows:
- I have one of these structures
isa
Member variable of, (pointing toStack block
orHeap block
) flags
Identification code, which can store some data information;invoke
Is to call a function;descriptor
Relevant description information (such as whether there is a destructor, etc.)
At this point, we print the data in the register:
x0
Is the message receiver, which is a__NSGlobalBlock__
Because at present ourblock
No external variables are captured;
Next we modify the block code as follows:
To continue executing the code to the _Block_copy symbol breakpoint, let’s print out the x0 register data:
- Because at this time
block
External variables are captured, so it is now a__NSStackBlock__
That is aStack block
; But based on our previous analysis,block
External variables are captured and areStrong reference
It should be oneHeap block
That’s right. Why is this placeStack block
Inconsistent??
But it should be noted that at this point in our program breakpoint process, _Block_copy has not finished execution!
_Block_copy = x0; _Block_copy = x0;
_Block_copy
When a method starts execution, and after executionreturn
When,x0
The register address has changed and is changed from__NSStackBlock__
Turned out to be__NSMallocBlock__
;_Block_copy
Method takes aStack block
Turned out to beHeap block
;
Now that we’ve analyzed the block changes from the assembly point of view, let’s examine them from the source code.
Source code analysis block process
The source code for _Block_copy is as follows:
Resolution:
(aBlock->flags & BLOCK_NEEDS_FREE)
ifblock
Is marked as released, so directreturn
;(aBlock->flags & BLOCK_IS_GLOBAL)
ifblock
Identified as global, so directreturn
;size_t size = Block_size(aBlock);
To obtainblock
The size of the;struct Block_layout *result = (struct Block_layout *)malloc(size)
Open up memory space according to size;memmove(result, aBlock, size)
Copy aBlock to result;result->isa = _NSConcreteMallocBlock
willblock
Relabel asHeap block
;
Only stack blocks can be generated at compile time, because there is no alloc or memory at compile time, so only stack blocks can be marked, and then stack blocks can be re-marked as heap blocks at run time.
When we look at the console print, we see that in addition to the above print, we also print the signature: “v8@? 0” and invoke, copy, dispose; So what are they?
signature
Is our currentblock
The signature;
We can view the signature information in the following way:
-
parsing
number of arguments = 1
: pass the1
The parameters;is special struct return? NO
: has no return value;argument 0:
: the parameters from0
# position start;flags {isObject, isBlock}
: is ablock
, is also aobject
That’s oneblock
Object of type;
-
Invoke is a pointer to the caller of a function;
So what do copy and dispose do to blocks? We’ll continue next time at……