上一篇《block函数块为何物?》介绍了在函数中定义的block函数块的反汇编实现,我在文中再三指出__block变量和block函数块自始还都是stack-based的,还不完全适合在离开定义它们的范围之外使用,包括异步回调。本篇贴上我手工逆向的函数
libsystem_blocks.dylib`_Block_copy_internal。从名字可以看出blocks编程由系统提供的编程框架,_Block_copy_internal也就是block函数块的copy方法,是令block函数块适合用于异步回调必要的操作。
NSStackBlock的逆向定义请参考上一篇《block函数块为何物?》,下面是函数的逆向C++代码:
附上逆向时参照的反汇编片段快照:
libsystem_blocks.dylib`_Block_copy_internal:
0x10ce28458 <+>: pushq %rbp
0x10ce28459 <+>: movq %rsp, %rbp
0x10ce2845c <+>: pushq %r15
0x10ce2845e <+>: pushq %r14
0x10ce28460 <+>: pushq %r13
0x10ce28462 <+>: pushq %r12
0x10ce28464 <+>: pushq %rbx
0x10ce28465 <+>: pushq %rax
0x10ce28466 <+>: movq %rdi, %rbx
0x10ce28469 <+>: xorl %eax, %eax
0x10ce2846b <+>: testq %rbx, %rbx
0x10ce2846e <+>: je 0x10ce28534 ; <+220>
0x10ce28474 <+>: leaq 0x8(%rbx), %rcx
0x10ce28478 <+>: testl $0x1000000, 0x8(%rbx)
0x10ce2847f <+>: jne 0x10ce284db ; <+131>
0x10ce28481 <+>: testl $0x8000000, (%rcx)
0x10ce28487 <+>: jne 0x10ce284f8 ; <+160>
0x10ce28489 <+>: testl $0x10000000, (%rcx)
0x10ce2848f <+>: jne 0x10ce28531 ; <+217>
0x10ce28495 <+>: movb 0xbad(%rip), %al ; isGC
0x10ce2849b <+>: testb %al, %al
0x10ce2849d <+>: je 0x10ce28543 ; <+235>
0x10ce284a3 <+>: movl 0x8(%rbx), %r13d
0x10ce284a7 <+>: movl %r13d, %r12d
0x10ce284aa <+>: andl $0x4000000, %r12d
0x10ce284b1 <+>: movq 0xb48(%rip), %r8 ; _Block_allocator
0x10ce284b8 <+>: movq 0x18(%rbx), %rax
0x10ce284bc <+>: movq 0x8(%rax), %rdi
0x10ce284c0 <+>: movb $0x1, %dl
0x10ce284c2 <+>: jne 0x10ce285b8 ; <+352>
0x10ce284c8 <+>: testl $0x40000000, (%rcx)
0x10ce284ce <+>: jne 0x10ce285a2 ; <+330>
0x10ce284d4 <+>: xorl %edx, %edx
0x10ce284d6 <+>: jmp 0x10ce285b8 ; <+352>
0x10ce284db <+>: movl (%rcx), %eax
0x10ce284dd <+>: movl %eax, %edx
0x10ce284df <+>: andl $0xfffe, %edx
0x10ce284e5 <+>: cmpl $0xfffe, %edx
0x10ce284eb <+>: je 0x10ce28531 ; <+217>
0x10ce284ed <+>: leal 0x2(%rax), %edx
0x10ce284f0 <+>: lock
0x10ce284f1 <+>: cmpxchgl %edx, (%rcx)
0x10ce284f4 <+>: jne 0x10ce284db ; <+131>
0x10ce284f6 <+>: jmp 0x10ce28531 ; <+217>
0x10ce284f8 <+>: testb %sil, %sil
0x10ce284fb <+>: je 0x10ce28531 ; <+217>
0x10ce284fd <+>: movl (%rcx), %eax
0x10ce284ff <+>: movl %eax, %edx
0x10ce28501 <+>: andl $0xfffe, %edx
0x10ce28507 <+>: cmpl $0xfffe, %edx
0x10ce2850d <+>: je 0x10ce28531 ; <+217>
0x10ce2850f <+>: leal 0x2(%rax), %edx
0x10ce28512 <+>: lock
0x10ce28513 <+>: cmpxchgl %edx, (%rcx)
0x10ce28516 <+>: jne 0x10ce284fd ; <+165>
0x10ce28518 <+>: andl $0xfffe, %edx
0x10ce2851e <+>: cmpl $0x2, %edx
0x10ce28521 <+>: jne 0x10ce28531 ; <+217>
0x10ce28523 <+>: movl $0x1, %esi
0x10ce28528 <+>: movq %rbx, %rdi
0x10ce2852b <+>: callq *0xae7(%rip) ; _Block_setHasRefcount
0x10ce28531 <+>: movq %rbx, %rax
0x10ce28534 <+>: addq $0x8, %rsp
0x10ce28538 <+>: popq %rbx
0x10ce28539 <+>: popq %r12
0x10ce2853b <+>: popq %r13
0x10ce2853d <+>: popq %r14
0x10ce2853f <+>: popq %r15
0x10ce28541 <+>: popq %rbp
0x10ce28542 <+>: retq
0x10ce28543 <+>: movq 0x18(%rbx), %r15
0x10ce28547 <+>: movq 0x8(%r15), %rdi
0x10ce2854b <+>: callq 0x10ce28b34 ; symbol stub for: malloc
0x10ce28550 <+>: movq %rax, %r14
0x10ce28553 <+>: xorl %eax, %eax
0x10ce28555 <+>: testq %r14, %r14
0x10ce28558 <+>: je 0x10ce28534 ; <+220>
0x10ce2855a <+>: movq 0x8(%r15), %rdx
0x10ce2855e <+>: movq %r14, %rdi
0x10ce28561 <+>: movq %rbx, %rsi
0x10ce28564 <+>: callq 0x10ce28b52 ; symbol stub for: memmove
0x10ce28569 <+>: andl $0xffff0000, 0x8(%r14)
0x10ce28571 <+>: orl $0x1000002, 0x8(%r14)
0x10ce28579 <+>: leaq 0xbd0(%rip), %rax ; _NSConcreteMallocBlock
0x10ce28580 <+>: movq %rax, (%r14)
0x10ce28583 <+>: testl $0x2000000, 0x8(%rbx)
0x10ce2858a <+>: je 0x10ce28629 ; <+465>
0x10ce28590 <+>: movq 0x18(%rbx), %rax
0x10ce28594 <+>: movq %r14, %rdi
0x10ce28597 <+>: movq %rbx, %rsi
0x10ce2859a <+>: callq *0x10(%rax)
0x10ce2859d <+>: jmp 0x10ce28629 ; <+465>
0x10ce285a2 <+>: leaq 0x10(%rax), %rdx
0x10ce285a6 <+>: testl $0x2000000, (%rcx)
0x10ce285ac <+>: cmoveq %rax, %rdx
0x10ce285b0 <+>: cmpq $0x0, 0x18(%rdx)
0x10ce285b5 <+>: setne %dl
0x10ce285b8 <+>: movzbl %sil, %r15d
0x10ce285bc <+>: movzbl %dl, %edx
0x10ce285bf <+>: movl %r15d, %esi
0x10ce285c2 <+>: callq *%r8
0x10ce285c5 <+>: movq %rax, %r14
0x10ce285c8 <+>: xorl %eax, %eax
0x10ce285ca <+>: testq %r14, %r14
0x10ce285cd <+>: je 0x10ce28534 ; <+220>
0x10ce285d3 <+>: movq 0x18(%rbx), %rax
0x10ce285d7 <+>: movq 0x8(%rax), %rdx
0x10ce285db <+>: movq %r14, %rdi
0x10ce285de <+>: movq %rbx, %rsi
0x10ce285e1 <+>: callq 0x10ce28b52 ; symbol stub for: memmove
0x10ce285e6 <+>: andl $0xf6ff0000, %r13d
0x10ce285ed <+>: addl %r15d, %r15d
0x10ce285f0 <+>: orl %r13d, %r15d
0x10ce285f3 <+>: orl $0x8000000, %r15d
0x10ce285fa <+>: movl %r15d, 0x8(%r14)
0x10ce285fe <+>: testl $0x2000000, 0x8(%rbx)
0x10ce28605 <+>: je 0x10ce28614 ; <+444>
0x10ce28607 <+>: movq 0x18(%rbx), %rax
0x10ce2860b <+>: movq %r14, %rdi
0x10ce2860e <+>: movq %rbx, %rsi
0x10ce28611 <+>: callq *0x10(%rax)
0x10ce28614 <+>: testl %r12d, %r12d
0x10ce28617 <+>: leaq 0xc32(%rip), %rax ; _NSConcreteAutoBlock
0x10ce2861e <+>: cmovneq 0x19ea(%rip), %rax ; (void *)0x000000010ce29350: _NSConcreteFinalizingBlock
0x10ce28626 <+>: movq %rax, (%r14)
0x10ce28629 <+>: movq %r14, %rax
0x10ce2862c <+>: jmp 0x10ce28534 ; <+220>
PS:博客园图片服务器不正常工作,数据上传后服务器返回http500,园方怡慢,迟迟还没解决。在此先占个placehoder。待园方解决问题后再上图。