9 个版本
0.2.2 | 2024 年 7 月 27 日 |
---|---|
0.2.1 | 2024 年 6 月 15 日 |
0.1.5 | 2024 年 5 月 3 日 |
0.1.4 | 2024 年 4 月 3 日 |
0.1.0 | 2024 年 2 月 29 日 |
#157 in 调试
每月 183 次下载
1MB
25K SLoC
BugStalker
Linux x86-64 的现代调试器。用 Rust 编写,用于 Rust 程序。
目录
支持的 rustc 版本
- 1.75
- 1.76
- 1.77
- 1.78
- 1.79
- 1.80
特性
- 用 Rust 语言编写,以简洁为首要目标
- 断点、步骤、信号、观察点
- 支持多线程应用程序
- 数据查询表达式
- 支持 Rust 类型系统(集合、智能指针、线程局部变量等),不仅限于打印,也支持交互
- 两种 UI 类型:控制台和 Tui,可以在任何时候切换
- 预言机 作为扩展机制
- 内建的 tokio 预言机 - 类似于 tokio_console,但无需更改源代码
- 等等!
安装
首先检查是否安装了必要的依赖项(pkg-config
和 libunwind-dev
)
例如,Ubuntu/Debian
apt install pkg-config libunwind-dev
例如,Fedora
dnf install pkg-config libunwind-devel
现在安装调试器
cargo install bugstalker
这就完成了,现在可以使用 bs
命令了!
libunwind 的问题?
如果您在 `libunwind` 上遇到任何问题,您可以尝试使用本地解包器安装 `bs`(目前,我不建议这种方法,因为 libunwind 更好 :))cargo install bugstalker --no-default-features
发行版软件包
Arch Linux
pacman -S bugstalker
Nix 软件包管理器
有一个可以用来开始使用的 flake。只需 启用 flakes,然后您就可以使用它了
nix run github:godzie44/BugStalker
bugstalker
还提供了一个可以包含到 NixOS 配置中的软件包。例如
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
bugstalker.url = "github:godzie44/BugStalker";
};
outpus = {nixpkgs, bugstalker, ...}: {
nixosConfigurations.your_hostname = nixpkgs.lib.nixosSystem {
modules = [
({...}: {
environment.systemPackages = [
# assuming your system runs on a x86-64 cpu
bugstalker.packages."x86_64-linux".default
];
})
];
};
};
}
Home-Manager
有一个 home-manager 模块可以将 programs.bugstalker
添加到您的 home-manager 配置中。您可以通过以下步骤添加它
{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
bugstalker.url = "github:godzie44/BugStalker";
};
outputs = inputs@{ nixpkgs, home-manager, bugstalker, ... }: {
nixosConfigurations = {
hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
home-manager.nixosModules.home-manager
{
home-manager.sharedModules = [
bugstalker.homeManagerModules.default
({...}: {
programs.bugstalker = {
enable = true;
# the content of `keymap.toml`
keymap = {
common = {
up = ["k"];
}
};
};
})
];
}
];
};
};
};
}
开始调试会话
要从二进制文件启动程序,请使用
bs my_cool_program
或者使用参数
bs my_cool_program -- --arg1 val1 --arg2 val2
或者通过 pid 连接到程序
bs -p 123
帮助
使用 help
打印以查看所有可用命令。
开始和重启
run
- 启动或重启程序(别名:r
)
停止和继续
当命中断点、访问观察点、执行步骤命令或操作系统信号到来时,调试器会停止您的程序。BugStalker 总是停止整个程序,这意味着所有线程都会停止。引发停止的线程成为当前选定的线程。
继续执行
continue
- 恢复停止的程序
断点
break {文件}:{行号}
- 在行上设置断点(别名:b {文件}:{行号}
)break {函数名}
- 在函数开始处设置断点(别名:b {函数名}
)break {指令地址}
- 在指令处设置断点(别名:b {指令地址}
)break remove {编号}
- 根据编号删除断点(别名:b r {编号}
)break remove {文件}:{行号}
- 在行上删除断点(别名:b r {文件}:{行号}
)break remove {函数名}
- 在函数开始处删除断点(别名:b r {函数名}
)break info
- 打印所有断点
观察点
观察点是一种“数据断点”。这意味着当观察点所观察到的变量(或表达式,或仅仅是原始内存区域)发生变化时,程序会停止。目前,观察点功能基于 x86-64
硬件断点。因此,有两个限制
- 一次只能有4个观察点
- 监视1/2/4/8字节大小的“observe”内存区域
您可以在变量(全局或局部)或基于变量的表达式中设置监视点。当变量超出作用域时,局部变量的监视点将自动删除。如果监视点观察全局变量,则它在调试器运行期间将一直存在。
让我们看一些例子
watch my_var
- 当变量值被重写时停止(别名:w my_var
)watch +rw my_var
- 当变量值被读取或重写时停止watch my_vector[0]
- 当第一个向量元素被重写时停止watch (~my_vector).len
- 当向量长度改变时停止watch 0x100:4
- 当写入内存区域[0x100:0x103]时停止
步骤
stepi
- 执行一条单条指令step
- 执行程序直到达到不同的源行(别名:stepinto
)next
- 执行程序,跳过子程序(函数)调用(别名:stepover
)finish
- 执行程序直到所选堆栈帧返回(别名:stepout
)
信号
BugStalker
会捕获从操作系统发送到调试程序程序的信号并停止执行。例如,尝试向调试程序程序发送SIGINT(Ctrl+C)以停止它。
更改当前选定的线程
thread info
- 打印有关线程的信息列表thread current
- 打印当前选定的线程thread switch {number}
- 切换选定的线程
检查堆栈
当您的程序停止时,您需要知道它停止的位置以及它是如何到达那里的。
每次您的程序执行函数调用时,有关调用是在程序中的哪个位置进行的的信息将保存在一个称为堆栈帧的数据块中。该帧还包含调用的参数和被调用的函数的局部变量。所有堆栈帧都分配在称为调用堆栈的内存区域中。
堆栈帧
调用堆栈被分成连续的部分,称为堆栈帧。每个帧是与一个函数的一次调用相关联的数据。帧包含传递给函数的参数、函数的局部变量以及函数执行的地址。
回溯
backtrace
- 打印当前停止的线程的回溯(别名:bt
)。回溯包含有关线程(编号、pid、线程停止处的指令地址)以及从当前正在执行的帧(帧0)开始的所有帧的信息,然后是其调用者(帧1),依此类推。backtrace all
- 打印所有活动线程的回溯(别名:bt all
)。
选择一个帧
大多数用于检查程序中堆栈和其他数据的命令都适用于当前选定的堆栈帧。
frame info
- 打印有关当前选定的帧的信息。frame switch {num}
- 切换当前选定的帧。
检查源文件
BugStalker 可以打印程序源代码的部分。当程序停止时,调试器会自动打印停止的行。还有source
命令可以打印更多。
source fn
- 打印当前选定的函数source {num}
- 打印范围 [current_line-num; current_line+num] 的行source asm
- 打印当前选定函数的汇编表示
检查数据
当然,你需要一种检查程序数据的方法。
var {expression}|locals
命令用于打印局部和全局变量arg {expression}|all
命令用于打印函数参数
这些命令接受表达式作为输入或具有特殊模式(var locals
打印所有局部变量,args all
打印所有参数)。
表达式
BugStalker 有一种特殊的语法来探索程序数据。您可以取消引用引用,获取结构字段,切片数组或通过其索引从向量中获取元素(等等!)。
表达式中的可用运算符
- 通过名称选择变量(例如,
var a
) - 取消引用指针/引用/智能指针(例如,
var *ref_to_a
) - 获取结构字段(例如,
var some_struct.some_field
) - 从数组、切片、向量、哈希表中通过索引或键获取元素(例如,
var arr[1]
或甚至var hm[{a: 1, b: 2}]
) - 切片数组、向量、切片(例如,
var some_vector[1..3]
或var some_vector[1..]
) - 将常量地址转换为具体类型的指针(例如,
var (*mut SomeType)0x123AABCD
) - 获取地址(例如,
var &some_struct.some_field
) - 显示规范表示(例如,显示向量头而不是向量数据
var ~myvec
) - 括号用于控制运算符的执行顺序
编写表达式很简单,您现在就可以这样做!一些示例
var *some_variable
- 取消引用并打印some_variable
的值var hm[{a: 1, b: *}]
- 打印与键对应的哈希表中的值。文字{a: 1, b: *}
匹配任何具有字段a
等于 1 且字段b
等于任何值的结构var some_array[0][2..5]
- 从索引0的some_array
元素开始打印三个元素var *some_array[0]
- 打印some_array[0]
的解引用值var &some_array[0]
- 打印some_array[0]
的地址var (~some_vec).len
- 打印向量头中的len字段var (*some_array)[0]
- 打印*some_array
的零元素var *(*(var1.field1)).field2[1][2]
- 打印变量var1中field1解引用值的field2索引1索引2处的解引用值 🤡
其他命令
当然,调试器提供了更多命令
symbol {name or regex}
- 打印符号类型和地址memory read {addr}
- 读取调试程序内存(别名:mem read
)memory write {addr} {value}
- 将值写入调试程序内存(别名:mem write
)register read {reg_name}
- 通过名称打印寄存器值(x86_64寄存器名称为小写)(别名:reg read
)register write {reg_name} {value}
- 通过名称设置寄存器的新值(别名:reg write
)register info
- 打印寄存器及其值的列表(别名:reg info
)sharedlib info
- 显示共享库列表quit
- 退出BugStalker(别名:q
)
Tui 界面
BugStalker最有趣的特性之一是在任何时候都可以在老式终端界面和漂亮的tui之间切换。
tui
- 切换到终端ui(在tui中,使用Esc
切换回)
配置
存在一个包含 tui 键绑定配置的 keymap.toml
文件。您可以在以下位置找到默认配置文件:https://github.com/godzie44/BugStalker/tree/master/src/ui/tui/config/preset/keymap.toml。
要覆盖任何默认配置,首先创建相应的文件(从上述链接中获取):~/.config/bs/keymap.toml
。您可以通过导出 KEYMAP_FILE
环境变量来更改键绑定配置文件。
预言机
Oracle 是一个扩展调试器功能的模块。Oracle 可以监视程序的内部状态以显示有趣的信息。例如,tokio Oracle 能够在程序调试期间提供关于 tokio 运行时信息,而无需更改源代码。您必须以启用 Oracle 的方式运行调试器,例如,对于 tokio Oracle
bs --oracle tokio ...
然后使用 oracle
命令来查看 Oracle 信息
oracle {oracle name} {subcommands}
- 运行 Oracle(例如,oracle tokio
)
Oracle 也可用于 tui。目前,只有一个内置 Oracle - tokio Oracle。
贡献
请随意提出更改建议、询问问题或实现新功能。任何贡献都十分欢迎。
如何贡献.
依赖项
~58–89MB
~2M SLoC