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 [文件名]可查看其他文件。

圖中沒有添加行號,直接鍵入命令listorl, 默認顯示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.

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

