lldb調試C++總結(1)


Note

好記性不如爛筆頭。時間一長,lldb的基本功快忘本了。

  • 本文將介紹使用 lldb 調試 C++程序的基本用法。
  • 演示基於 Ubuntu + lldb

lldb + clang(++) 版本

源碼編譯,可能和你使用的不一樣,but, lldb的語法差不多的。

lldb help

USAGE: lldb [options]

ATTACHING:
  --attach-name <name> Tells the debugger to attach to a process with the given name.
  --attach-pid <pid>   Tells the debugger to attach to a process with the given pid.
  -n <value>           Alias for --attach-name
  -p <value>           Alias for --attach-pid
  --wait-for           Tells the debugger to wait for a process with the given pid or name to launch before attaching.
  -w                   Alias for --wait-for

COMMANDS:
  --batch              Tells the debugger to run the commands from -s, -S, -o & -O, and then quit.
  -b                   Alias for --batch
  -K <value>           Alias for --source-on-crash
  -k <value>           Alias for --one-line-on-crash
  --local-lldbinit     Allow the debugger to parse the .lldbinit files in the current working directory, unless --no-lldbinit is passed.
  --no-lldbinit        Do not automatically parse any '.lldbinit' files.
  --one-line-before-file <command>
                       Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded.
  --one-line-on-crash <command>
                       When in batch mode, tells the debugger to run this one-line lldb command if the target crashes.
  --one-line <command> Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded.
  -O <value>           Alias for --one-line-before-file
  -o <value>           Alias for --one-line
  -Q                   Alias for --source-quietly
  --source-before-file <file>
                       Tells the debugger to read in and execute the lldb commands in the given file, before any file has been loaded.
  --source-on-crash <file>
                       When in batch mode, tells the debugger to source this file of lldb commands if the target crashes.
  --source-quietly     Tells the debugger to execute this one-line lldb command before any file has been loaded.
  --source <file>      Tells the debugger to read in and execute the lldb commands in the given file, after any file has been loaded.
  -S <value>           Alias for --source-before-file
  -s <value>           Alias for --source
  -x                   Alias for --no-lldbinit

OPTIONS:
  --arch <architecture> Tells the debugger to use the specified architecture when starting and running the program.
  -a <value>            Alias for --arch
  --capture-path <filename>
                        Tells the debugger to use the given filename for the reproducer.
  --capture             Tells the debugger to capture a reproducer.
  --core <filename>     Tells the debugger to use the full path to <filename> as the core file.
  -c <value>            Alias for --core
  --debug               Tells the debugger to print out extra information for debugging itself.
  -d                    Alias for --debug
  --editor              Tells the debugger to open source files using the host's "external editor" mechanism.
  -e                    Alias for --editor
  --file <filename>     Tells the debugger to use the file <filename> as the program to be debugged.
  -f <value>            Alias for --file
  --help                Prints out the usage information for the LLDB debugger.
  -h                    Alias for --help
  --no-use-colors       Do not use colors.
  --replay <filename>   Tells the debugger to replay a reproducer from <filename>.
  --reproducer-skip-version-check
                        Skip the reproducer version check.
  --version             Prints out the current version number of the LLDB debugger.
  -v                    Alias for --version
  -X                    Alias for --no-use-color

REPL:
  -r=<flags>     Alias for --repl=<flags>
  --repl-language <language>
                 Chooses the language for the REPL.
  --repl=<flags> Runs lldb in REPL mode with a stub process with the given flags.
  --repl         Runs lldb in REPL mode with a stub process.
  -R <value>     Alias for --repl-language
  -r             Alias for --repl

SCRIPTING:
  -l <value>    Alias for --script-language
  --python-path Prints out the path to the lldb.py file for this version of lldb.
  -P            Alias for --python-path
  --script-language <language>
                Tells the debugger to use the specified scripting language for user-defined scripts.

EXAMPLES:
  The debugger can be started in several modes.

  Passing an executable as a positional argument prepares lldb to debug the
  given executable. Arguments passed after -- are considered arguments to the
  debugged executable.

    lldb --arch x86_64 /path/to/program -- --arch arvm7

  Passing one of the attach options causes lldb to immediately attach to the
  given process.

    lldb -p <pid>
    lldb -n <process-name>

  Passing --repl starts lldb in REPL mode.

    lldb -r

  Passing --core causes lldb to debug the core file.

    lldb -c /path/to/core

  Command options can be combined with these modes and cause lldb to run the
  specified commands before or after events, like loading the file or crashing,
  in the order provided on the command line.

    lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
    lldb -S /source/before/file -s /source/after/file
    lldb -K /source/before/crash -k /source/after/crash

  Note: In REPL mode no file is loaded, so commands specified to run after
  loading the file (via -o or -s) will be ignored.

下面進入正題。

c++代碼demo

准備了一份C++代碼,用作演示。

提示: clang++編譯需要使用 -g 參數,生成調試信息。

#include <iostream>

int print(const char *parr)
{
    if (nullptr != parr)
        std::cout << parr << "\n\n";

    return 0;
}

int main(int argc, char* argv[], char* env[])
{
    int var_a = 1;
    char arr[] = {"ABCDEF"};
    
    int ret = print("hello world");

    std::cout << arr << "\n\n";
    std::cout << "var_a=" << var_a << "\n\n";
    std::cout << "ret=" << ret << "\n\n";

    return 0;
}

已使用clang++將其編譯為demo

lldb啟動與退出

啟動

啟動有兩種方式。

方式1

