1

我很惊讶搜索j__objc_msgSend在 stackoverflow 上返回 0 结果,而 Google 似乎也不太了解。根据它的拆解,j__objc_msgSend 只调用了 objc_msgSend,那么为什么我们已经有了 objc_msgSend 还需要 j__objc_msgSend 呢?总的来说,j__objc_msgSend 和 objc_msgSend 有什么区别?

在这个截图中,最右边的分支以“函数结束”结尾,最左边的分支没有“函数结束”有什么区别?它与j__objc_msgSend 有关吗?

4

1 回答 1

1
  1. 这是 ARM RISC 代码,ARM 的首选编程模式是相对的——不要使用绝对地址,始终使用“IP+/-offset”。在这里,被调用的地址超出了直接调用或跳转的范围,编译器使用了他能找到的最近的地址。它增加了一个额外的跳跃(或超过 1 个!),但它与位置无关。(*)

    编译器无法使用简单的指令构造到目标地址的跳转,因为您无法立即使用 RISC 汇编加载每个可能的 2^32 数字。

  2. 如果例程objc_msgSend自己返回,那么这相当于call objc_msgSend; return-- 只是更短。从当前函数的角度来看,这两种形式都只做一次“返回”。


(*) 您可以在反汇编屏幕截图中看到(??为什么不是文本?) R12 加载了目标地址和当前地址之间的差异。这个差异是由编译器计算出来的;它不会原始二进制文件中显示为减法,这是 IDA 的工作。然后将差值添加到当前地址——不管它是什么!立即objc_msgSend - 0x1AE030数使用足够少的位在一条指令中加载到 R12 中(您应该熟悉的 ARM RISC '功能')。

如果您想知道语法:这只是 IDA,告诉您这是直接跳转到已知标签。据推测,如果你的代码足够长,你可能会发现到这个标签的距离又太大了,所以你可能会发现.j__labelj__j__objc_msgSend

于 2013-10-21T20:32:05.477 回答