iOS之LLDB常用命令

LLDB是個開源的內(nèi)置于XCode的調(diào)試工具,這里來理一理常用用法。
lldb對于命令的簡稱,是頭部匹配方式,只要不混淆,你可以隨意簡稱某個命令。結(jié)果為在xcode下驗證所得,可能與其它平臺有所誤差。

1 打印值、修改值、調(diào)用方法

1.1 p、po 打印值

打印相關(guān)的命令有:p、po。
p 和 po 的區(qū)別在于使用 po 只會輸出對應(yīng)的值,而 p 則會返回值的類型以及命令結(jié)果的引用名。

(lldb) p width
(CGFloat) $10 = 70
(lldb) po width
70
(lldb) p endTime
(__NSCFString *) $14 = 0x0000608000437660 @"08-11 11:43"
(lldb) po endTime
08-11 11:43

對比結(jié)果:

po:輸出值
p:輸出值+值類型+引用名+內(nèi)存地址(xcode中有內(nèi)存地址,其它平臺不確定)

除此之外,p還隱藏了一個有意思的功能,常量的進制轉(zhuǎn)換:

//默認(rèn)打印為10進制
(lldb) p 100
(int) $8 = 100
//轉(zhuǎn)16進制
(lldb) p/x 100
(int) $9 = 0x00000064
//轉(zhuǎn)8進制
(lldb) p/o 100
(int) $10 = 0144
//轉(zhuǎn)二進制
(lldb) p/t 100
(int) $2 = 0b00000000000000000000000001100100
//字符轉(zhuǎn)10進制數(shù)字
(lldb) p/d 'A'
(char) $7 = 65
//10進制數(shù)字轉(zhuǎn)字符
(lldb) p/c 66
(int) $10 = B\0\0\0

1.2 expression 修改參數(shù)值

感覺exp命令是調(diào)試過程中最有價值有命令了,它可以打印值、修改值。

//expression打印值
(lldb) expression width
(CGFloat) $5 = 67
//expression修改值
(lldb) expression width = 80
(CGFloat) $6 = 80
//打印修改后結(jié)果
(lldb) p width
(CGFloat) $7 = 80
(lldb) 

expression:同樣可以輸出值+值類型+引用名,但其一般用于修改。

1.3 call 方法調(diào)用

在斷點調(diào)用某個方法,?并輸出此方法的返回值。

(lldb) call width
(CGFloat) $12 = 70
(lldb) call endTime
(__NSCFString *) $16 = 0x0000608000437660 @"08-11 11:43"

call:同樣為輸出值+值類型+引用名

2 Thread

2.1 堆棧打印 thread backtrace

如果嫌堆棧打印太長,可以加一個值限制,如bt 10,只打印

(lldb) bt 10
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x00000001005e4906 DiDi`-[FW_HomeCell_HotBill setDataSource:](self=0x00007fd3938a7800, _cmd="setDataSource:", dataSource=0x00006080001c8bb0) at FW_HomeCell.m:357
    frame #1: 0x00000001009a9fd7 DiDi`-[FW_MyHomeTableView tableView:cellForRowAtIndexPath:](self=0x00007fd3921fec00, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007fd3921fec00, indexPath=0xc000000000000316) at FW_MyHomeTableView.m:247
    frame #2: 0x00000001055a2ab2 UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 750
    frame #3: 0x00000001055a2cf8 UIKit`-[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
    frame #4: 0x0000000105577639 UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 2845
    frame #5: 0x00000001055abccc UIKit`-[UITableView _performWithCachedTraitCollection:] + 111
    frame #6: 0x0000000105592e7a UIKit`-[UITableView layoutSubviews] + 233
    frame #7: 0x00000001054f955b UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
    frame #8: 0x0000000105114904 QuartzCore`-[CALayer layoutSublayers] + 146
    frame #9: 0x0000000105108526 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 370

2.2 thread return 跳出當(dāng)前方法的執(zhí)行

Debug的時候,也許會因為各種原因,我們不想讓代碼執(zhí)行某個方法,或者要直接返回一個想要的值。這時候就該thread return上場了。
有返回值的方法里,如:numberOfSectionsInTableView:,直接thread return 10,就可以直接跳過方法執(zhí)行,返回10.

