高效LLDB调试技巧

ps:本文为以前学些是学习所记笔记,原文链接已经丢失,在此发表为以后查阅方便,如有侵权请作者联系我,会马上删除。

LLDB命令还是不少的,但有些都集成在Xcode的图形化界面中,没必要再去手动操作,这里主要说一下使用起来更加高效的一些命令。

help

和大多数命令一样,help命令会显示出所有的命令列表,对于相关的操作可以直接查看。若想查看某一条命令的话,直接在help后面加上对应的命令名称。如:

Objective-C

1

helpprint

p & call & po

先说p和call,二者都是expression —的别名, p为print的简写,同时可以写为pri,打印某个东西,可以i是变量和表达式;call为调用某个方法,输出变量也是可以的。

po一般用于打印对象,是expression -O —的别名。

p和po的区别在于使用po只会输出对应的值,而p则会返回值的类型以及命令结果的引用名。如:

Objective-C

1

2

3

4

5

6

7

8(lldb)pself.model.number

(float) $4=98

(lldb)pself.model.name

(NSString *) $5=nil

(lldb)poself.model.number

98

(lldb)poself.model.words

Hello

expression

expression命令的作用是执行一个表达式,并将表达式返回的结果输出。expression的完整语法是这样的:

Objective-C

1

expression --

:命令选项,一般情况下使用默认的即可,不需要特别标明。

–:命令选项结束符,表示所有的命令选项已经设置完毕,如果没有命令选项,–可以省略。

:要执行的表达式

说expression是LLDB里面最重要的命令都不为过。因为他能实现2个功能。

执行某个表达式。我们在代码运行过程中,可以通过执行某个表达式来动态改变程序运行的轨迹。假如我们在运行过程中,突然想把self.view颜色改成红色,看看效果。我们不必写下代码,重新run,只需暂停程序,用expression改变颜色,再刷新一下界面,就能看到效果

Objective-C

1

2

3

4// 改变颜色

(lldb)expression--self.view.backgroundColor=[UIColorredColor]

// 刷新界面

(lldb)expression--(void)[CATransactionflush]

将返回值输出。也就是说我们可以通过expression来打印东西。假如我们想打印self.view:

Objective-C

1

2(lldb)expression--self.view

(UIView *) $1=0x00007fe322c18a10

thread

backtrace & bt

此命令一般用于将线程的堆栈打印出来,一般在程序出现crash的时候调用。如;

Objective-C

1

2

3

4

5

6

7

8

9(lldb)threadbacktrace

*thread#1: tid = 0xdd42, 0x000000010afb380b libobjc.A.dylib`objc_msgSend + 11, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

frame#0: 0x000000010afb380b libobjc.A.dylib`objc_msgSend + 11

*frame#1: 0x000000010aa9f75e TLLDB`-[ViewController viewDidLoad](self=0x00007fa270e1f440, _cmd="viewDidLoad") + 174 at ViewController.m:23

frame#2: 0x000000010ba67f98 UIKit`-[UIViewController loadViewIfRequired] + 1198

frame#3: 0x000000010ba682e7 UIKit`-[UIViewController view] + 27

frame#4: 0x000000010b93eab0 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 61

frame#5: 0x000000010b93f199 UIKit`-[UIWindow _setHidden:forced:] + 282

frame#6: 0x000000010b950c2e UIKit`-[UIWindow makeKeyAndVisible] + 42

bt为thread backtrace的别名,直接使用bt和使用上面那一长串是一个效果。

thread return

Debug的时候,也许会因为各种原因,我们不想让代码执行某个方法,或者要直接返回一个想要的值。这时候就该thread return上场了。

Objective-C

1

threadreturn[]

thread return可以接受一个表达式,调用命令之后直接从当前的堆栈中返回表达式的值。

e.g:我们有一个someMethod方法,默认情况下是返回YES。我们想要让他返回NO

