Advanced+Apple+Debugging(3)

現在你已經學到了兩個最基本的命令apropos和help.是時候研究一下LLDB是如何把自己附加到進程上的.你會學習到所有用不同的選項把LLDB附加到進程上的不同方法, 以及附加到進程後會發生什麼.
附加attaching這個單詞多少有點誤導.一個叫debugserver的程序(可以在Xcode.app/Contents/SharedFrameworks/LLDB.framework/ Resources/裏找到), 負責附加到目標進程上.
如果要附加的是一個遠程進程, 比如是一個運行在iOS, watchOS或者tvOS的設備上的應用程序, 一個遠程debugserver會在那個遠程設備上啓動.啓動, 連接和使用debugserver定位來處理在調試應用程序過程中所有的交互是LLDB的工作.

附加到已經存在的進程上

就像你再第一章中看到的, 你可以用下面的命令附加到一個進程上:

lldb -n Xcode
然而, 我們還有另外一種方法做這件事!你可以通過使用進程標識符或者PID將LLDB附加到正在運行的進程上.
打開Xcode, 然後打開一個新的終端窗口, 然後運行下面的命令:

pgrep -x Xcode
這條命令會輸出Xcode進程的PID.
然後, 運行下面這條命令, 並把89944用上面得到的PID替換掉:

lldb -p 89944
這條指令告訴LLDB用用指定的PID附加到進程上.在這裏就是Xcode的進程.

附加到一個將來的進程上

上面的命令只能附加到正在運行的進程上.如果Xcode沒有運行, 上面的命令就會失效.如何在你還不知道進程PID的情況下捕獲到即將啓動的進程呢?
你可以使用-w參數做到, 這會讓LLDB進入等待狀態直到特定PID的進程啓動或者可執行文件的名字與-w的參數一致的時候.
例如, 在終端裏按下Ctrl + D殺掉已經存在的LLDb進程, 然後輸入下面的命令:

lldb -n Finder -w
這條命令會讓LLDB附加到一個下次啓動的名字叫Finder的進程上. 然後打開一個新的終端窗口, 並輸入一下命令:

pkill Finder
這條命令會殺掉Finder進程並強制重啓Finder進程.
macOS會自動重啓Finder當Finder被殺掉的時候.切換到你第一次創建的終端窗口中, 你會發現LLDB已經附加到了最近創建的Finder進程上.
另外一個附加到指定進程的方法是指定可執行文件的路徑, 並在你方便的時候手動啓動進程.

lldb -f /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
這會將Finder設置爲可執行文件啓動.一旦你準備好開始調試了, 只需在LLDB會話中簡單的輸入下面的命令:

(lldb) process launch
注意:一個有趣的現象是當你手動啓動一個進程的時候stderr會自動發送到終端窗口. 用其他方法附加LLDB的時候不會自動做這件事.
啓動時的選項

進程啓動命令有一些選項值得我們進一步探索.如果你感覺好奇並且想知道啓動進程時可用選項的完整列表, 只需要簡單鍵入help process launch.
關閉前面的LLDB會話, 打開一個新的終端窗口並且輸入下面的命令:

lldb -f /bin/ls
這條命令告訴LLDB使用/bin/ls(文件列表命令)作爲可執行文件.
你會看到下面這些輸出:

(lldb) target create "/bin/ls"
Current executable set to '/bin/ls' (x86_64).
鑑於ls是一個很迅速的程序(它會啓動, 完成它的工作, 然後退出),你將會用不同的參數多次運行這個程序來瀏覽每次都做了什麼.
第一次先嚐試在沒有參數的情況下啓動ls. 輸入下面的命令:

(lldb) process launch
你將會看到下面的輸出:

Process 7681 launched: '/bin/ls' (x86_64)
... # Omitted directory listing output
Process 7681 exited with status = 0 (0x00000000)
一個ls進程將會在你當前的工作目錄裏啓動.你也可以用-w選項告訴LLDB改變當前的工作目錄.
輸入下面的命令:

(lldb) process launch -w /Applications
這條命令會在/Applications目錄下啓動ls程序.
這條命令等價於下面這條命令:

$ cd /Applications
$ ls
我們還有另外一條方法來做到同樣的事情.取而代之的是你可以告訴LLDB運行程的目錄, 你可以給程序目錄參數傳一個值.
輸入下面的命令:

(lldb) process launch -- /Applications
這條命令與之前的命令擁有同樣的效果, 但是這一次他做了下面的事情:

$ ls /Applications
這一次, 會羅列出你macOS中所有的應用程序, 但是你指定了一個參數改變了ls啓動的目錄.怎樣將你桌面的目錄作爲啓動參數呢?鍵入下面的命令:

(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的參數.用下面的命令再試一次:

(lldb) process launch -X true -- ~/Desktop
-X參數可以展開你提供的任何shell參數, 比如~.
這裏有一個LLDB指令的快捷鍵:run.要學習更多創建自己命令的快捷鍵的, 請參考第八章"Persisting and Customizing Commands".
輸入下面的命令來查看run命令的文檔:

(lldb) help run
你會看到下面的輸出:

...
Command Options Usage:
run [<run-args>]
'run' is an abbreviation for 'process launch -X true --'
這是你剛剛運行的命令的縮寫.只需鍵入下面的命令去運行:

(lldb) run ~/Desktop
如何改變輸出的位置?在第一章中你已經試過用-e參數將stderr輸出到不同的終端窗口中, 但是改變stdout的位置如何做呢?
嘗試鍵入下面的命令:

(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
正如期望的那樣, 這是你應用程序下次輸出的目錄!
對於stdin同樣也有一個-i選項.首先,鍵入下面的選項:

(lldb) target delete
這條命令移除了作爲目標的ls.接下來, 輸入下面的命令:

(lldb) target create /usr/bin/wc
這一條命令將/usr/bin/wc作爲新的目標.wc可以用來統計stdin輸入中的字符, 單詞或者行數.
你已經將LLDB的目標可執行文件從ls切換到wc.現在你需要給wc提供一些參數.打開一個新的終端窗口並輸入下面的命令:

echo "hello world" > /tmp/wc_input.txt
你會看到這個文件給wc提供了一些輸入.
切換到LLDB會話中, 並輸入下面的命令:

(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)
這等價於下面這條命令:

$ wc < /tmp/wc_input.txt
有時你不想用stdin(standard input). 這對像Xcode這樣的GUI程序是非常有用的, 但是對於像ls和wc這樣的終端命令來說沒有實質性的幫助.
舉例說明你一下, 不用任何參數運行wc程序, 鍵入下面的內容:

(lldb) run
這個程序將只是掛在那裏因爲它希望從stdin裏讀到一些輸入.
鍵入hello world來給它一些輸入, 在字符的結尾處, 按下Return, 然後按下Control + D.wc會分析這些輸入並且退出.你將會看到同你前面用文件作爲輸入的時候的同樣的輸出.
現在, 用下面的命令啓動進程:

(lldb) process launch -n
你會看到wc立刻退出, 並看到下面這些輸出:

Process 28849 launched: '/usr/bin/wc' (x86_64)
Process 28849 exited with status = 0 (0x00000000)
-n選項告訴LLDB不要創建一個stdin.一次wc沒有可以處理的數據並且立即退出.
我們爲什麼要學習這些東西?
還有一些更有趣的選項可以用, 你會在後面的章節裏看到它們.在後面的章節中, 你將會學到LLDB如何將自己附加到iOS設備的遠程debugsever上.
從現在開始嘗試附加到非GUI程序上就像附加到GUI程序上那樣.嘗試在終端中運行你期望的stdin或者參數, 然後看看你發現了什麼?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章