5个版本
0.6.4 | 2024年5月22日 |
---|---|
0.6.3 | 2024年5月12日 |
0.1.3 | 2023年10月1日 |
#110 in 调试
17KB
ChatDBG
由 Emery Berger、Stephen Freund、Kyla Levin、Nicolas van Kempen 贡献(按字母顺序排列)
ChatDBG是一个基于AI的调试助手,用于C/C++/Python/Rust代码,它将大型语言模型集成到标准调试器(pdb
、lldb
、gdb
和windbg
)中,以帮助您调试代码。使用ChatDBG,您可以与调试器进行对话,提出关于程序的开放性问题,例如为什么x为null?
。ChatDBG将接管方向盘并引导调试器回答您的查询。ChatDBG可以提供错误诊断并建议修复。
据我们所知,ChatDBG是第一个自动执行根本原因分析并提供建议修复的调试器。
观看ChatDBG的实际操作!
在test-overflow.cpp上的LLDB | 在test-overflow.cpp上的GDB | 在bootstrap.py上的Pdb |
---|---|---|
有关技术细节和完整评估,请参阅我们的arXiv论文,ChatDBG:基于AI的调试助手(PDF)。
[!NOTE]
ChatDBG针对
pdb
、lldb
和gdb
的功能已经完善;我们目前正在将这些调试器的功能移植到其他调试器中。
安装
[!IMPORTANT]
ChatDBG 目前需要连接到 OpenAI 账户。 您的账户需要保持正余额才能正常工作 (检查您的余额)。如果您从未购买过积分,您需要购买至少 $1 的积分(如果您的 API 账户是在 2023 年 8 月 13 日之前创建的)或 $0.50(如果您有一个较新的 API 账户),以便访问 ChatDBG 所使用的 GPT-4。 在此处获取密钥。
一旦您有了 API 密钥,将其设置为名为
OPENAI_API_KEY
的环境变量。export OPENAI_API_KEY=<your-api-key>
使用 pip
安装 ChatDBG(无论您是在调试 Python、C 还是 C++ 代码,您都需要这样做)
python3 -m pip install chatdbg
如果您使用 ChatDBG 调试 Python 程序,则已完成。如果您想使用 ChatDBG 通过 gdb
或 lldb
调试原生代码,请按照以下安装说明操作。
作为 lldb
扩展安装
lldb安装说明
通过运行以下命令将 ChatDBG 安装到 lldb
调试器中
Linux
python3 -m pip install ChatDBG
python3 -c 'import chatdbg; print(f"command script import {chatdbg.__path__[0]}/chatdbg_lldb.py")' >> ~/.lldbinit
如果您遇到错误,您可能正在使用较旧的 LLVM 版本。按照以下方式更新到最新版本
sudo apt install -y lsb-release wget software-properties-common gnupg
curl -sSf https://apt.llvm.org/llvm.sh | sudo bash -s -- 18 all
# LLDB now available as `lldb-18`.
Mac
xcrun python3 -m pip install ChatDBG
xcrun python3 -c 'import chatdbg; print(f"command script import {chatdbg.__path__[0]}/chatdbg_lldb.py")' >> ~/.lldbinit
这将把 ChatDBG 作为 LLVM 扩展安装。
作为 gdb
扩展安装
gdb安装说明
通过运行以下命令将 ChatDBG 安装到 gdb
调试器中
python3 -m pip install ChatDBG
python3 -c 'import chatdbg; print(f"source {chatdbg.__path__[0]}/chatdbg_gdb.py")' >> ~/.gdbinit
这将把 ChatDBG 作为 GDB 扩展安装。
作为 WinDBG
扩展安装
WinDBG安装说明
- 安装 WinDBG:如果尚未安装
WinDBG
,请按照 此处 的说明进行操作。 - 安装
vcpkg
:如果尚未安装vcpkg
,请按照 此处 的说明进行操作。 - 安装 Windows 调试工具:从 此处 安装 Windows SDK 并勾选
Debugging Tools for Windows
复选框。 - 导航到
src\chatdbg
目录:cd src\chatdbg
- 安装所需依赖:运行
vcpkg install
- 构建 chatdbg.dll 扩展:运行
mkdir build & cd build & cmake .. & cmake --build . & cd ..
使用 ChatDBG:
- 加载到 WinDBGX
- 运行
windbgx your_executable_here.exe
- 点击菜单项
视图
->命令浏览器
- 在命令浏览器中输入
.load debug\chatdbg.dll
- 运行
- 在运行代码并遇到异常/信号后
- 在命令浏览器中输入
!why
- 在命令浏览器中输入
用法
调试 Python
要使用 ChatDBG 调试 Python 程序,只需按照以下方式运行您的 Python 脚本
chatdbg -c continue yourscript.py
ChatDBG 是标准 Python 调试器 pdb
的扩展。与 pdb
类似,当你的脚本遇到未捕获的异常时,ChatDBG 将进入死后调试模式。
与其他调试器不同,你可以使用 why
命令询问 ChatDBG 为什么你的程序失败,并得到一个建议的修复方案。在大型语言模型(LLM)响应后,你可以发出额外的调试命令,或者通过输入任何其他文本继续对话。
IPython 和 Jupyter 支持
要将 ChatDBG 设置为 IPython 或 Jupyter 笔记本中的默认调试器,请创建一个 IPython 配置文件,然后在启动时添加必要的扩展。如果已经有了自定义的配置文件,请根据需要修改这些行。
ipython profile create
echo "c.InteractiveShellApp.extensions = ['chatdbg.chatdbg_pdb', 'ipyflow']" >> ~/.ipython/profile_default/ipython_config.py
在命令行上,你可以运行
ipython --pdb yourscript.py
在 Jupyter 中,使用 ipyflow 内核 运行你的笔记本,并在文件的顶部包含此行魔术命令。
%pdb
调试原生代码(C、C++ 或 Rust)lldb / gdb)
要使用 ChatDBG 与 lldb
或 gdb
一起工作,只需使用你的选择调试器运行原生代码(使用 -g
编译调试符号),当它崩溃时,询问 why
。这也适用于死后调试(当使用 -c
选项加载核心时)。
原生调试器的工作方式略不同于 Pdb。在调试器对你的问题做出响应后,你将进入 ChatDBG 的命令循环,如 (ChatDBG 聊天)
提示所示。你可以继续发出调试命令,并且可以通过以 "chat" 开头的消息向大型语言模型(LLM)发送额外的消息。当你完成时,键入 quit
返回调试器的主命令循环。
调试 Rust 程序
要使用 ChatDBG 与 Rust 一起工作,你需要进行两个步骤:修改你的 Cargo.toml
文件并在源程序中添加一行。
- 将以下内容添加到你的
Cargo.toml
文件中
[dependencies]
chatdbg = "0.6.2"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
- 在你的程序中,将
#[chatdbg::main]
属性应用于main
函数
#[chatdbg::main]
fn main() {
现在你可以使用 gdb
或 lldb
调试你的 Rust 代码。
示例
ChatDBG 示例在lldb
(ChatDBG lldb) run
Process 85494 launched: '/Users/emery/git/ChatDBG/test/a.out' (arm64)
TEST 1
TEST -422761288
TEST 0
TEST 0
TEST 0
TEST 0
TEST 0
TEST 0
Process 85494 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100056200)
frame #0: 0x0000000100002f64 a.out`foo(n=8, b=1) at test.cpp:7:22
4 int x[] = { 1, 2, 3, 4, 5 };
5
6 void foo(int n, float b) {
-> 7 cout << "TEST " << x[n * 10000] << endl;
8 }
9
10 int main()
Target 0: (a.out) stopped.
询问 why
以让 ChatDBG 提供一个有用的解释为什么这个程序失败,并提出一个修复方案
(ChatDBG lldb) why
The root cause of this error is accessing an index of the array `x`
that is out of bounds. In `foo()`, the index is calculated as `n *
10000`, which can be much larger than the size of the array `x` (which
is only 5 elements). In the given trace, the program is trying to
access the memory address `0x100056200`, which is outside of the range
of allocated memory for the array `x`.
To fix this error, we need to ensure that the index is within the
bounds of the array. One way to do this is to check the value of `n`
before calculating the index, and ensure that it is less than the size
of the array divided by the size of the element. For example, we can
modify `foo()` as follows:
```
void foo(int n, float b) {
if (n < 0 || n >= sizeof(x)/sizeof(x[0])) {
cout << "ERROR: Invalid index" << endl;
return;
}
cout << "TEST " << x[n] << endl;
}
```
This code checks if `n` is within the valid range, and prints an error
message if it is not. If `n` is within the range, the function prints
the value of the element at index `n` of `x`. With this modification,
the program will avoid accessing memory outside the bounds of the
array, and will print the expected output for valid indices.
ChatDBG 示例在 Python(pdb)
Traceback (most recent call last):
File "yourscript.py", line 9, in <module>
print(tryme(100))
File "yourscript.py", line 4, in tryme
if x / i > 2:
ZeroDivisionError: division by zero
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> yourscript.py(4)tryme()
-> if x / i > 2:
询问 why
以让 ChatDBG 提供一个有用的解释为什么这个程序失败,并提出一个修复方案
(ChatDBG Pdb) why
The root cause of the error is that the code is attempting to
divide by zero in the line "if x / i > 2". As i ranges from 0 to 99,
it will eventually reach the value of 0, causing a ZeroDivisionError.
A possible fix for this would be to add a check for i being equal to
zero before performing the division. This could be done by adding an
additional conditional statement, such as "if i == 0: continue", to
skip over the iteration when i is zero. The updated code would look
like this:
def tryme(x):
count = 0
for i in range(100):
if i == 0:
continue
if x / i > 2:
count += 1
return count
if __name__ == '__main__':
print(tryme(100))
依赖项
~245–690KB
~16K SLoC