語法: lldb [程序名]。 例如, lldb demo。 其中,demo為程序名。執行命令后,lldb將啟動demo程序,並暫停。

如果你的程序需要傳遞參數到 main,可以使用lldb demo [參數1] [參數2]....

方式2

上面是直接一步到位。接着這個方法可能有點慢: 先啟動lldb,再用file啟動程序。

  • 首先鍵入lldb可直接啟動lldb.
  • 其次鍵入file demo 啟動目標程序.

對比可知,都可以打達到同樣的效果。

退出

退出也有兩種方式

方式1

使用quit命令。

方式2

使用exit命令

可見,鍵入命令后,已經返回current directory了。

list 查看源碼

查看文件代碼

  • 使用listorl可以查看當前設置的文件代碼. 語法: list 行號。 例如: list 10. 這里將跳轉到第10行,從此往下顯示10行
  • 使用list [文件名] 可查看其他文件。

    圖中沒有添加行號,直接鍵入命令 list or l , 默認顯示10行代碼。
    下面演示代碼行跳轉

    上面的list 1 將從第一行顯示10行代碼。下面接着按下回車,默認顯示10行代碼。

查看函數

使用命令list [函數名]可查看函數代碼。

breakpoint 斷點

函數名設置斷點

breakpoint set --name [函數名] 可設置斷點。 如下圖,設置了main函數斷點。

設置斷點后,再執行run,可見程序已經停在了函數的入口處。

行號設置斷點

breakpoint set --line [行號] s設置斷點. 下面演示了在當前文件的第8行設置斷點。且斷點序號為3

(lldb) breakpoint set --line 8
Breakpoint 3: where = demo`main + 33 at demo.cpp:8:10, address = 0x0000000000401201

根據文件名設置斷點

breakpoint set --file [文件名] --line [行號]。 下面演示 將斷點設置在文件car.hpp中的第17

(lldb) breakpoint set --file car.hpp --line 17
Breakpoint 1: where = demo`car::print_name() + 12 at car.hpp:18:19, address = 0x00000000004012ec

刪除所有斷點

breakpoint delete可刪除所有斷點,並提示確認 。

(lldb) breakpoint delete
About to delete all breakpoints, do you want to do that?: [Y/n] 

刪除某個斷點

斷點列表

(lldb) breakpoint list
Current breakpoints:
2: name = 'main', locations = 1
  2.1: where = demo`main + 26 at demo.cpp:7:9, address = demo[0x00000000004011fa], unresolved, hit count = 0 

3: file = '/home/xxx/demo/libevent_demo/demo.cpp', line = 8, exact_match = 0, locations = 1
  3.1: where = demo`main + 33 at demo.cpp:8:10, address = demo[0x0000000000401201], unresolved, hit count = 0 

4: file = '/home/xxx/demo/libevent_demo/demo.cpp', line = 10, exact_match = 0, locations = 1
  4.1: where = demo`main + 47 at demo.cpp:10:15, address = demo[0x000000000040120f], unresolved, hit count = 0 
  • 使用 breakpoint delete [斷點序號] 可刪除指定斷點。 下面刪除序號為2的斷點和刪除后的斷點列表
(lldb) breakpoint delete 2
1 breakpoints deleted; 0 breakpoint locations disabled.
(lldb) breakpoint list
Current breakpoints:
3: file = '/home/cube/demo/libevent_demo/demo.cpp', line = 8, exact_match = 0, locations = 1
  3.1: where = demo`main + 33 at demo.cpp:8:10, address = demo[0x0000000000401201], unresolved, hit count = 0 

4: file = '/home/cube/demo/libevent_demo/demo.cpp', line = 10, exact_match = 0, locations = 1
  4.1: where = demo`main + 47 at demo.cpp:10:15, address = demo[0x000000000040120f], unresolved, hit count = 0 
  • 使用 breakpoint delete [n-m] 可刪除從 序號n序號m之間的斷點。一個例子
(lldb) breakpoint delete 3-4
2 breakpoints deleted; 0 breakpoint locations disabled.
(lldb) breakpoint list  
No breakpoints currently set.
  • 刪除多個不連續斷點
    使用breakpoint delete [序號1] [序號2] [序號3]..... 可刪除多個斷點。
(lldb) breakpoint delete 5 7 8
3 breakpoints deleted; 0 breakpoint locations disabled.
(lldb) breakpoint list
Current breakpoints:
6: file = '/home/cube/demo/libevent_demo/demo.cpp', line = 9, exact_match = 0, locations = 1
  6.1: where = demo`main + 47 at demo.cpp:10:15, address = demo[0x000000000040120f], unresolved, hit count = 0 

查看斷點列表

  • 使用breakpoint list 可以查看所有斷點。

    圈出來的是序號,可設置多個斷點,用這個序號作為唯一標識。

  • 禁用斷點:breakpoint disable [序號], 例如, breakpoint disable 1

  • 啟動斷點:breakpoint enable [序號],例如: breakpoint enable 1

run 運行

run命令可以讓程序運行起來。

next 下一步

使用 next or n 可以單步執行

step 步入

使用 step or s 步入 函數。

finish 跳出

使用 finish 跳出,返回步入的地方,

p和po輸出變量

p

使用p [變量名] 可以查看變量的值。

po

使用 po [指針變量名] 可以查看其值

frame查看變量值

使用frame variable 可以查看當前frame中的所有value

expression 修改變量值

使用expression [變量名]=[value]可以修改變量的值。(做ios tweak 分析時,這招就挺好使)。
例如: expression ret=10.

程序繼續執行,發現輸出的ret0變為10.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM