美文网首页
开始学习LLDB命令(第三章:使用LLDB附加)

开始学习LLDB命令(第三章:使用LLDB附加)

作者: 股金杂谈 | 来源:发表于2017-05-21 22:16 被阅读794次

    现在你已经学到了两个最基本的命令aproposhelp.是时候研究一下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程序是非常有用的, 但是对于像lswc这样的终端命令来说没有实质性的帮助.
    举例说明你一下, 不用任何参数运行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或者参数, 然后看看你发现了什么?

    相关文章

      网友评论

          本文标题:开始学习LLDB命令(第三章:使用LLDB附加)

          本文链接:https://www.haomeiwen.com/subject/vkdvxxtx.html