LLDB 调试命令、插件和技巧(上)

简介: LLDB 调试命令、插件和技巧(上)

原生


p/po 命令

  • p 打印基本数据类型的值,查看对象返回对象的指针地址(不可以用宏)。
  • po 打印对象的描述,常量、变量、表达式返回的对象等。
(lldb) p p1
(Person *) $0 = 0x000061200023130
(lldb) po p1
<Person *): 0x000061200023130>


e 命令

给具体变量赋值。

if dataArray.count == 0 {
   print("dataArray is empty")
}

if 处断点,控制台输入 e dataArray.count = 0 回车,继续运行即可。


call 命令

动态调用函数。

(lldb) po cell.contentView.subviews
<__NSArrayM 0x60800005f5f0>(
<UILabel: 0x7f91f4f18c90; frame = (5 5; 300 25); text = '2 - Drawing index is top ...'; userInteractionEnabled = NO; tag = 1; layer = <_UILabelLayer: 0x60800009ff40>>,
<UIImageView: 0x7f91f4d20050; frame = (105 20; 85 85); opaque = NO; userInteractionEnabled = NO; tag = 2; layer = <CALayer: 0x60000003ff60>>,
<UIImageView: 0x7f91f4f18f10; frame = (200 20; 85 85); opaque = NO; userInteractionEnabled = NO; tag = 3; layer = <CALayer: 0x608000039860>>
)
(lldb) call [label removeFromSuperview]
(lldb) po cell.contentView.subviews
<__NSArrayM 0x600000246de0>(
<UIImageView: 0x7f91f4d20050; frame = (105 20; 85 85); opaque = NO; userInteractionEnabled = NO; tag = 2; layer = <CALayer: 0x60000003ff60>>,
<UIImageView: 0x7f91f4f18f10; frame = (200 20; 85 85); opaque = NO; userInteractionEnabled = NO; tag = 3; layer = <CALayer: 0x608000039860>>
)

动态将 cell 的某个子视图移除。


bt 命令

打印线程的堆栈信息(bt all 打印全部线程堆栈信息)。

(lldb) bt 
* thread #1: tid = 0x27363, 0x000000010d204125 TestDemo`-[FifthViewController tableView:cellForRowAtIndexPath:](self=0x00007f91f4e153c0, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007f91f5889600, indexPath=0xc000000000400016) + 2757 at FifthViewController.m:91, queue = 'com.apple.main-thread', stop reason = breakpoint 6.1
* frame #0: 0x000000010d204125 TestDemo`-[FifthViewController tableView:cellForRowAtIndexPath:](self=0x00007f91f4e153c0, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007f91f5889600, indexPath=0xc000000000400016) + 2757 at FifthViewController.m:91
frame #1: 0x0000000111d0a7b5 UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 757
frame #2: 0x0000000111d0aa13 UIKit`-[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
frame #3: 0x0000000111cde47d UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 3295
frame #4: 0x0000000111d13d95 UIKit`-[UITableView _performWithCachedTraitCollection:] + 110
frame #5: 0x0000000111cfa5ef UIKit`-[UITableView layoutSubviews] + 222
frame #6: 0x0000000111c61f50 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
frame #7: 0x00000001117a5cc4 QuartzCore`-[CALayer layoutSublayers] + 146
(lldb)


image 命令

列出当前 App 中的所有 module,可以查看某一个地址对应的代码位置。


image lookup -address

查找崩溃位置

0   CoreFoundation                      0x0000000103209b0b __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x00000001079db141 objc_exception_throw + 48
2   CoreFoundation                      0x000000010313effb -[__NSArrayM objectAtIndex:] + 203
3   DiDi                                0x00000001009a9f3a -[FW_MyHomeTableView tableView:cellForRowAtIndexPath:] + 1322
4   UIKit                               0x00000001055a2ab2 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 750
5   UIKit                               0x00000001055a2cf8 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
6   UIKit                               0x0000000105577639 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2845
7   UIKit                               0x00000001055abccc -[UITableView _performWithCachedTraitCollection:] + 111
8   UIKit                               0x0000000105592e7a -[UITableView layoutSubviews] + 233
9   UIKit                               0x00000001054f955b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
10  QuartzCore                          0x0000000105114904 -[CALayer layoutSublayers] + 146
image lookup -a 0x00000001009a9f3a
      Address: DiDi[0x0000000100609f3a] (DiDi.__TEXT.__text + 6323194)
      Summary: DiDi`-[FW_MyHomeTableView tableView:cellForRowAtIndexPath:] + 1322 at FW_MyHomeTableView.m:243

当遇到 crash 时,查看线程栈,只能看到栈帧的地址,使用 image lookup –address 地址 可以方便的定位到这个地址对应的代码行。


image lookup -name

查找方法来源。

(lldb) image lookup -n transformOtherModelToSuit:
1 match found in /Users/xxx/Library/Developer/Xcode/DerivedData/DiDi-cwpbvvyvqmeijmcjnneothzuthsy/Build/Products/Debug-iphonesimulator/DiDi.app/DiDi:
        Address: DiDi[0x0000000100293d60] (DiDi.__TEXT.__text + 2693664)
        Summary: DiDi`+[FW_BetFunction transformOtherModelToSuit:] at FW_BetFunction.m:107


