Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions docs/scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -866,12 +866,12 @@ trace test_function {
}
```

Options:
The compact syntax is `bt [full|raw] [noinline];`. `backtrace` remains an alias for `bt`.

- `bt raw;` prints raw module cookie, module offset, and runtime IP without source symbolization.
- `bt full;` prints symbolized source-aware frames. Raw IP/cookie debug metadata is kept out of `bt full` and is only shown by `bt raw`.
- `bt inline;` enables inline call-chain rendering. This is the default.
- `bt noinline;` suppresses inline call-chain rendering.
- `bt;` prints source-aware, symbolized frames. Rust compiler disambiguators are hidden by default, so legacy `::h...` suffixes and v0 crate hashes do not clutter normal backtraces.
- `bt full;` keeps those Rust disambiguators in otherwise identical symbolized frames. `full` changes symbol presentation only: it does not collect more frames or variables, change unwinding, or add raw IP/cookie metadata.
- `bt raw;` skips source symbolization and prints the module cookie, module offset, and runtime IP. `raw` and `full` are mutually exclusive.
- Inline call-chain rendering is enabled by default. Append `noinline` to suppress inline pseudo-frames. The explicit `inline` option remains accepted.

Backtrace depth is configured globally, not in the script. Use `--backtrace-depth <N>` or `[ebpf] backtrace_depth = N` in the config file. Valid range is `1..=128`; the default is `128`.
In `--script-output pretty`, backtrace payload lines are colorized when `[script] color` enables ANSI output. `--script-output plain` always emits the raw payload text without ANSI color.
Expand All @@ -880,8 +880,9 @@ Examples:

```ghostscope
trace test_function {
bt full;
bt raw noinline;
bt;
bt full noinline;
bt raw;
}
```

Expand All @@ -895,6 +896,16 @@ backtrace: complete, 4 frames (max 128)
#3 <unknown function> at ?? [libc.so.6+0x2a1ca]
```

For Rust frames, concise and full symbol display differ only in compiler-generated disambiguators:

```text
bt: my_crate::worker
bt full: my_crate::worker::h05af221e174051e9 # legacy mangling
bt full: my_crate[a0b1c2d3]::worker # v0 mangling
```

The exact disambiguator is compiler-generated and may change between builds. Use `full` when distinguishing otherwise identical paths from different crate instances matters.

`bt raw;` keeps the same header but prints machine-facing fields for diagnosis:

```text
Expand Down
25 changes: 18 additions & 7 deletions docs/zh/scripting.md
Original file line number Diff line number Diff line change
Expand Up @@ -874,12 +874,12 @@ trace test_function {
}
```

参数:
紧凑语法为 `bt [full|raw] [noinline];`。`backtrace` 仍是 `bt` 的别名。

- `bt raw;` 输出原始 module cookie、模块内偏移和运行时 IP,不做源码符号化
- `bt full;` 输出符号化的源码感知栈帧。raw IP/cookie 调试元数据不会出现在 `bt full` 中,只由 `bt raw` 显示
- `bt inline;` 输出 inline 调用链;这是默认行为
- `bt noinline;` 关闭 inline 调用链输出
- `bt;` 输出源码感知的符号化栈帧。默认隐藏 Rust 编译器消歧信息,避免 legacy `::h...` 后缀和 v0 crate hash 干扰普通回溯阅读
- `bt full;` 在相同的符号化栈帧中保留这些 Rust 消歧信息。`full` 只改变符号展示:不会采集更多栈帧或变量,不会改变 unwind,也不会增加 raw IP/cookie 元数据
- `bt raw;` 跳过源码符号化,输出 module cookie、模块内偏移和运行时 IP。`raw` 与 `full` 互斥
- 默认输出 inline 调用链;追加 `noinline` 可隐藏 inline 伪栈帧。显式的 `inline` 参数仍然可用

