工具篇-LLDB 調(diào)試器

LLDB (Low Level Debugger) 輕量級高性能調(diào)試器曲尸,掌握 LLDB 可以有效的提升 Debug 能力,提高工作效率瓣俯。

一肋乍、常用命令

對象操作 (p/po/e/call)

NSArray *array = @[@"a", @"b", @"b", @"c"];

//(lldb) p array
//(__NSArray0 *) $3 = 0x00007fff8db5c830 @"0 elements"
//(lldb) p array = @[@"a"]
//(__NSSingleObjectArrayI *) $4 = 0x00000001005013b0 @"1 element"

// (lldb) po array
//<__NSArrayI 0x1006022f0>(
//a,
//b,
//b,
//c
//)

ZSan *zsan  = [[ZSan alloc] init];
zsan->_no   = 1;

//(lldb) e zsan->_no = 2;
// (int) $2 = 2

lldbp 打印對象的描述信息俊马,包括類型,指針地址等信息肩杈;po 打印的是對象的詳細信息柴我。

po 同時也可以修改對象信息,e 可以修改對象中屬性的值扩然,call 可以讓對象執(zhí)行方法艘儒。

p/po/e/call 都可以打印對象的信息。

函數(shù)操作 (bt/frame/image)

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 斷點處
        NSArray *array = @[@"a", @"b", @"b", @"c"];
    }
    return 0;
}
//  (lldb) bt
//  * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
//      * frame #0: 0x0000000100000d58 BLBaseNSObject`main(argc=1, argv=0x00007ffeefbff4f8) at main.m:122:22
//        frame #1: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//        frame #2: 0x00007fff6c55e7fd libdyld.dylib`start + 1

//(lldb) frame select 0
//frame #0: 0x0000000100000d58 BLBaseNSObject`main(argc=1, argv=0x00007ffeefbff4f8) at main.m:122:22
//   119
//   120             NSArray *array = @[@"a", @"b", @"b", @"c"];
//   121
//-> 122             NSLog(@"%@", array);
//                             ^
//   123         }
//   124         return 0;
//   125     }

bt(backtrace) 打印當前調(diào)用堆棧(crash堆棧)与学;frame 打印函數(shù)調(diào)用詳情以及調(diào)用順序彤悔;image 打印棧地址對應的代碼。

frame selecte 0 可以查看當前函數(shù)調(diào)用的信息索守,通過 updown 可以追蹤函數(shù)的調(diào)用和被調(diào)用關(guān)系晕窑。

frame variable 很方便的查方法的調(diào)用者及方法名稱。

image lookup -a 地址 這個方法主要用于尋址卵佛,常用與在崩潰的時候杨赤,查找崩潰地址對應的文件代碼的位置。

當項目遇到崩潰的時候同時利用 btimage loopup -a 地址 可以更好的找到問題截汪。

屬性&變量操作 (watchpoint)

有時候我們開發(fā)過程中會遇到類似的問題疾牲,有一些屬性或者變量值發(fā)生了變化,但是不知道具體是哪里開始發(fā)生的變化衙解,導致最后的結(jié)果與我們預期有了出入阳柔。

這里就可以使用 watchpoint 來監(jiān)聽我們的屬性或者變量。

ZSan *zsan  = [[ZSan alloc] init];
zsan.ccc    = 10;
zsan.ccc    = 1000;