//跳出方法
(lldb) thread return
//讓帶有返回int值的方法直接跳出,并返回值10
(lldb) thread return 10

2.3 流程控制

實際上使用xcode自帶的可視化工具來控制“繼續(xù)”“暫停”“下一步”“進入”“跳出”更簡單

繼續(xù):continue, c
下一步:next, n
進入:step, s
跳出:finish, f

2.4 跳幀 frame select N

2.1中打印有10幀,如果我想跳轉(zhuǎn)到第1幀:frame select 1

(lldb) frame select 1
frame #1: 0x0000000105e91c3c DiDi`-[FW_HomeViewController tableView:cellForRowAtIndexPath:](self=0x00007fbf9f73b410, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007fbfa11dc400, indexPath=0xc000000000a00316) at FW_HomeViewController.m:597
   594                  break;
   595                  
   596                  case 3: {
-> 597                      cell.?[4md?[0mataSource = _hotBills[indexPath.row];
   598                      cell.textSelect = ^(UITextField *text) {
   599                          weakSelf.curruntText = text;
   600                      };

2.5 查看幀變量 frame variable

(lldb) frame variable
(FW_HomeViewController *) self = 0x00007faccbf587d0
(SEL) _cmd = "tableView:cellForRowAtIndexPath:"
(UITableView *) tableView = 0x00007faccd09b400
(NSIndexPath *) indexPath = 0xc000000000000316
(FW_HomeViewController *) weakSelf = 0x00007faccbf587d0
(FW_HomeCell_HotBill *) cell = 0x00007faccc101a00
(UIView *) model = 0x00007fff52c13d90
(FW_HomeCell_HotBill *) billCell = 0x00000001124e99f6

3 Image

3.1 image lookup -address 查找崩潰位置

當(dāng)你遇見數(shù)組崩潰,你又沒有找到崩潰的位置,只扔給你一堆報錯信息,這時候image lookup來幫助你。如下

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

尋找自己項目的標(biāo)識,看到frame3位置,你只需這樣查找位置:

image lookup -a 0x00000001009a9f3a
      Address: DiDi[0x0000000100609f3a] (DiDi.__TEXT.__text + 6323194)
      Summary: DiDi`-[FW_MyHomeTableView tableView:cellForRowAtIndexPath:] + 1322 at FW_MyHomeTableView.m:243

項目中FW_MyHomeTableView.m:243,perfect!

3.2 image lookup -name 查找方法來源

此命令可以用來查找方法的來源。包括在第三方SDK中的方法,也能被查到。
例:查找transformOtherModelToSuit:

(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

3.3 image lookup –type 查看成員

查看某個class的所有屬性和成員變量。不過貌似frameWork庫中文件不能查看。

(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"

4 breakpoint

4.1 文件名+行號 breakpoint set -f xxx -l xxx

我們平時操作xcode,在某一行點下斷點,其實操作的就是這個命令。

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

4.2 函數(shù)名斷點

4.2.1 方法名斷點 breakpoint set -n 方法名
(lldb) breakpoint set -n viewDidLoad
Breakpoint 4: 414 locations.

Tips:這里要說一下,xcode其實也有函數(shù)名斷點,不過用breakpoint set -n實現(xiàn),比xcode下斷點快N倍,不過xcode下的斷點還給提示所有斷到的位置。

viewDidLoad斷點
4.2.2 類中方法斷點 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

注意:-[FW_MyHomeViewController viewDidLoad],外面一定要加雙引號,不然會誤識別為-[FW_MyHomeViewController`

4.3 條件斷點 breakpoint ?set -c "xxxx"

和xcode中symbolic Breakpoint功能相同,我在FW_HomeCell.m 362行下斷點,但又想過濾僅width>68的狀態(tài),操作如下:

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

4.4 查看斷點列表 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 

4.5 禁用/啟用斷點 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 

4.6 移除斷點 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 

5 別名

其實很多命令是LLDB一些命令的別名,比如p是frame variable的別名,p view實際上是frame variable view。除了系統(tǒng)自建的LLDB別名,你也可以自定義別名。

5.1 自定義別名 command alias

很多時候,LLDB完整的命令是很長的。比如前面所說的image lookup --address這個組合命令。為了方便日常的使用,提高效率,LLDB命令也提供通過簡稱的方式調(diào)用命令。
為了說明問題,我來個奇葩的,中文定義!!!

(lldb) command alias 查看堆棧 thread backtrace
(lldb) 查看堆棧 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

5.2 帶參數(shù)別名 command alias %1 %2等等

(lldb) command alias 刪除斷點 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) 刪除斷點 3
1 breakpoints deleted; 0 breakpoint locations disabled.

雖然我用了中文命名,但不要學(xué)習(xí)我哦,這里只是為了說明命名不只支持英文的問題。
而且,命名盡量符合簡寫規(guī)律,這樣更有利于使用。如help command alias中給出的例子:

(lldb) command alias bpl breakpoint list
(lldb) command alias bfl breakpoint set -f %1 -l %2

5.3 持久存儲

我們在xcode下打command alias,在下次項目運行時直接就沒了,有個辦法可以做到持久存儲。lldb初始化時會讀取~/.lldbinit文件,我們可以把簡寫命令寫進此文件中。

添加步驟:
  1. 打開終端,輸入vi ~/.lldbinit進入文件編輯。
  2. 寫入自定義內(nèi)容,如:command alias 堆棧 thread backtrace
  3. 然后ESC鍵,出現(xiàn)冒號后輸入wqenter鍵保存并退出編輯。

Xcode中斷點使用

xcode中斷點其實是對lldb的一個界面化,確實使用起來特別方便。
但有一點不同:使用lldb添加的斷點,下次運行時就失效了,而xcode中設(shè)置的斷點仍然正常使用

示例

1. 條件斷點
條件斷點
2. 添加斷點事件

我們項目中就有一個使用場景:用戶想要發(fā)貼,會先請求一個接口,返回用戶是否有發(fā)帖權(quán)限。有權(quán)限跳轉(zhuǎn)發(fā)帖頁,無權(quán)限跳轉(zhuǎn)無權(quán)限提示頁。所以我們在debug的時候,就會在返回值isHasPermisson那里添加一個斷點,action中把值改為1,勾選自動繼續(xù)。如下圖:

image.png

執(zhí)行結(jié)果:

image.png

通過添加斷點,可以做到偷偷改動斷點處的一個參數(shù)值,避免修改代碼,或者頻繁手動exp修改值,簡直是方便。

結(jié)語:

有了這些命令,調(diào)試起來肯定就得心應(yīng)手了。總結(jié)下常用的,供多看幾遍加深回憶:

堆棧相關(guān):bt查看堆棧、frame select跳幀、frame variable查看幀參數(shù)、thread return跳出當(dāng)前執(zhí)行、【step/finish/next/continue】進入/跳出/下一步/跳出本斷點

斷點相關(guān):breakpoint set -f -l -c條件斷點、breakpoint set -n方法斷點、breakpoint delete斷點移除、breakpoint list斷點列表

image命令:image lookup -address崩潰定位、image lookup -name方法來源、 image lookup –type 查看成員

LLDB支持簡寫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內(nèi)容

  • LLDB的Xcode默認(rèn)的調(diào)試器,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測的調(diào)試功能。平時用Xc...
    CoderSC閱讀 1,374評論 0 2
  • [轉(zhuǎn)]淺談LLDB調(diào)試器文章來源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,541評論 2 6
  • LLDB的Xcode默認(rèn)的調(diào)試器,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測的調(diào)試功能。平時用Xc...
    小笨狼閱讀 20,522評論 31 187
  • 隨著Xcode 5的發(fā)布,LLDB調(diào)試器已經(jīng)取代了GDB,成為了Xcode工程中默認(rèn)的調(diào)試器。它與LLVM編譯器一...
    隨風(fēng)飄蕩的小逗逼閱讀 1,409評論 0 0
  • 古典美女,當(dāng)我第一次看到這樣照片時候,不管從她的打扮,還她的衣服色彩,非常好看非常美,但是過了很久我才開始畫這幅畫...
    燁然v閱讀 384評論 0 2