前言
如下所示,通常情况下,我们只能看到触发断点线程的指令代码。
如果希望看到另外一个函数或方法的指令,通常需要打开另外的工具。比如 Hopper。
x 命令
实际上,lldb 已经提供了一个方便的工具查看汇编代码。
x
是 lldb 的 memory read
命令缩写,它支持部分 GDB 简写格式的语法 GDB to LLDB command map
x [Address expression]
- Length 代表重复次数,默认是 1。通过它,可以控制多少个单位的内存进行输出。
- Format 输出内容的格式,常见对应关系如下所示, o - octal x - hexadecimal d - decimal u - unsigned decimal t - binary f - floating point a - address c - char s - string i - instruction b - bytes h - Halfwords(two bytes) w - Words (four bytes) g - Giant words (eight bytes)
- [Address expression]
任意合法的地址表达
- (lldb) x/3i NSLog
- 0x1a8dcb72c: 0xd10083ff sub sp, sp, #0x20 ; =0x20
- 0x1a8dcb730: 0xa9017bfd stp x29, x30, [sp, #0x10]
- 0x1a8dcb734: 0x910043fd add x29, sp, #0x10 ; =0x10
- (lldb) b NSLog
- Breakpoint 4: where = Foundation`NSLog, address = 0x00000001a8dcb72c
- (lldb) x/3i 0x00000001a8dcb72c
- 0x1a8dcb72c: 0xd10083ff sub sp, sp, #0x20 ; =0x20
- 0x1a8dcb730: 0xa9017bfd stp x29, x30, [sp, #0x10]
- 0x1a8dcb734: 0x910043fd add x29, sp, #0x10 ; =0x10
- (lldb) b dic
- Breakpoint 5: where = testLock`-[DataManager dic] at DataManager.m:14, address = 0x0000000104ee9d24
- (lldb) x/3i 0x0000000104ee9d24
- 0x104ee9d24: 0xd10043ff sub sp, sp, #0x10 ; =0x10
- 0x104ee9d28: 0xf90007e0 str x0, [sp, #0x8]
- 0x104ee9d2c: 0xf90003e1 str x1, [sp]
- (lldb) x/3i $pc
- -> 0x104ee9bc4: 0xf85c83a0 ldur x0, [x29, #-0x38]
- 0x104ee9bc8: 0x940001e5 bl 0x104eea35c ; symbol stub for: objc_release
- 0x104ee9bcc: 0xf85e83a8 ldur x8, [x29, #-0x18]
- (lldb) x/3i 4377713956
- 0x104ee9d24: 0xd10043ff sub sp, sp, #0x10 ; =0x10
- 0x104ee9d28: 0xf90007e0 str x0, [sp, #0x8]
- 0x104ee9d2c: 0xf90003e1 str x1, [sp]
- 合法的地址,如
0x0000000104ee9d24
4377713956
- 函数名
NSLog
- 寄存器名
$pc
实战
如下所示,我们可以通过以下步骤打印。 1、获取任意函数或者方案的地址。
2、以汇编格式打印该地址后方的内容。
下面,我们验证一下上面的汇编内容。
首先,我们先查看通过 Xcode 生成的汇编代码,(655-673行)
略以 .
"
Lfunc
Ltmp
开头的辅助信息后,我们可以发现两份数据完全一致。
至此,可以确认,通过 x
命令可以正确打印任意函数的汇编代码
参考文章
GDB to LLDB command map GDB Memory
lldb