//(lldb) watchpoint set variable zsan->_ccc
//Watchpoint created: Watchpoint 1: addr = 0x100555c30 size = 4 state = enabled type = w
//    declare @ '/Users/Charlyliu/Desktop/學習項目/OC/BLBaseNSObject/BLBaseNSObject/main.m:108'
//    watchpoint spec = 'zsan->_ccc'
//    new value: 0
//
//Watchpoint 1 hit:
//old value: 0
//new value: 10
//(lldb) pt
//error: 'pt' is not a valid command.
//(lldb) bt
//* thread #1, queue = 'com.apple.main-thread', stop reason = watchpoint 1
//  * frame #0: 0x0000000100001a70 BLBaseNSObject`-[ZSan setCcc:](self=0x0000000100555c10, _cmd="setCcc:", ccc=10) at main.m:60:35
//    frame #1: 0x0000000100001c69 BLBaseNSObject`main(argc=1, argv=0x00007ffeefbff4f8) at main.m:114:14
//    frame #2: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//    frame #3: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//(lldb) n
//(lldb) bt
//* thread #1, queue = 'com.apple.main-thread', stop reason = step over
//  * frame #0: 0x0000000100001c69 BLBaseNSObject`main(argc=1, argv=0x00007ffeefbff4f8) at main.m:120:111
//    frame #1: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//    frame #2: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//(lldb) c
//Process 36061 resuming
//2019-12-27 13:40:11.600731+0800 BLBaseNSObject[36061:1628481] 測試多層繼承關(guān)系成員變量大小的內(nèi)存對齊邏輯---40
//2019-12-27 13:40:11.601062+0800 BLBaseNSObject[36061:1628481] 測試多層繼承關(guān)系內(nèi)存分配---48
//
//Watchpoint 1 hit:
//old value: 10
//new value: 1000
//(lldb) bt
//* thread #1, queue = 'com.apple.main-thread', stop reason = watchpoint 1
//  * frame #0: 0x0000000100001a70 BLBaseNSObject`-[ZSan setCcc:](self=0x0000000100555c10, _cmd="setCcc:", ccc=1000) at main.m:60:35
//    frame #1: 0x0000000100001cd5 BLBaseNSObject`main(argc=1, argv=0x00007ffeefbff4f8) at main.m:123:14
//    frame #2: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//    frame #3: 0x00007fff6c55e7fd libdyld.dylib`start + 1
//(lldb) image lookup 0x0000000100001a70
//error: invalid combination of options for the given command
//(lldb) image lookup -a 0x0000000100001a70
//      Address: BLBaseNSObject[0x0000000100001a70] (BLBaseNSObject.__TEXT.__text + 64)
//      Summary: BLBaseNSObject`-[ZSan setCcc:] + 32 at main.m:60:35
//(lldb) 
  • watchpoint set variable zsan->_ccc 注意蚓峦,這里的 zsan->_ccc 不能使用點語法舌剂,這條命令主要是監(jiān)聽屬性地址,如果其地址內(nèi)保存的值發(fā)生變化就會走進斷點暑椰,而點語法實際上是調(diào)用的 getter 方法霍转。
  • watchpoint set variable testInt 設(shè)置變量觀察,testInt變量發(fā)生改變后觸發(fā)一汽。
  • watchpoint set expression -- 0x000000010f46c070 設(shè)置內(nèi)存觀察避消。
  • watchpoint list / watch l 當前所有觀察列表。
  • watchpoint modify -c 'testInt == 2' 設(shè)置條件觸發(fā)觀察召夹。
  • watchpoint delete 2 刪除對應的觀察岩喷。

這里我們可以配合 bt 堆棧信息使用,當發(fā)現(xiàn)值變化的時候可以查閱堆棧信息定位修改代碼的位置监憎。

內(nèi)存操作 (memory/x {read/write})

ZSan *zsan  = [[ZSan alloc] init];
zsan->_no   = 1;
zsan->_num  = 1;
zsan->_age  = 18;

//(lldb) memory read zsan
//0x1007009a0: 21 23 00 00 01 80 1d 00 01 00 00 00 01 00 00 00  !#..............
//0x1007009b0: 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
// 表示修改 0x1007009a8 后的值纱意,將其值修改為 4;根據(jù)剛才獲取內(nèi)存信息可知枫虏,從 0x1007009a8 地址之后是 _no 的值妇穴,值位 0x01爬虱,這里我們將其修改成為 0x04,也就是 zsan->_no = 4
//(lldb) memory write 0x1007009a8 4 
//(lldb) po zsan->_no
//4

memory read 可以用 x 代替腾它,使用起來更方便跑筝,用法 memory read/數(shù)量格式字節(jié)數(shù) 讀取對象/或某個具體的內(nèi)存地址 或者 x/數(shù)量格式字節(jié)數(shù) 讀取對象/或某個具體的內(nèi)存地址

/ 后各個字段描述:

  • 數(shù)量瞒滴,表示讀取從該對象起始地址或該內(nèi)存地址起始地址后多長的地址
  • 格式
    • x16 進制
    • f 是浮點
    • d10 進制
  • 字節(jié)數(shù)
    • bbyte 1 字節(jié)
    • hhalf word 2 字節(jié)
    • wword 4 字節(jié)
    • ggiant word 8 字節(jié)

舉例:讀取 szan 對象地址曲梗,要求以 8 個字節(jié),用 16 進制格式讀取 4 組數(shù)據(jù)妓忍。
x/4xg szan 或者 x/4xg 0x10055d610虏两,其中 0x10055d610szan 對象的地址。

