既然你已經(jīng)了解了兩個最重要的命令榛泛,help 和 apropos,現(xiàn)在是時候研究 LLDB 如何連接進程。 你將學(xué)習(xí)使用各種選項將 LLDB 連接到進程的所有方式,以及連接到進程后發(fā)生的結(jié)果静檬。
LLDB “連接”這個詞實際上有點誤導(dǎo)炭懊。 名為 debugserver 的程序(在 Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/ 中找到)負責(zé)連接到目標進程并级。
如果它是一個遠程進程,例如運行在遠程設(shè)備上的 iOS侮腹,watchOS 或 tvOS 應(yīng)用程序嘲碧,遠程的 debugserver 將在該遠程設(shè)備上啟動。 LLDB 的工作是啟動父阻,連接和協(xié)調(diào) debugserver愈涩,以處理調(diào)試應(yīng)用程序中的所有交互。
連接到已有進程
正如你在第一章中已經(jīng)看到的那樣加矛,你可以像這樣連接一個進程:
lldb -n Xcode
然而履婉,還有其他方法可以做同樣的事情。 你可以通過提供正在運行的程序的進程標識符或 PID 來連接到 Xcode斟览。
打開 Xcode毁腿,然后打開一個新的終端會話,最后運行以下內(nèi)容:
pgrep -x Xcode
這會輸出 Xcode 進程的 PID。
接下來已烤,運行以下命令鸠窗,用上面的命令替換 89944 的數(shù)字輸出:
lldb -p 89944
這讓 LLDB 使用給定的 PID 連接到進程。 目前胯究,連接的是你正在運行的 Xcode 進程稍计。
連接到未來進程
之前的命令只能獲取正在運行的進程地址。 如果 Xcode 沒有運行裕循,或者已經(jīng)連接到調(diào)試器臣嚣,那么之前的命令將會失敗。 如果你還不知道 PID剥哑,你怎么能得到一個即將啟動的進程呢茧球?
你可以用 -w 參數(shù)來做到這一點,這會導(dǎo)致 LLDB 等待一個進程啟動星持,其 PID 或可執(zhí)行進程名稱與使用 -p 或 -n 參數(shù)提供的條件匹配抢埋。
例如,通過在終端窗口中按 Ctrl + D 來終止現(xiàn)有的 LLDB 會話督暂,然后輸入以下內(nèi)容:
lldb -n Finder -w
這會讓 LLDB 在下次啟動時連接名為 Finder 的進程揪垄。 接下來,打開一個新的終端選項卡逻翁,并輸入以下內(nèi)容:
pkill Finder
這將終止 Finder 進程并強制重啟饥努。 終止后,macOS 會自動重新啟動 Finder八回。 切換回你的第一個終端選項卡酷愧,你會注意到 LLDB 已經(jīng)把自己連接到新創(chuàng)建的 Finder 進程中。
另一種連接到進程的方法是指定可執(zhí)行進程的路徑缠诅,并在方便時手動啟動進程:
lldb -f /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
這將設(shè)置 Finder 作為可執(zhí)行進程啟動溶浴。 一旦準備好開始調(diào)試會話,只需在 LLDB 會話中輸入以下內(nèi)容:
(lldb) process launch
注意:一個有趣的副作用是管引,手動啟動進程時士败,stderr 輸出(即 NSLog 和公司)會自動發(fā)送到終端窗口。 其他 LLDB 連接配置不會自動執(zhí)行此操作褥伴。
啟動時的選項
process launch 命令帶有一套值得進一步探索的選項谅将。 如果你好奇,想要查看 process launch 的可用選項的完整列表重慢,只需輸入 help process launch饥臂。
關(guān)閉之前的 LLDB 會話,打開一個新的終端窗口并輸入以下內(nèi)容:
lldb -f /bin/ls
這告訴 LLDB 使用 /bin/ls(文件列表命令)作為目標可執(zhí)行進程似踱。
注意:如果你省略了-f選項隅熙,LLDB 會自動推斷第一個參數(shù)作為可執(zhí)行進程來啟動和調(diào)試志衣。 在調(diào)試終端可執(zhí)行進程時,我經(jīng)常輸入 lldb $(which ls)(或其他等價內(nèi)容)猛们,然后轉(zhuǎn)換成 lldb /bin/ls念脯。
你會看到下面的輸出:
(lldb) target create "/bin/ls"
Current executable set to '/bin/ls' (x86_64).
由于 ls 是一個快速的程序(它啟動,完成工作弯淘,然后退出)绿店,你將用不同的參數(shù)多次運行這個程序來探索每一個的作用。
不帶參數(shù)從 LLDB 啟動 ls庐橙。 輸入以下內(nèi)容:
(lldb) process launch
你會看到下面的輸出:
Process 7681 launched: '/bin/ls' (x86_64)
... # Omitted directory listing output
Process 7681 exited with status = 0 (0x00000000)
一個 ls 進程將在你最初的目錄中啟動假勿。您可以通過告訴 LLDB 在哪里啟動 -w 選項來更改當前的工作目錄。 輸入以下內(nèi)容:
(lldb) process launch -w /Applications
這將從 /Applications 目錄中啟動 ls态鳖。 這等價于以下內(nèi)容:
$ cd /Applications
$ ls
還有另一種方式來做到這一點转培。 不要讓 LLDB 改變目錄然后運行程序,你可以直接將參數(shù)傳遞給程序浆竭。
(lldb) process launch -- /Applications
這和前面的命令有相同的效果浸须,但是這一次是這樣做的:
$ ls /Applications
再說一次,這列出了所有的 macOS 程序邦泄,但是你指定了一個參數(shù)而不是改變起始目錄删窒。 將桌面目錄指定為啟動參數(shù)怎么樣? 嘗試運行這個:
(lldb) process launch -- ~/Desktop
你會看到下面的輸出:
Process 8103 launched: '/bin/ls' (x86_64)
ls: ~/Desktop: No such file or directory
Process 8103 exited with status = 1 (0x00000001)
噢顺囊,沒有生效肌索。 你需要 shell 來擴展參數(shù)中的波浪號。 試試這個:
(lldb) process launch -X true -- ~/Desktop
-X 選項擴展你提供的任何 shell 參數(shù)特碳,例如波浪號诚亚。 在 LLDB 中有一個快捷方式:只需輸入 run 即可。 要了解有關(guān)創(chuàng)建自定義命令快捷鍵的更多信息午乓,請查看第八章“持久化和自定義命令”站宗。
輸入以下內(nèi)容以查看 run 的文檔:
(lldb) help run
你會看到下面的輸出:
...
Command Options Usage:
run [<run-args>]
'run' is an abbreviation for 'process launch -X true --'
看到了嗎? 這是你剛才跑的命令的縮寫硅瞧! 通過輸入以下內(nèi)容來執(zhí)行命令:
(lldb) run ~/Desktop
將控制臺輸出更改到不同的位置會怎么樣份乒? 你已經(jīng)在第一章中嘗試使用 -e 標志將 stderr 更改為其他終端選項卡恕汇,但 stdout 會怎么樣呢腕唧?
輸入以下內(nèi)容:
(lldb) process launch -o /tmp/ls_output.txt -- /Applications
-o 選項告訴 LLDB 將 stdout 傳到給定的文件。
你會看到下面的輸出:
Process 15194 launched: '/bin/ls' (x86_64)
Process 15194 exited with status = 0 (0x00000000)
注意瘾英,沒有直接從 ls 輸出枣接。
打開另一個終端選項卡,然后運行以下命令:
cat /tmp/ls_output.txt
你的應(yīng)用程序目錄應(yīng)該再次輸出缺谴,如預(yù)期結(jié)果一樣但惶!
stdin 也有一個選項 -i。 首先,輸入以下內(nèi)容:
(lldb) target delete
這將消除 ls 作為目標膀曾。 接下來县爬,輸入這個:
(lldb) target create /usr/bin/wc
這將 /usr/ bin/wc 設(shè)置為新目標。 wc 可以用來計算給 stdin 輸入的字符添谊,單詞或者行數(shù)财喳。
你已經(jīng)把你的 LLDB 會話的目標可執(zhí)行進程從 ls 換成了 wc。 現(xiàn)在你需要提供一些數(shù)據(jù)給 wc斩狱。 打開一個新的終端選項卡并輸入以下內(nèi)容:
echo "hello world" > /tmp/wc_input.txt
你會用這個文件給 wc 一些輸入耳高。
切換回 LLDB 會話并輸入以下內(nèi)容:
(lldb) process launch -i /tmp/wc_input.txt
你會看到下面的輸出:
Process 24511 launched: '/usr/bin/wc' (x86_64)
1 2 12
Process 24511 exited with status = 0 (0x00000000)
這在功能上等同于以下內(nèi)容:
$ wc < /tmp/wc_input.txt
有時候你不需要 stdin(標準輸入)。 這對于 Xcode 等 GUI 程序非常有用所踊,但對于終端命令(如 ls 和 wc)沒什么幫助泌枪。
為了舉例說明,不帶任何參數(shù)運行 wc 目標秕岛,就像這樣:
(lldb) run
程序只是等待著碌燕,因為它期望從 stdin 讀取一些東西。
給它輸入 hello world继薛,按回車鍵陆蟆,然后按 Control + D,這是傳輸字符的結(jié)尾惋增。 wc 將解析輸入并退出叠殷。 你將看到與作為輸入的使用文件相同的輸出。
現(xiàn)在诈皿,像這樣啟動過程:
(lldb) process launch -n
你會看到 wc 立即退出林束,輸出如下:
Process 28849 launched: '/usr/bin/wc' (x86_64)
Process 28849 exited with status = 0 (0x00000000)
-n 選項告訴 LLDB 不要創(chuàng)建 stdin,wc 沒有數(shù)據(jù)可以處理稽亏,因此退出壶冒。
接下來?
還有一些有趣的選項可以使用(你可以通過 help 命令找到)截歉,你需要自己花時間去探索胖腾。
現(xiàn)在,嘗試連接到 GUI 和非 GUI 程序瘪松。 如果沒有源代碼咸作,你可能理解不了太多的東西,但是在即將到來的章節(jié)中你會發(fā)現(xiàn)在這些程序中你能得到多少信息和控制宵睦。