image lookup –type

查看成员

(lldb) image lookup -t MatchEvent
1 match found in /Users/xxxx/Library/Developer/Xcode/DerivedData/DiDi-cwpbvvyvqmeijmcjnneothzuthsy/Build/Products/Debug-iphonesimulator/DiDi.app/DiDi:
id = {0x00433d32}, name = "MatchEvent", byte-size = 48, decl = MatchEvent.h:11, compiler_type = "@interface MatchEvent : NSObject{
    BOOL _isHome;
    NSString * _playerName;
    NSString * _timePoint;
    NSString * _eventType;
    NSString * _eventDesc;
}
@property ( getter = isHome,setter = setIsHome:,assign,readwrite,nonatomic ) BOOL isHome;
@property ( getter = playerName,setter = setPlayerName:,readwrite,copy,nonatomic ) NSString * playerName;
@property ( getter = timePoint,setter = setTimePoint:,readwrite,copy,nonatomic ) NSString * timePoint;
@property ( getter = eventType,setter = setEventType:,readwrite,copy,nonatomic ) NSString * eventType;
@property ( getter = eventDesc,setter = setEventDesc:,readwrite,copy,nonatomic ) NSString * eventDesc;
@end"


breakpoint

breakpoint set -f xxx -l xxx

(lldb) breakpoint set -f FW_ProfilesDetailModel.m -l 95
Breakpoint 3: where = DiDi`-[FW_ProfilesDetailModel incomeRate] + 27 at FW_ProfilesDetailModel.m:96, address = 0x0000000105b404bb


breakpoint set -n func name

(lldb) breakpoint set -n viewDidLoad
Breakpoint 4: 414 locations.

💡 Tips: 这里要说一下,xcode 其实也有函数名断点,不过用 breakpoint set -n 实现,比 xcode 下断点快 N 倍,不过 xcode 下的断点还给提示所有断到的位置。


breakpoint set -n "-[类名 方法名]"

(lldb) breakpoint set -n "-[FW_MyHomeViewController viewDidLoad]"
Breakpoint 8: where = DiDi`-[FW_MyHomeViewController viewDidLoad] + 20 at FW_MyHomeViewController.m:58, address = 0x0000000105aec944


breakpoint set -c "xxxx"

条件断点操作。

breakpoint set -f FW_HomeCell.m -l 362 -c "width > 68"
Breakpoint 5: where = DiDi`-[FW_HomeCell_HotBill setDataSource:] + 2006 at FW_HomeCell.m:363, address = 0x000000010d22e0a6


breakpoint list

查看断点列表。

(lldb) breakpoint list
Current breakpoints:
8: name = '-[FW_MyHomeViewController viewDidLoad]', locations = 1, resolved = 1, hit count = 2
  8.1: where = DiDi`-[FW_MyHomeViewController viewDidLoad] + 20 at FW_MyHomeViewController.m:58, address = 0x0000000105aec944, resolved, hit count = 2 
9: file = '/Users/xxxx/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, resolved, hit count = 0


breakpoint disable/enable

禁用/启用断点。

//禁用断点
(lldb) breakpoint disable 9
1 breakpoints disabled.
(lldb) breakpoint list
Current breakpoints:
9: file = '/Users/zmz/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1 Options: disabled 
  9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, unresolved, hit count = 0
//启用断点
(lldb) breakpoint enable 9
1 breakpoints enabled.
(lldb) breakpoint list
Current breakpoints:
9: file = '/Users/zmz/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, resolved, hit count = 0


breakpoint delete

删除断点。

(lldb) breakpoint delete 8
1 breakpoints deleted; 0 breakpoint locations disabled.
(lldb) breakpoint list
Current breakpoints:
9: file = '/Users/xxxx/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
 9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, resolved, hit count = 0


command alias

自定义别名。

(lldb) command alias see thread backtrace
(lldb) see 5
  thread #5
    frame #0: 0x000000010bd3544e libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x000000010bd69621 libsystem_pthread.dylib`_pthread_wqthread + 1426
    frame #2: 0x000000010bd6907d libsystem_pthread.dylib`start_wqthread + 13


command alias %1 %2

自定义别名带参数。

