2个稳定版本
1.74.1 | 2023年12月11日 |
---|---|
1.74.0 | 2023年12月8日 |
#217 in 调试
在 firedbg-stream-indexer 中使用
435KB
11K SLoC
FireDBG调试引擎(用于Rust)
基于 lldb.
此库免于semver版本控制。版本号旨在跟踪rustc的版本。
调试器配置
可以通过环境变量FIREDBG_RUST_CONFIG
来设置配置。例如:FIREDBG_RUST_CONFIG=MAX_ARRAY_SIZE=100;DONT_TRACE_ALLOCATION
键 | 类型 | 描述 |
---|---|---|
MAX_ARRAY_SIZE |
usize |
数组、字符串和其他容器中的最大项目数 |
RECURSIVE_DEREF_LIMIT |
usize |
递归限制;即限制二叉树的深度 |
KEEP_HASH_ORDER |
bool |
如果设置,不要按哈希键排序哈希表 |
DONT_TRACE_ALLOCATION |
bool |
如果设置,不要跟踪堆分配 |
指令集
目前支持x64(即amd64)和arm64(即aarch64)。为每个平台提供了大量的汇编解析和寄存器操作。代码库中对指针是8字节有一些假设。支持新的架构需要相当大的努力,但我们愿意进行商业合作。
操作系统
目前没有特定于操作系统的代码。在Linux和macOS上使用lldb。但在macOS上,我们将连接到主机的lldb-server
。如果我们决定原生支持Windows,我们需要创建一个Windows后端。
必须为与目标二进制文件相同的平台编译debugger
二进制文件。此外,我们假设它们都使用相同的rustc
(不一定是完全相同的,但应与彼此兼容)。
标准库类型
我们打算内置所有标准库类型的处理。对于 HashMap
,使用的是 frozen-hashbrown。未来,我们希望开放脚本接口(可能通过 rhai)来处理供应商库类型(例如 DateTime
、Decimal
),类似于 Natvis 的方式。
二进制值格式
序列化 Rust 值的格式可以通过阅读 SourceReader::read_values()
来最好地理解,它在 reader.rs
中。这应该是相当直接的,唯一棘手的部分是 ReaderContext
,它是用于解析内存引用的。
返回值捕获
这非常依赖于架构。我们试图在函数返回时捕获返回值,即在 ret
指令处。并非所有内容都在栈上,有时返回值将通过寄存器传递。
根据 Rust 的 ABI 规范,这意味着如果返回值是
-
一个或两个原语,每个都不大于 64 位。这包括
(i64, i64)
和struct { a: i64, b: i64 }
。 -
一个
i128
/u128
;将被拆分为rax
/rdx
-
一个或两个
f32
/f64
;将放在xmm0
/xmm1
-
Option<T>
和Result<T, E>
;其中T
&E
不大于 64 位枚举区分符在
rax
中,其中类型 T E Option
Some = 1
None = 0
Result
Ok = 0
Err = 1
并且
T
/E
将在rdx
中。
不幸的是,这比 上面的摘要 要复杂得多。目前实现非常混乱,完全基于启发式方法。如果我们有机会正确地做这件事,也许我们可以生成 Rust 代码并检查汇编(系统性地)。假设我们的返回类型是 (T, F)
fn probe() -> (T, F) { todo!() }
fn extractor() {
let res = probe();
std::hint::black_box(&res);
}
如果我们反汇编二进制文件,我们应该看到
extractor:
call probe
mov ..
call black_box
所以在 probe
和 black_box
之间,会有一些内存操作,最终将整个结构体写入栈中,然后地址将存储在 rax
/ x0
中。
应该有更好的方法来做这件事,如果你有想法,请开一个讨论线程!
堆分配
目前仍处于工作状态。我们现在可以跟踪所有 Box
、Rc
、Arc
分配,因此我们可以提取 Box<dyn T>
的内容。待办事项是跟踪释放并输出信息到专用事件流。
依赖关系
~11–25MB
~337K SLoC