如何确定此地址在 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
中的那个地址是代表你的GTMOAuth2WindowController
class的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。
所以我目前正在调试一个问题,并试图弄清楚这是怎么发生的。
这是 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
中的那个地址是代表你的GTMOAuth2WindowController
class的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。