如何确定此地址在 64 位 macOS 应用程序上的来源

How to determine where this address comes from on 64-bit macOS application

所以我目前正在调试一个问题,并试图弄清楚这是怎么发生的。

这是 obj-c 运行时中方法的程序集,称为 objc_msgsend()

libobjc.A.dylib`objc_msgSend:
    0x7fff9084a0c0 <+0>:   testq  %rdi, %rdi
    0x7fff9084a0c3 <+3>:   je     0x7fff9084a140            ; <+128>
    0x7fff9084a0c6 <+6>:   testb  [=10=]x1, %dil
    0x7fff9084a0ca <+10>:  jne    0x7fff9084a14b            ; <+139>
    0x7fff9084a0cd <+13>:  movabsq [=10=]x7ffffffffff8, %r11
    0x7fff9084a0d7 <+23>:  andq   (%rdi), %r11
    0x7fff9084a0da <+26>:  movq   %rsi, %r10
    0x7fff9084a0dd <+29>:  andl   0x18(%r11), %r10d

我正在使用 Xcode 的 lldb 查看寄存器和地址。

这是我第一次检查偏移量 +0 处的寄存器时得到的有趣输出(预期):

(lldb) register read
r11 = 0x00007fff74a940f0  (void *)0x00007fff74a94118: NSObject

偏移+13后(预期):

(lldb) register read
r11 = 0x00007ffffffffff8

偏移量 +23 后(不是预期的):

(lldb) register read
r11 = 0x0000000100761138  (void *)0x0000000100761160: GTMOAuth2WindowController

然后如果我 po 此时寄存器:

(lldb) po $rdi
<GTMOAuth2WindowController: 0x6100001c2850>

(lldb) po &$rdi
0x000000010bc2b3b8

(lldb) po $r11
GTMOAuth2WindowController

(lldb) po &$r11
0x000000010bc2b3b8

这就是我迷路的地方;在偏移量+23之后,我register read时那个地址是什么? 0x0000000100761138。我希望它有 0x6100001c2850,在 +23

取消引用的对象的位置

如果我 po $r11 它打印出 class 名称(这是预期的,因为我们正在查看 isa 属性),如果我打印指针在内存中的位置,它与 register read 中的地址不匹配,它与 %rdi 中的地址匹配(预期)。

<+23>0x0000000100761138之后%r11中的那个地址是代表你的GTMOAuth2WindowControllerclass的class对象的地址.

当你在编译时定义一个 class(使用 @interface@implementation)时,在运行时有一个特殊的对象代表 class。事实上,它被称为“class 对象”,就像您创建的所有对象一样,它是一个真实的对象。这意味着 class 对象本身可以响应消息。当您在 <+23> 之后说 po %r11 时,调试器将 description 消息发送到 class 对象。 class 对象的 description 方法 returns class 的名称作为 NSString,因此调试器打印 class 的名称。

You can learn more about class objects here。该页面上的图像 link 在 Chrome 中已损坏,但您可以单击它查看 pdf。