(lldb) command alias dlt breakpoint delete %1
(lldb) breakpoint list
Current breakpoints:
3: file = 'JSONKit.m', line = 725, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  3.1: where = TEST`-[JKArray dealloc] + 20 at JSONKit.m:727, address = 0x00000001073360c4, resolved, hit count = 0
(lldb) dlt 3
1 breakpoints deleted; 0 breakpoint locations disabled.

lldb 初始化时会读取 ~/.lldbinit 文件,可以把简写命令写进此文件中。


  1. 打开终端,输入 vi ~/.lldbinit 进入文件编辑。
  2. 写入自定义内容,如:command alias 堆栈 thread backtrace
  3. 然后 ESC 键,出现冒号后输入 wqenter 键保存并退出编辑。


menthods

打印当前对象的属性和方法。

(lldb) methods p1
<Person: 0x60000003eac0> : 
in Person:
    Properties:
        @property (copy, nonatomic) NSString* name; (@synthesize name = _name;) 
        @property (nonatomic) long age; (@synthesize age = _age; )
    Instance Methods:
        - (void) eat; (0x1098bf3e0)
        - (void) .cxx_destruct; (0x1098bf4fo)
        - (id) description; (0x1098bf410)
        - (id) name; (0x1098bf430)
(NSObject . . )


pachtion

打印对象调用者及方法。

(lldb) pactions 0x7fcdhsja212728
<ViewController: 0x7fcdhsja212728>: login:


pclass

打印对象继承关系。

pcalss s
Student
    | Preson
    |   | NSObject


presponder

打印响应者链。

(lldb) presponder 0x7ff1ab5a6770
<UIView: 0x7ff1ab5a6770; frame = (75 362; 123 96); autoresize = RM+BM; layer = <CALayer: 0x7ff1ab5a10a0>>
   | <UIView: 0x7ff1ab5a6660; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7ff1ab5a23c0>>
   |    | <test.ViewController: 0x7ff1ab6380a0>
   |    |    | <UIWindow: 0x7ff1ab411de0; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x7ff1ab409a20>; layer = <UIWindowLayer: 0x7ff1ab417a90>>
   |    |    |    | <UIApplication: 0x7ff1ab528330>
   |    |    |    |    | <test.AppDelegate: 0x7ff1ab40f050>


search

搜索栈内控件及其子控件。

search UIButton
<UIButton: 0x7fc373828111; frame = (0 0; 100 90);
opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x608000221060>>

lookup 搜索,可执行正则表达式。


目录
相关文章
|
存储 数据可视化 C语言
[iOS研习记]聊聊iOS中的Mach-O
Mach-O的全称为Mach Object,是OS X与iOS上的一种可执行文件格式。Mach本身指一种操作系统的微内核标准,被用于OS X与iOS系统的内核中。相信对于移动端的iOS开发者来说,对Mach-O文件一定不陌生,我们编译打包的iOS IPA文件,内部其实就有一个可执行的Mach-O文件,我们开发的framework和.a等动态库静态库中,也会包含Mach-O文件,本篇文章,我们就来详细看看Mach-O中究竟放的是什么,Mach-O的结构是怎样的。
974 0
|
11月前
|
物联网 5G 调度
|
9月前
|
自然语言处理 前端开发 Serverless
基于阿里云通义千问开发编程辅助与代码生成工具
随着软件开发需求的增加,编程辅助与代码生成工具成为开发者提高效率的利器。这类工具能够根据用户描述生成代码片段、协助调试、生成自动化脚本等,大大减少重复性劳动。阿里云通义千问作为一款先进的大语言模型,具备强大的自然语言处理和代码生成能力,非常适合用于开发这样的工具。
979 3
|
存储 负载均衡 Linux
【Linux 系统】进程间通信(匿名管道 & 命名管道)-- 详解(下)
【Linux 系统】进程间通信(匿名管道 & 命名管道)-- 详解(下)
|
12月前
|
数据采集 存储 监控
网络爬虫的最佳实践:结合 set_time_limit() 与 setTrafficLimit() 抓取云盘数据
本文探讨了如何利用 PHP 的 `set_time_limit()` 与爬虫工具的 `setTrafficLimit()` 方法,结合多线程和代理 IP 技术,高效稳定地抓取百度云盘的公开资源。通过设置脚本执行时间和流量限制,使用多线程提高抓取效率,并通过代理 IP 防止 IP 封禁,确保长时间稳定运行。文章还提供了示例代码,展示了如何具体实现这一过程,并加入了数据分类统计功能以监控抓取效果。
174 17
网络爬虫的最佳实践:结合 set_time_limit() 与 setTrafficLimit() 抓取云盘数据
|
12月前
|
算法 Java 关系型数据库
Java中到底有哪些锁
【9月更文挑战第24天】在Java中,锁主要分为乐观锁与悲观锁、自旋锁与自适应自旋锁、公平锁与非公平锁、可重入锁以及独享锁与共享锁。乐观锁适用于读多写少场景,通过版本号或CAS算法实现;悲观锁适用于写多读少场景,通过加锁保证数据一致性。自旋锁与自适应自旋锁通过循环等待减少线程挂起和恢复的开销,适用于锁持有时间短的场景。公平锁按请求顺序获取锁,适合等待敏感场景;非公平锁性能更高,适合频繁加解锁场景。可重入锁支持同一线程多次获取,避免死锁;独享锁与共享锁分别用于独占和并发读场景。
289 3
|
IDE 开发工具 Python
新一代数据科学ide平台DataSpell提前发行版体验
新一代数据科学ide平台DataSpell提前发行版体验
319 0
vcpkg安装软件包时自定义编译选项
vcpkg安装软件包时自定义编译选项
773 0
|
机器学习/深度学习 存储 API
GGML 非官方中文文档(2)
GGML 非官方中文文档
848 0
|
NoSQL 容器 消息中间件
rtsp-simple-server + srs搭建流媒体服务器
rtsp-simple-server + srs搭建流媒体服务器
1463 0