比如这个,是执行 objc_retain 崩溃还是执行 ldr 崩溃的?
之所以问这个问题是我在 ldr 处打了断点,按道理说还没执行 ldr 。
1
Qusic 2020-12-07 12:26:28 +08:00 via iPhone
上一行,retain bl 过去访问了 0x20 这个无效的地址
|
2
sunnywqf 2020-12-07 12:54:13 +08:00
估计是 x0 里的对象已经被释放了:
(lldb) disassemble -n objc_retain libobjc.A.dylib`objc_retain: 0x1c0aa7be0 <+0>: cbz x0, 0x1c0aa7c14 ; <+52> 0x1c0aa7be4 <+4>: tbnz x0, #0x3f, 0x1c0aa7c14 ; <+52> 0x1c0aa7be8 <+8>: ldr x8, [x0] 0x1c0aa7bec <+12>: and x8, x8, #0xffffffff8 0x1c0aa7bf0 <+16>: ldrb w8, [x8, #0x20] //////// 是在这里挂了, 加个断点看看 0x1c0aa7bf4 <+20>: tbz w8, #0x2, 0x1c0aa7c18 ; <+56> 0x1c0aa7bf8 <+24>: orr x8, xzr, #0x200000000000 |
3
fffang OP @sunnywqf
为啥我在 hopper 里或 xcode 断点里看 objc_retain 是这样的 ``` imp___stubs__objc_retain: // objc_retain 0000000100006548 nop ; CODE XREF=-[UIViewController new_initWithCoder:]+84 000000010000654c ldr x16, #_objc_retain_ptr ; _objc_retain 0000000100006550 br x16 ; _objc_retain ; endp ``` |
4
fffang OP ```
- (instancetype)new_initWithCoder:(NSCoder *)coder{ [self new_initWithCoder:coder]; return self; } ``` @sunnywqf 原始代码就这些,就是 hook 了初始化方法。按照上述代码运行会崩溃,但是直接` [self new_initWithCoder:coder];`这样是不会崩溃的,有兴趣的话可以一起研究下。 |
6
arnoldxiao 2020-12-09 16:19:00 +08:00
- (instancetype)new_initWithCoder:(NSCoder *)coder{
self = [self new_initWithCoder:coder]; return self; } |
7
fffang OP @arnoldxiao 这样是可以的,同理,把方法名中的 new 换掉也可以,直接 return 也可以,不过想知道为什么 self 经过原来的 init 方法会被 release 掉。
|
8
arnoldxiao 2020-12-10 09:34:15 +08:00
@fffang 不是被释放掉,你上一行执行初始化的返回实例没有赋值给 self,相当于 self 没有初始化
|
9
onevcat 2020-12-10 11:47:12 +08:00 1
OC 的 naming convention 里有一条叫做,new 开头的方法返回的东西会被认为 retain count +1 。但是实际上你的代码里并没有 retain 它,所以在 ARC 的世界里,这部分内存会被 release 两次,你就挂了。
记住,没搞清楚的情况下,别用 `new` 做方法或者属性的开头。同理还有 copy 啊之类的。 |
10
calvincheung 2020-12-10 15:03:32 +08:00
@onevcat 附议
|
11
fffang OP @onevcat 感谢,了解了。不过我翻了 objc 源码也没发现哪个地方有这部分的实现,用 clang 转写成 c++也不会有 retain 之类的关键词。
|
12
fffang OP 其实我正是在寻找 objc 内部处理 prefix 为 new 的方法的实现才特意这么写的,不过导致崩溃确实是我没想到的。
|
13
fffang OP InitWithCoder`-[UIViewController(hook) new_initWithCoder:]:
0x1043e1e60 <+0>: sub sp, sp, #0x40 ; =0x40 0x1043e1e64 <+4>: stp x29, x30, [sp, #0x30] 0x1043e1e68 <+8>: add x29, sp, #0x30 ; =0x30 0x1043e1e6c <+12>: stur x0, [x29, #-0x8] 0x1043e1e70 <+16>: stur x1, [x29, #-0x10] 0x1043e1e74 <+20>: add x8, sp, #0x18 ; =0x18 0x1043e1e78 <+24>: mov x9, #0x0 0x1043e1e7c <+28>: str x9, [sp, #0x18] 0x1043e1e80 <+32>: mov x0, x8 0x1043e1e84 <+36>: mov x1, x2 0x1043e1e88 <+40>: str x8, [sp, #0x10] 0x1043e1e8c <+44>: str x9, [sp, #0x8] 0x1043e1e90 <+48>: bl 0x1043e253c ; symbol stub for: objc_storeStrong 0x1043e1e94 <+52>: ldur x0, [x29, #-0x8] 0x1043e1e98 <+56>: ldr x2, [sp, #0x18] 0x1043e1e9c <+60>: adrp x8, 4 0x1043e1ea0 <+64>: add x8, x8, #0x4b8 ; =0x4b8 0x1043e1ea4 <+68>: ldr x1, [x8] 0x1043e1ea8 <+72>: bl 0x1043e2500 ; symbol stub for: objc_msgSend 0x1043e1eac <+76>: bl 0x1043e2518 ; symbol stub for: objc_release -> 0x1043e1eb0 <+80>: ldur x0, [x29, #-0x8] 0x1043e1eb4 <+84>: bl 0x1043e2524 ; symbol stub for: objc_retain 0x1043e1eb8 <+88>: ldr x8, [sp, #0x10] 0x1043e1ebc <+92>: str x0, [sp] 0x1043e1ec0 <+96>: mov x0, x8 0x1043e1ec4 <+100>: ldr x9, [sp, #0x8] 0x1043e1ec8 <+104>: mov x1, x9 0x1043e1ecc <+108>: bl 0x1043e253c ; symbol stub for: objc_storeStrong 0x1043e1ed0 <+112>: ldr x0, [sp] 0x1043e1ed4 <+116>: ldp x29, x30, [sp, #0x30] 0x1043e1ed8 <+120>: add sp, sp, #0x40 ; =0x40 0x1043e1edc <+124>: ret InitWithCoder`-[UIViewController(hook) abc_initWithCoder:]: 0x104ac1e60 <+0>: sub sp, sp, #0x40 ; =0x40 0x104ac1e64 <+4>: stp x29, x30, [sp, #0x30] 0x104ac1e68 <+8>: add x29, sp, #0x30 ; =0x30 0x104ac1e6c <+12>: stur x0, [x29, #-0x8] 0x104ac1e70 <+16>: stur x1, [x29, #-0x10] 0x104ac1e74 <+20>: add x8, sp, #0x18 ; =0x18 0x104ac1e78 <+24>: mov x9, #0x0 0x104ac1e7c <+28>: str x9, [sp, #0x18] 0x104ac1e80 <+32>: mov x0, x8 0x104ac1e84 <+36>: mov x1, x2 0x104ac1e88 <+40>: str x8, [sp, #0x10] 0x104ac1e8c <+44>: str x9, [sp, #0x8] 0x104ac1e90 <+48>: bl 0x104ac2530 ; symbol stub for: objc_storeStrong 0x104ac1e94 <+52>: ldur x0, [x29, #-0x8] 0x104ac1e98 <+56>: ldr x2, [sp, #0x18] 0x104ac1e9c <+60>: adrp x8, 4 0x104ac1ea0 <+64>: add x8, x8, #0x4b8 ; =0x4b8 0x104ac1ea4 <+68>: ldr x1, [x8] 0x104ac1ea8 <+72>: bl 0x104ac2500 ; symbol stub for: objc_msgSend 0x104ac1eac <+76>: mov x29, x29 0x104ac1eb0 <+80>: bl 0x104ac253c ; symbol stub for: objc_unsafeClaimAutoreleasedReturnValue -> 0x104ac1eb4 <+84>: ldur x8, [x29, #-0x8] 0x104ac1eb8 <+88>: ldr x9, [sp, #0x10] 0x104ac1ebc <+92>: mov x0, x9 0x104ac1ec0 <+96>: ldr x10, [sp, #0x8] 0x104ac1ec4 <+100>: mov x1, x10 0x104ac1ec8 <+104>: str x8, [sp] 0x104ac1ecc <+108>: bl 0x104ac2530 ; symbol stub for: objc_storeStrong 0x104ac1ed0 <+112>: ldr x0, [sp] 0x104ac1ed4 <+116>: ldp x29, x30, [sp, #0x30] 0x104ac1ed8 <+120>: add sp, sp, #0x40 ; =0x40 0x104ac1edc <+124>: ret 以 new 开头的方法到底做了什么呢?附上两个这两个仅仅方法名不同的汇编实现以供有兴趣的同学研究~ |