ps:本文为之前学些是学习所记笔记,原文连接已经丢失,在此发表为之后查阅方便,若有侵权请做者联系我,会立刻删除。python
LLDB 命令仍是很多的,但有些都集成在 Xcode 的图形化界面中,不必再去手动操做,这里主要说一下使用起来更加高效的一些命令。shell
helpexpress
和大多数命令同样,help 命令会显示出全部的命令列表,对于相关的操做能够直接查看。 若想查看某一条命令的话,直接在 help 后面加上对应的命令名称。如:app
Objective-Ciphone
1ide |
help print工具 |
p & call & po学习
先说 p 和 call, 两者都是 expression — 的别名, p 为 print 的简写,同时能够写为 pri,打印某个东西,能够i是变量和表达式; call 为调用某个方法,输出变量也是能够的。ui
po 通常用于打印对象,是 expression -O — 的别名。atom
p 和 po 的区别在于使用 po 只会输出对应的值,而 p 则会返回值的类型以及命令结果的引用名。如:
Objective-C
1 2 3 4 5 6 7 8 |
(lldb) p self.model.number (float) $4 = 98 (lldb) p self.model.name (NSString *) $5 = nil (lldb) po self.model.number 98 (lldb) po self.model.words Hello |
expression
expression 命令的做用是执行一个表达式,并将表达式返回的结果输出。expression的完整语法是这样的:
Objective-C
1 |
expression <cmd-options> -- <expr> |
说 expression 是LLDB里面最重要的命令都不为过。由于他能实现2个功能。
1 2 3 4 |
// 改变颜色 (lldb) expression -- self.view.backgroundColor = [UIColor redColor] // 刷新界面 (lldb) expression -- (void)[CATransaction flush] |
将返回值输出。 也就是说咱们能够经过expression来打印东西。 假如咱们想打印 self.view:
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) thread backtrace * 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上场了。
1 |
thread return [<expr>] |
thread return能够接受一个表达式,调用命令以后直接从当前的堆栈中返回表达式的值。
e.g: 咱们有一个 someMethod 方法,默认状况下是返回YES。咱们想要让他返回NO
1 |
(lldb) thread return NO |
效果至关于在断点位置直接调用 *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 |
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 1 beyond bounds for empty NSArray' *** First throw call stack: ( 0 CoreFoundation 0x000000010accde65 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x000000010a746deb objc_exception_throw + 48 2 CoreFoundation 0x000000010ac7c395 -[__NSArray0 objectAtIndex:] + 101 3 TLLDB 0x000000010a1c3e36 -[ViewController viewDidLoad] + 86 4 UIKit 0x000000010b210f98 -[UIViewController loadViewIfRequired] + 1198 5 UIKit 0x000000010b2112e7 -[UIViewController view] + 27 |
咱们能够看到是因为-[__NSArray0 objectAtIndex:]:超出边界而致使的crash,可是objectAtIndex:的代码到底在哪儿呢?
Objective-C
1 2 3 |
(lldb) image lookup -a 0x000000010a1c3e36 Address: TLLDB[0x0000000100000e36] (TLLDB.__TEXT.__text + 246) Summary: TLLDB`-[ViewController viewDidLoad] + 86 at ViewController.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) image lookup -n dictionaryWithXMLString: 2 matches found in /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:] at XmlDictionary.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:] at XMLDictionary.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 2 |
CompileUnit: 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) image lookup -t Model Best match found in /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) po NSHomeDirectory() /Users/mfw/Library/Developer/CoreSimulator/Devices/EAFE74A5-4C53-42CE-8B40-141380D73A6D/data/Containers/Data/Application/B4C48D8B-BD8B-4246-B9D7-15FEC3CA8662 (lldb) platform shell open /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 脚本使用。