返回

以对象属性为中心,利用LLDB调试iOS平台JavaScript逻辑

IOS

深入探讨 iOS 中的 LLDB 调试:分析 JS 对象

简介

在 iOS 开发中,LLDB 调试器提供了强大的工具,用于深入分析 JavaScript (JS) 逻辑。本文将深入探讨如何利用 LLDB 来检查 JS 对象,包括 Butterfly 和普通对象的内存布局,以及如何查找相应的属性值。

基本流程

  1. 连接进程: 使用 attach 命令连接到目标进程。
  2. 创建表达式: 使用 expr 命令评估 JS 代码以创建表达式。
  3. 打印值: 使用 p 命令打印表达式的结果。
  4. 导航对象: 使用 . 运算符在对象属性之间导航。
  5. 设置断点: 使用 breakpoint 命令在特定代码行处设置断点以暂停执行。

Butterfly 和普通对象

iOS 中的 JS 对象有两种类型:Butterfly 对象和普通对象。

  • Butterfly 对象: 更为常见,提供额外的空间开销以实现更快的属性访问和更低的内存占用。
  • 普通对象: 不包含内联属性,内存占用较少,但属性访问速度较慢。

Butterfly 对象内存布局

+----------------+
| ButterflyHeader |   8 字节
+----------------+
| ButterflyInlines |   16 字节
+----------------+
| Properties      |   ... 字节
+----------------+
  • ButterflyHeader: 包含对象的类型、内联属性数量、大小和哈希值。
  • ButterflyInlines: 存储前三个内联属性的值。
  • Properties: 存储剩余属性的值。

普通对象内存布局

+----------------+
| OrdinaryHeader  |   16 字节
+----------------+
| PropertyStorage |   ... 字节
+----------------+
  • OrdinaryHeader: 包含对象的类型、大小和哈希值。
  • PropertyStorage: 存储属性键和值。

查找属性值

Butterfly 对象:

  1. 获取对象的地址(使用 p 命令)。
  2. 计算 ButterflyHeader 的地址(expr (ptrdiff_t)$arg1 + 8)。
  3. 计算内联属性的数量(expr *((int8_t *)$arg2 + 1))。
  4. 如果内联属性数量为 0,则计算 Properties 的地址(expr (ptrdiff_t)$arg2 + 16)。
  5. 遍历属性(使用 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 代码,确保应用程序的预期行为。

常见问题解答

  1. 什么是 LLDB?
    LLDB 是一个强大的调试器,用于分析 iOS 应用程序,包括 JS 逻辑。

  2. 为什么需要调试 JS 对象?
    调试 JS 对象有助于查找错误、理解代码行为并优化应用程序性能。

  3. 如何连接到进程?
    使用 attach 命令将 LLDB 连接到目标进程。

  4. 如何查找对象的属性值?
    使用 expr 命令计算对象属性值的地址,然后使用 p. 运算符导航到所需的值。

  5. Butterfly 对象和普通对象之间有什么区别?
    Butterfly 对象提供了更快的属性访问和更低的内存占用,而普通对象不包含内联属性,但内存占用较少。