LLDB 调试命令使用指南

本贴最后更新于 2022 天前,其中的信息可能已经事过景迁

原文链接 LLDB 调试命令使用指南

前言

LLDB Debugger (LLDB) 是一个开源、底层调试器(low level debugger),具有 REPL (Read-Eval-Print Loop,交互式解释器)、C++ 和 Python 插件,位于 Xcode 窗口底部控制台中,也有其他 IDE 加入了 LLDB 调试器,如 CLion,当然其也可以在 terminal 中使用。搜罗了一圈,发现大多数教程还是可视化的使用,本文就命令行使用 LLDB 调试程序做一个总结。

调试前

需要安装 lldb 调试器,如果你安装了 llvm 编译环境,lldb 是其自带的工具,就不用安装了。

开始或结束调试

特别注意,需调试的程序一定要加上 -g 参数进行编译,否则调试时无法看到源码。

lldb 有两种进入方式,本例使用方法一(假设可执行程序名为 toy,参数为 example1

方式一,直接运行 lldb toy example 进入调试环境

方式二,先运行 lldb,再通过 file toy 进入调试环境

除此之外,还可调试正在运行时的程序,此时需要找到此程序的 PID 或者进程名,再使用

(lldb) process attach --pid 9939

或者

(lldb) process attach --name Safari

进入调试环境。

退出 lldb 环境,输入 quit 或者 exit 即可。

查看代码

list 查看

和 gdb 一样,使用 list 查看代码,这里有两个小技巧

  • 不输入命令的时候直接按回车,就会执行上一次执行的命令。
  • 一直 list 到底了之后再 list 就没有了,这时候怎么办?list 1 就回到第一行了。l 13 就是从第 13 行开始往下看 10 行。
看其他文件的代码

如果程序编译的时候是由很多文件组成的,那么就可以使用 list 文件名 看其他文件的代码, 以后再执行 list 3 的时候,看的就是你前面设置的文件名的第三行。

看某个函数的代码

直接输入某个函数的名字即可。

演示如下:

设置断点

根据文件名和行号下断点
(lldb) breakpoint set --file toy.cpp --line 10
根据函数名下断点
# C函数
(lldb) breakpoint set --name main
# C++类方法
(lldb) breakpoint set --method foo
根据某个函数调用语句下断点
# lldb有一个最小子串匹配算法,会知道应该在哪个函数那里下断点
breakpoint set -n "-[SKTGraphicView alignLeftEdges:]"
小技巧

你可以通过设置命令的别名来简化上面的命令

# 比如下面的这条命令
(lldb) breakpoint set --file test.c --line 10

# 你就可以写这样的别名
(lldb) command alias bfl breakpoint set -f %1 -l %2

# 使用的时候就像这样就好了
(lldb) bfl test.c 10
查看断点列表、启用/禁用断点、删除断点
# 查看断点列表
(lldb) breakpoint list
   
# 禁用断点
# 根据上面查看断点列表的时候的序号来操作断点
(lldb) breakpoint disable 2

# 启用断点
(lldb) breakpoint enable 2
   
# 删除断点
(lldb) breakpoint delete 1

演示如下:

调试环境操作

启动

OK, 我们前面已经下好断点了,现在就要启动这个程序了!前面留一个断点是断在 main 函数。

# run命令就是启动程序
(lldb) run
下一步、步入、步出、继续执行
# 下一步 (next 或 n)
(lldb) next

# 步入(step 或 s)
(lldb) step
  
# 步出(finish)
(lldb) finish

# 继续执行到下一个断点停, 后面没有断点的话就跑完了(continue 或 c)
(lldb) continue
查看变量、跳帧查看变量
# 使用po或p,po一般用来输出指针指向的那个对象,p一般用来输出基础变量。普通数组两者都可用
(lldb) po result_array
 
 # 查看所有帧(bt)
(lldb) bt
   
# 跳帧(frame select)
(lldb) frame select 1
  
# 查看当前帧中所有变量的值(frame variable)
 (lldb) frame variable

修改变量或调用函数

使用 expression 命令可以在调试过程中修改变量的值,或者执行函数。

修改变量值
(lldb) expression a
(int) $0 = 9
(lldb) frame variable a
(int) a = 9
(lldb) expression a=10
(int) $1 = 10
(lldb) frame variable a
(int) a = 10
(lldb) 
调用函数
(lldb) expression printf("execute function %i",a)
(int) $2 = 19
execute function 10

对于执行结果都会自动保存,以备他用。

线程控制

在加载进程开始调试后,当执行到设置断点时,可以使用 thread 命令控制代码的执行。

线程继续执行
(lldb) thread continue 
Resuming thread 0x2c03 in process 46915 
Resuming process 46915 
(lldb)
线程进入、单步执行或跳出
(lldb) thread step-in    
(lldb) thread step-over  
(lldb) thread step-out
单步指令的执行
(lldb) thread step-inst  
(lldb) thread step-over-ins
执行指定代码行数直到退出当前帧
(lldb) thread until 100
查看线程列表,第一个线程为当前执行线程
(lldb) thread list
Process 46915 state is Stopped
* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
  thread #2: tid = 0x2e03, 0x0000
查看当前线程栈
(lldb) thread backtrace
thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
 frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
 frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
 frame #2: 0
查看所有线程的调用栈
(lldb) thread backtrace all
设置当前线程
(lldb) thread select 2

部分参考:

使用 LLDB 调试程序

LLDB 常用命令

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...