Backtrace 深度是全局配置,不再写在脚本里。使用命令行 `--backtrace-depth <N>`,或在配置文件 `[ebpf]` 中设置 `backtrace_depth = N`。合法范围是 `1..=128`,默认值是 `128`。
在 `--script-output pretty` 下,如果 `[script] color` 启用了 ANSI 输出,backtrace payload 会带颜色。`--script-output plain` 始终输出不带 ANSI 的原始 payload 文本。
Expand All @@ -888,8 +888,9 @@ Backtrace 深度是全局配置,不再写在脚本里。使用命令行 `--bac

```ghostscope
trace test_function {
bt full;
bt raw noinline;
bt;
bt full noinline;
bt raw;
}
```

Expand All @@ -903,6 +904,16 @@ backtrace: complete, 4 frames (max 128)
#3 <unknown function> at ?? [libc.so.6+0x2a1ca]
```

对于 Rust 栈帧,简洁输出与 full 输出的区别仅在编译器生成的消歧信息:

```text
bt: my_crate::worker
bt full: my_crate::worker::h05af221e174051e9 # legacy mangling
bt full: my_crate[a0b1c2d3]::worker # v0 mangling
```

具体消歧值由编译器生成,可能随构建发生变化。需要区分来自不同 crate 实例、但源码路径相同的符号时再使用 `full`。

`bt raw;` 使用相同的 header,但会输出面向排障的机器字段:

```text
Expand Down
23 changes: 17 additions & 6 deletions e2e-tests/tests/common/rust_toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ pub fn compile_standalone_fixture(
source: &Path,
binary: &Path,
) -> anyhow::Result<()> {
compile_fixture(rustc, toolchain, source, binary, true)
compile_fixture(rustc, toolchain, source, binary, true, &["opt-level=0"])
}

pub fn compile_standalone_fixture_with_codegen_options(
rustc: &Path,
toolchain: &str,
source: &Path,
binary: &Path,
codegen_options: &[&str],
) -> anyhow::Result<()> {
compile_fixture(rustc, toolchain, source, binary, true, codegen_options)
}

pub fn compile_compact_standalone_fixture(
Expand All @@ -32,7 +42,7 @@ pub fn compile_compact_standalone_fixture(
source: &Path,
binary: &Path,
) -> anyhow::Result<()> {
compile_fixture(rustc, toolchain, source, binary, false)
compile_fixture(rustc, toolchain, source, binary, false, &["opt-level=0"])
}

fn compile_fixture(
Expand All @@ -41,12 +51,13 @@ fn compile_fixture(
source: &Path,
binary: &Path,
link_dead_code: bool,
codegen_options: &[&str],
) -> anyhow::Result<()> {
let mut command = Command::new(rustc);
command
.args(["--edition=2018", "-g"])
.arg("-C")
.arg("opt-level=0");
command.args(["--edition=2018", "-g"]);
for option in codegen_options {
command.arg("-C").arg(option);
}
if link_dead_code {
command.arg("-C").arg("link-dead-code");
}
Expand Down
40 changes: 40 additions & 0 deletions e2e-tests/tests/fixtures/rust_backtrace_program/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#![crate_name = "rust_backtrace_program"]

use std::hint::black_box;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
use std::time::Duration;

static RESULT: AtomicUsize = AtomicUsize::new(0);

#[no_mangle]
#[inline(never)]
pub extern "C" fn rust_backtrace_probe(value: usize) -> usize {
black_box(value.wrapping_add(1))
}

#[inline(always)]
fn rust_backtrace_inline(value: usize) -> usize {
rust_backtrace_probe(value) // INLINE_BACKTRACE_TRACE_POINT
}

#[inline(never)]
fn rust_backtrace_middle(value: usize) -> usize {
let result = rust_backtrace_inline(value);
black_box(result.wrapping_mul(3))
}

#[inline(never)]
fn rust_backtrace_outer(value: usize) -> usize {
let result = rust_backtrace_middle(value);
black_box(result.wrapping_add(value))
}

fn main() {
let mut value = 1usize;
loop {
value = rust_backtrace_outer(value);
RESULT.store(value, Ordering::Relaxed);
thread::sleep(Duration::from_millis(25));
}
}
Loading
Loading