汇编和源码配合分析alloc

2020-11-18  本文已影响0人  扫地僧练级

源码查找:苹果开源地址
先下载objc4-xxx.tar

开始

全局搜索alloc {,找到底层实现方法

20201118174435.jpg
image.png

最后看到的就是这些代码:

static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
    if (slowpath(checkNil && !cls)) return nil;

#if __OBJC2__
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        // No alloc/allocWithZone implementation. Go straight to the allocator.
        // fixme store hasCustomAWZ in the non-meta class and 
        // add it to canAllocFast's summary
        if (fastpath(cls->canAllocFast())) {
            // No ctors, raw isa, etc. Go straight to the metal.
            bool dtor = cls->hasCxxDtor();
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            obj->initInstanceIsa(cls, dtor);
            return obj;
        }
        else {
            // Has ctor or raw isa or something. Use the slower path.
            id obj = class_createInstance(cls, 0);
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            return obj;
        }
    }
#endif

    // No shortcuts available.
    if (allocWithZone) return [cls allocWithZone:nil];
    return [cls alloc];
}

但是这么看各种if else是不是不爽,接下来通过汇编看看:

  • 终端执行register read (寄存器-简单理解 存储指针)如下:
    (注意:执行前将符号榜断点只保留alloc的)
x0 = 0x00000001042d95e8  (void *)0x00000001042d95c0: ZKCPerson
        x1 = 0x00000001c568183f  
        x2 = 0x0000000000000001
        x3 = 0x000000016bb2de10
        x4 = 0x0000000000000010
        x5 = 0x000000016bb2da1f
        x6 = 0x000000016bb2db10
        x7 = 0x0000000000000000
        x8 = 0x00000001c5681000  
        x9 = 0x0000000000000303
       x10 = 0x00000002420cce4f
       x11 = 0x0000000000000003
       x12 = 0x0000000000000003
       x13 = 0x0000000000000000
       x14 = 0x00000000000000f2
       x15 = 0x00000001cb12b198  (void *)0x00000001c568180f
       x16 = 0x21512c8188dbe2e4 (0x0000000188dbe2e4) libobjc.A.dylib`+[NSObject alloc]
       x17 = 0x0000000188dbe2e4  libobjc.A.dylib`+[NSObject alloc]
       x18 = 0x0000000000000000
       x19 = 0x0000000000000000
       x20 = 0x0000000135e0a9d0
       x21 = 0x00000001d7236000  _MergedGlobals.9 + 24
       x22 = 0x00000001c5681f05  
       x23 = 0x0000000000000001
       x24 = 0x0000000000000001
       x25 = 0x00000001d4346000  UIKitCore`UIKeyboardSquishTransition._useInteractiveOpacity
       x26 = 0x0000000135e08a10
       x27 = 0x00000002834e6c40
       x28 = 0x00000001c568b55a  
        fp = 0x000000016bb2dc80
        lr = 0x00000001042d5e30  001`-[ViewController viewDidLoad] + 108 at ViewController.m:21:21
        sp = 0x000000016bb2dc00
        pc = 0x0000000188dbe2e4  libobjc.A.dylib`+[NSObject alloc]
      cpsr = 0x40000000
因为OC方法有两个默认参数:
  1. id self
  2. _cmd 当前方法的selector
所以可以执行以下命令:只读x0 register read x0,结果如下:

(x0 第一个参数 -返回的时候 返回值的存储地方)

x0 = 0x00000001042d95e8 (void *)0x00000001042d95c0: ZKCPerson

继续执行: po 0x00000001042d95e8

po 0x00000001042d95e8
ZKCPerson

可以看到现在还没指针(alloc-申请空间-给指针地址)

20201118210836.jpg

在retab(返回对象)前增加断点,继续,执行register read x0

x0 = 0x0000000282f6c000

继续执行 po 0x0000000282f6c000

<ZKCPerson: 0x282f6c000>

可以看见现在person有了指针0x282f6c000

未完待续,先关注一波。。。

上一篇下一篇

猜你喜欢

热点阅读