memory write 地址 修改后的數(shù)據(jù) 世剖,通過 write 可以修改內(nèi)存中的數(shù)據(jù)定罢。

斷點操作 (breakpoind/b)

Xcode 工具為我們提供了斷點調(diào)試的功能,為什么還要使用這個命令呢旁瘫?LLDB 的斷點使用起來速度更快祖凫,功能更全面。

0. 流程控制

  • c/continue 繼續(xù)執(zhí)行酬凳,跳到下一個斷點或者沒有斷點程序執(zhí)行完畢
  • next/n(step-over) 單步運行惠况,將子函數(shù)當做整體一步運行
  • stepi/s(step-in) 單步運行,遇到子函數(shù)會進入
  • finish(step-out) 如果進入一個子函數(shù)宁仔,則可以通過這個方法退出子函數(shù)

1. 增刪查

  • set 添加斷點
    • -a {內(nèi)存地址} 根據(jù)函數(shù)地址打斷點(常用與逆向)
    • -n {xxx:} 設(shè)置方法名斷點 breakpoint/b set -n login:
    • -n { [Class xxxx]} 根據(jù)對應的類設(shè)置該類的方法名斷點(可多個:一組) breakpoint/b set -n "-[Class1 xxx]" -n "-[Class2 xxx]"
    • -l {lineNumber} 根據(jù)行號設(shè)置斷點
    • -f {fileName} 根據(jù)文件名中的信息設(shè)置斷點
    • -F {函數(shù)全名}根據(jù)函數(shù)全名打斷點
    • -r {部分函數(shù)名} 根據(jù)部分函數(shù)名打斷點
    • -N{別名} 給斷點添加別名
  • delete {breakpoint_num} 刪除一個斷點
  • list {breakpoint_num} 列舉指定斷點信息稠屠,breakpoint_num 可選
  • enable/disable {breakpoint_num} 啟用或禁用某個/某組斷點
  • commond 執(zhí)行一些特殊命令
    • add {breakpoint_num} {特殊命令(如p/po/bt等)} 斷點執(zhí)行后執(zhí)行一些特殊LLDB操作
    • delete{breakpoint_num}刪除某個斷點添加的特殊操作

2. 條件、命令

  • -i {number} 設(shè)置斷點忽略次數(shù)
  • -o 只斷住一次
  • -c {條件(類似數(shù)據(jù)庫where操作)} 設(shè)置斷點條件

其他操作

  • methods命令可以打印當前對象的屬性和方法
  • previews命令可以打印當前視圖的層級結(jié)構(gòu)
  • help 獲取幫助信息翎苫,查看更多 LLDB 命令

參考文檔

LLDB調(diào)試利器及高級用法
斷點遠比你想想中的強大
動態(tài)調(diào)試及LLDB技巧集合

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末权埠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拉队,更是在濱河造成了極大的恐慌弊知,老刑警劉巖阻逮,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粱快,死亡現(xiàn)場離奇詭異,居然都是意外死亡叔扼,警方通過查閱死者的電腦和手機事哭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓜富,“玉大人鳍咱,你說我怎么就攤上這事∮敫蹋” “怎么了谤辜?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵蓄坏,是天一觀的道長。 經(jīng)常有香客問我丑念,道長涡戳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任脯倚,我火速辦了婚禮渔彰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘推正。我一直安慰自己恍涂,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布植榕。 她就那樣靜靜地躺著再沧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尊残。 梳的紋絲不亂的頭發(fā)上产园,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音夜郁,去河邊找鬼什燕。 笑死,一個胖子當著我的面吹牛竞端,可吹牛的內(nèi)容都是我干的屎即。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼事富,長吁一口氣:“原來是場噩夢啊……” “哼技俐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起统台,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤雕擂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贱勃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體井赌,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年贵扰,在試婚紗的時候發(fā)現(xiàn)自己被綠了仇穗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡戚绕,死狀恐怖纹坐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舞丛,我是刑警寧澤耘子,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布果漾,位于F島的核電站,受9級特大地震影響谷誓,放射性物質(zhì)發(fā)生泄漏跨晴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一片林、第九天 我趴在偏房一處隱蔽的房頂上張望端盆。 院中可真熱鬧,春花似錦费封、人聲如沸焕妙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焚鹊。三九已至,卻和暖如春韧献,著一層夾襖步出監(jiān)牢的瞬間末患,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工锤窑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留璧针,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓渊啰,卻偏偏與公主長得像探橱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绘证,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355