返回
以对象属性为中心,利用LLDB调试iOS平台JavaScript逻辑
IOS
2023-09-07 08:56:32
深入探讨 iOS 中的 LLDB 调试:分析 JS 对象
简介
在 iOS 开发中,LLDB 调试器提供了强大的工具,用于深入分析 JavaScript (JS) 逻辑。本文将深入探讨如何利用 LLDB 来检查 JS 对象,包括 Butterfly 和普通对象的内存布局,以及如何查找相应的属性值。
基本流程
- 连接进程: 使用
attach
命令连接到目标进程。 - 创建表达式: 使用
expr
命令评估 JS 代码以创建表达式。 - 打印值: 使用
p
命令打印表达式的结果。 - 导航对象: 使用
.
运算符在对象属性之间导航。 - 设置断点: 使用
breakpoint
命令在特定代码行处设置断点以暂停执行。
Butterfly 和普通对象
iOS 中的 JS 对象有两种类型:Butterfly 对象和普通对象。
- Butterfly 对象: 更为常见,提供额外的空间开销以实现更快的属性访问和更低的内存占用。
- 普通对象: 不包含内联属性,内存占用较少,但属性访问速度较慢。
Butterfly 对象内存布局
+----------------+
| ButterflyHeader | 8 字节
+----------------+
| ButterflyInlines | 16 字节
+----------------+
| Properties | ... 字节
+----------------+
- ButterflyHeader: 包含对象的类型、内联属性数量、大小和哈希值。
- ButterflyInlines: 存储前三个内联属性的值。
- Properties: 存储剩余属性的值。
普通对象内存布局
+----------------+
| OrdinaryHeader | 16 字节
+----------------+
| PropertyStorage | ... 字节
+----------------+
- OrdinaryHeader: 包含对象的类型、大小和哈希值。
- PropertyStorage: 存储属性键和值。
查找属性值
Butterfly 对象:
- 获取对象的地址(使用
p
命令)。 - 计算 ButterflyHeader 的地址(
expr (ptrdiff_t)$arg1 + 8
)。 - 计算内联属性的数量(
expr *((int8_t *)$arg2 + 1)
)。 - 如果内联属性数量为 0,则计算 Properties 的地址(
expr (ptrdiff_t)$arg2 + 16
)。 - 遍历属性(使用
p
和.
运算符)直到找到所需的属性。
普通对象:
过程类似,但没有内联属性。
示例
(lldb) p object
0x10e315d70 <JSObject>
(lldb) expr (ptrdiff_t)$arg1 + 8
(JSButterflyHeader *) 0x10e315d68
(lldb) expr *((int8_t *)$arg2 + 1)
(int8_t) 2
(lldb) expr (ptrdiff_t)$arg2 + 16
(JSPropertyNameArray *) 0x10e315d90
(lldb) p `0x10e315d90`.getPropertyAtIndex(0)
(JSPropertyName) "foo"
(lldb) p `0x10e315d90`.getPropertyAtIndex(1)
(JSPropertyName) "bar"
(lldb) p `0x10e315d90`.getPropertyAtIndex(2)
(JSPropertyName) null
结论
掌握 LLDB 调试 JS 对象对于分析 iOS 应用程序至关重要。了解 Butterfly 和普通对象的数据结构以及查找属性值的方法,开发人员可以有效地调试 JS 代码,确保应用程序的预期行为。
常见问题解答
-
什么是 LLDB?
LLDB 是一个强大的调试器,用于分析 iOS 应用程序,包括 JS 逻辑。 -
为什么需要调试 JS 对象?
调试 JS 对象有助于查找错误、理解代码行为并优化应用程序性能。 -
如何连接到进程?
使用attach
命令将 LLDB 连接到目标进程。 -
如何查找对象的属性值?
使用expr
命令计算对象属性值的地址,然后使用p
和.
运算符导航到所需的值。 -
Butterfly 对象和普通对象之间有什么区别?
Butterfly 对象提供了更快的属性访问和更低的内存占用,而普通对象不包含内联属性,但内存占用较少。