我们只需在方法的开始位置加一个断点,当程序中断的时候,输入命令即可:

Objective-C

1

(lldb)threadreturnNO

效果相当于在断点位置直接调用*return NO; *,不会执行断点后面的代码.

target

对于target这个命令,我们用得最多的可能就是target modules lookup。由于LLDB给target modules取了个别名*image *,所以这个命令我们又可以写成*image lookup *。

image lookup –address

当我们有一个地址,想查找这个地址具体对应的文件位置,可以使用image lookup –address,简写为image lookup -a。e.g:当我们发生一个crash

Objective-C

1

2

3

4

5

6

7

8

9***Terminatingapp due to uncaughtexception'NSRangeException',reason:'*** -[__NSArray0 objectAtIndex:]: index 1 beyond bounds for empty NSArray'

***Firstthrowcall stack:

(

0CoreFoundation0x000000010accde65__exceptionPreprocess+165

1libobjc.A.dylib0x000000010a746debobjc_exception_throw+48

2CoreFoundation0x000000010ac7c395-[__NSArray0 objectAtIndex:]+101

3TLLDB0x000000010a1c3e36-[ViewControllerviewDidLoad]+86

4UIKit0x000000010b210f98-[UIViewControllerloadViewIfRequired]+1198

5UIKit0x000000010b2112e7-[UIViewControllerview]+27

我们可以看到是由于-[__NSArray0 objectAtIndex:]:超出边界而导致的crash,但是objectAtIndex:的代码到底在哪儿呢?

Objective-C

1

2

3(lldb)imagelookup-a0x000000010a1c3e36

Address: TLLDB[0x0000000100000e36] (TLLDB.__TEXT.__text+246)

Summary: TLLDB`-[ViewControllerviewDidLoad]+86atViewController.m:32

根据0x000000010a1c3e36 -[ViewController viewDidLoad]里面的地址,使用image lookup –address查找,我们可以看到代码位置在ViewController.m里面的32行。

image lookup –name

当我们想查找一个方法或者符号的信息,比如所在文件位置等。我们可以使用image lookup –name,简写为*image lookup -n *。

e.g:刚刚遇到的真问题,某个第三方SDK用了一个我们项目里原有的第三方库,库里面对NSDictionary添加了category。也就是有2个class对NSDictionary添加了名字相同的category,项目中调用自己的category的地方实际走到了第三方SDK里面去了。最大的问题是,这2个同名category方法行为并不一致,导致出现bug

现在问题来了,怎么寻找到底是哪个第三方SDK?方法完全包在.a里面。

其实只需使用image lookup -n即可:

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28(lldb)imagelookup-ndictionaryWithXMLString:

2matches foundin/Users/jiangliancheng/Library/Developer/Xcode/DerivedData/VideoIphone-aivsnqmlwjhxapdlvmdmrubbdxpq/Build/Products/Debug-iphoneos/BaiduIphoneVideo.app/BaiduIphoneVideo:

Address: BaiduIphoneVideo[0x00533a7c] (BaiduIphoneVideo.__TEXT.__text+5414908)

Summary: BaiduIphoneVideo`+[NSDictionary(SAPIXmlDictionary)dictionaryWithXMLString:]atXmlDictionary.m

Module: file="/Users/jiangliancheng/Library/Developer/Xcode/DerivedData/VideoIphone-aivsnqmlwjhxapdlvmdmrubbdxpq/Build/Products/Debug-iphoneos/BaiduIphoneVideo.app/BaiduIphoneVideo",arch="armv7"

CompileUnit: id={0x00000000},file="/Users/jiangliancheng/Development/Work/iOS_ShareLib/SharedLib/Srvcs/BDPassport4iOS/BDPassport4iOS/SAPI/Extensive/ThirdParty/XMLDictionary/XmlDictionary.m",language="Objective-C"

Function: id={0x23500000756},name="+[NSDictionary(SAPIXmlDictionary) dictionaryWithXMLString:]",range=[0x005a6a7c-0x005a6b02)

FuncType: id={0x23500000756},decl=XmlDictionary.m:189,clang_type="NSDictionary *(NSString *)"

Blocks: id={0x23500000756},range=[0x005a6a7c-0x005a6b02)

LineEntry:[0x005a6a7c-0x005a6a98): /Users/jiangliancheng/Development/Work/iOS_ShareLib/SharedLib/Srvcs/BDPassport4iOS/BDPassport4iOS/SAPI/Extensive/ThirdParty/XMLDictionary/XmlDictionary.m

Symbol: id={0x0000f2d5},range=[0x005a6a7c-0x005a6b04),name="+[NSDictionary(SAPIXmlDictionary) dictionaryWithXMLString:]"

Variable: id={0x23500000771},name="self",type="Class",location=[sp+32],decl=

Variable: id={0x2350000077e},name="_cmd",type="SEL",location=[sp+28],decl=

Variable: id={0x2350000078b},name="string",type="NSString *",location=[sp+24],decl=XmlDictionary.m:189

Variable: id={0x23500000799},name="data",type="NSData *",location=[sp+20],decl=XmlDictionary.m:192

Address: BaiduIphoneVideo[0x012ee160] (BaiduIphoneVideo.__TEXT.__text+19810016)

Summary: BaiduIphoneVideo`+[NSDictionary(XMLDictionary)dictionaryWithXMLString:]atXMLDictionary.m

Module: file="/Users/jiangliancheng/Library/Developer/Xcode/DerivedData/VideoIphone-aivsnqmlwjhxapdlvmdmrubbdxpq/Build/Products/Debug-iphoneos/BaiduIphoneVideo.app/BaiduIphoneVideo",arch="armv7"

CompileUnit: id={0x00000000},file="/Users/wingle/Workspace/qqlive4iphone/iphone_4.0_fabu_20150601/Common_Proj/mobileTAD/VIDEO/Library/Third Party/XMLDictionary/XMLDictionary.m",language="Objective-C"

Function: id={0x79900000b02},name="+[NSDictionary(XMLDictionary) dictionaryWithXMLString:]",range=[0x01361160-0x0136119a)

FuncType: id={0x79900000b02},decl=XMLDictionary.m:325,clang_type="NSDictionary *(NSString *)"

Blocks: id={0x79900000b02},range=[0x01361160-0x0136119a)

LineEntry:[0x01361160-0x01361164): /Users/wingle/Workspace/qqlive4iphone/iphone_4.0_fabu_20150601/Common_Proj/mobileTAD/VIDEO/Library/Third Party/XMLDictionary/XMLDictionary.m

Symbol: id={0x0003a1e9},range=[0x01361160-0x0136119c),name="+[NSDictionary(XMLDictionary) dictionaryWithXMLString:]"

Variable: id={0x79900000b1e},name="self",type="Class",location=r0,decl=

Variable: id={0x79900000b2c},name="_cmd",type="SEL",location=r1,decl=

Variable: id={0x79900000b3a},name="string",type="NSString *",location=r2,decl=XMLDictionary.m:325

Variable: id={0x79900000b4a},name="data",type="NSData *",location=r2,decl=XMLDictionary.m:327

东西有点多,我们只需关注里面的file这一行:

Objective-C

1

2CompileUnit: id={0x00000000},file="/Users/jiangliancheng/Development/Work/iOS_ShareLib/SharedLib/Srvcs/BDPassport4iOS/BDPassport4iOS/SAPI/Extensive/ThirdParty/XMLDictionary/XmlDictionary.m",language="Objective-C"

CompileUnit: id={0x00000000},file="/Users/wingle/Workspace/qqlive4iphone/iphone_4.0_fabu_20150601/Common_Proj/mobileTAD/VIDEO/Library/Third Party/XMLDictionary/XMLDictionary.m",language="Objective-C"

可以清晰的看到,LLDB给我们找出来了这个方法的位置。当然这个命令也可以找到方法的其他相关信息,比如参数等.

image lookup –type

当我们想查看一个类型的时候,可以使用image lookup –type,简写为image lookup -t:

e.g:我们来看看Model的类型:

Objective-C

1

2

3

4

5

6

7

8

9

10(lldb)imagelookup-tModel

Bestmatch foundin/Users/jiangliancheng/Library/Developer/Xcode/DerivedData/TLLDB-beqoowskwzbttrejseahdoaivpgq/Build/Products/Debug-iphonesimulator/TLLDB.app/TLLDB:

id={0x30000002f},name="Model",byte-size=32,decl=Modek.h:11,clang_type="@interface Model : NSObject{

NSString * _bb;

NSString * _cc;

NSString * _name;

}

@property ( getter = name,setter = setName:,readwrite,nonatomic ) NSString * name;

@end

"

可以看到,LLDB把Model这个class的所有属性和成员变量都打印了出来,当我们想了解某个类的时候,直接使用image lookup -t即可。

其他

可以直接使用LLDB打开模拟器位置:

Objective-C

1

2

3(lldb)poNSHomeDirectory()

/Users/mfw/Library/Developer/CoreSimulator/Devices/EAFE74A5-4C53-42CE-8B40-141380D73A6D/data/Containers/Data/Application/B4C48D8B-BD8B-4246-B9D7-15FEC3CA8662

(lldb)platform shellopen/Users/mfw/Library/Developer/CoreSimulator/Devices/EAFE74A5-4C53-42CE-8B40-141380D73A6D/data/Containers/Data/Application/B4C48D8B-BD8B-4246-B9D7-15FEC3CA8662

常用的Debug快捷键

debug的时候,使用快捷键是一个很好的习惯,我简单列举了几个debug的快捷键

功能

命令

暂停/继续

cmd + ctrl + Y

断点失效/生效

cmd + Y

控制台显示/隐藏

cmd + shift + Y

光标切换到控制台

cmd + shift + C

清空控制台

cmd + K

step over

F6

step into

F7

step out

F8

工程导航器

Command+1

显示/隐藏导航器面板

Command+0

显示/隐藏实用工具面板

Command+Option+0

打开Assistant Editor

项目导航器中选中文件执行Option+左键点击操作

展示方法列表

Control+6(键入方法/变量名+Enter跳转

快速打开

Command + Shift + O

文档和参考

Command + Shift + 0

快速帮助

在类或者方法名上执行Option + Left-click操作

展示当前你在工程导航器中打开的文件

Command + Shift + J

迷你窗口,可任意选择位置

Command + Option + Shift + Left-click

End

这是我比较常用的一些命令,不全但是有效,像那些breakpoint的功能,若不是使用lldb调试可执行文件的话,直接使用Xcode的功能效果会更加显著一些。若想使用一些高级命令,可结合python脚本使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • LLDB的Xcode默认的调试器,它与LLVM编译器一起,带给我们更丰富的流程控制和数据检测的调试功能。平时用Xc...
    CoderSC阅读 1,346评论 0 2
  • [转]浅谈LLDB调试器文章来源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc阅读 2,480评论 2 6
  • 一、expression expression命令的作用是执行一个表达式,并将表达式返回的结果输出。express...
    boundlessocean阅读 1,022评论 0 2
  • 随着Xcode 5的发布,LLDB调试器已经取代了GDB,成为了Xcode工程中默认的调试器。它与LLVM编译器一...
    随风飘荡的小逗逼阅读 1,398评论 0 0
  • 大学时没有选好专业,以至于到现在我都对英语耿耿于怀,今天来这边的教学楼背书,看到正在上英语课的同学,不知道我...
    肖肖Anna阅读 199评论 0 0