#gdb #stack-frame #tui

bin+lib bugstalker

BugStalker 是一个用于 Rust 应用的现代轻量级调试器

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 调试

Download history 156/week @ 2024-05-03 8/week @ 2024-05-10 13/week @ 2024-05-17 4/week @ 2024-05-24 193/week @ 2024-05-31 41/week @ 2024-06-07 207/week @ 2024-06-14 13/week @ 2024-06-21 11/week @ 2024-06-28 7/week @ 2024-07-05 9/week @ 2024-07-12 16/week @ 2024-07-19 154/week @ 2024-07-26 13/week @ 2024-08-02

每月 183 次下载

MIT 许可证

1MB
25K SLoC

BugStalker

Linux x86-64 的现代调试器。用 Rust 编写,用于 Rust 程序。

debugger-demo


目录


支持的 rustc 版本

  • 1.75
  • 1.76
  • 1.77
  • 1.78
  • 1.79
  • 1.80

特性


安装

首先检查是否安装了必要的依赖项(pkg-configlibunwind-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

发行版软件包

打包状态

Packaging status

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 环境变量来更改键绑定配置文件。

预言机

演示控制台

演示 tui

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