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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 112 additions & 2 deletions config-zh.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,35 @@ enable_logging = true
log_level = "trace"

[dwarf]
# DWARF 调试信息搜索路径(用于未来的 --debug-file 自动发现功能)
# 目前未实现,为未来使用保留
# DWARF 调试信息搜索路径(用于 .gnu_debuglink 文件)
#
# 当二进制文件使用 .gnu_debuglink 引用独立的调试文件时,
# GhostScope 会在这些路径中搜索调试文件。
#
# 搜索顺序(优先级从高到低):
# 1. 绝对路径(如果 .gnu_debuglink 包含绝对路径 - 罕见)
# 2. 用户配置的 search_paths + basename(此处配置)
# 3. 二进制文件所在目录 + basename
# 4. 二进制文件所在目录的 .debug 子目录 + basename
#
# 对于每个用户配置的路径,会检查两种位置:
# - <路径>/debug_文件名
# - <路径>/.debug/debug_文件名
#
# 特性:
# - 主目录展开:"~/" 会被替换为你的主目录
# - 自动去除重复路径以避免冗余检查
# - 按顺序尝试路径,直到找到匹配的调试文件
#
# 常用搜索路径:
# - 系统调试符号:"/usr/lib/debug"(用于已安装的调试包)
# - 本地调试符号:"/usr/local/lib/debug"
# - 用户特定: "~/.local/lib/debug"
# - 自定义构建输出:"/path/to/build/debug"
#
# 注意:.gnu_debuglink 通常使用 basename(相对路径),但也支持绝对路径。
# 如需使用系统范围的调试目录(如 /usr/lib/debug),请添加到 search_paths。
#
# 默认值:["/usr/lib/debug", "/usr/local/lib/debug"]
search_paths = [
"/usr/lib/debug",
Expand Down Expand Up @@ -96,3 +123,86 @@ output_dir = "."
# 自动生成的实时日志文件的默认文件名前缀
# 默认值:"ghostscope_session"
filename_prefix = "ghostscope_session"

[ebpf]
# RingBuf 映射大小(字节,必须是 2 的幂)
# 控制用于从内核向用户空间传输跟踪事件的环形缓冲区大小。
# 较大的尺寸允许缓冲更多事件,但会消耗更多内核内存。
# 有效范围:4096 (4KB) 到 16777216 (16MB)
# 推荐值:
# - 低频追踪:131072 (128KB)
# - 中频追踪:262144 (256KB)
# - 高频追踪:524288 (512KB) 或 1048576 (1MB)
# 默认值:262144 (256KB)
ringbuf_size = 262144

# ASLR 地址转换的最大 (pid, module) 偏移条目数
# 此映射存储每个进程中每个已加载模块的运行时地址偏移。
# 每个条目存储 text/rodata/data/bss 段的偏移量。
# 有效范围:64 到 65536
# 推荐值:
# - 单进程:1024
# - 多进程:4096
# - 系统范围追踪:8192 或 16384
# 默认值:4096
proc_module_offsets_max_entries = 4096

# PerfEventArray 页数(每个 CPU 的 perf 缓冲区页数)
# 仅在选择 PerfEventArray 时使用(内核 < 5.8 或 force_perf_event_array=true 时)
# 必须是 2 的幂。大多数系统上每页为 4KB。
# 有效范围:1 到 512 页
# 推荐值:
# - 低频追踪:8 页 (每 CPU 32KB)
# - 中频追踪:32 页 (每 CPU 128KB)
# - 高频追踪:64 页 (每 CPU 256KB)
# 默认值:32 (每 CPU 128KB)
perf_page_count = 32

# 强制使用 PerfEventArray 而不是 RingBuf(仅用于测试)
# 警告:仅用于测试目的。正常情况下系统会自动检测内核能力,
# 并使用 RingBuf(内核 >= 5.8)或回退到 PerfEventArray。
# 设置为 true 可在支持 RingBuf 的内核上强制使用 PerfEventArray。
# 默认值:false
force_perf_event_array = false

# 源代码路径配置
# 当 DWARF 调试信息中包含的编译时路径与运行时路径不同时,
# 使用这些设置帮助 ghostscope 定位实际的源文件。

[source]
# 路径替换规则(首先应用,优先级最高)
# 将编译时路径前缀替换为运行时路径前缀。
# 适用于源代码在不同机器上编译或移动到新位置的情况。
#
# 使用场景示例:
# - 在 CI 服务器上编译:/home/build/project -> /home/user/work/project
# - 内核源码移动:/usr/src/linux-5.15 -> /home/user/kernel/linux-5.15
# - 交叉编译:/buildroot/arm/src -> /local/embedded/src
#
# 格式:数组,包含 { from = "编译路径前缀", to = "运行时路径前缀" }
substitutions = [
# { from = "/home/build/myproject", to = "/home/user/work/myproject" },
# { from = "/usr/src/linux", to = "/home/user/kernel/linux" },
]

# 附加搜索目录(替换失败时的回退方案)
# 当通过替换无法找到源文件时,ghostscope 将在这些目录中
# 按文件名(basename 匹配)进行搜索。
# 类似于 GDB 的 "directory" 命令。
#
# 格式:目录路径数组
search_dirs = [
# "/home/user/sources",
# "/opt/local/src",
]

# 运行时配置:
# 你也可以使用 'srcpath' 命令交互式配置源路径:
# srcpath - 显示当前配置
# srcpath map <from> <to> - 添加路径替换规则
# srcpath add <directory> - 添加搜索目录
# srcpath remove <path> - 移除规则
# srcpath clear - 清除所有运行时规则
# srcpath reset - 重置为配置文件规则
#
# 运行时规则优先于配置文件规则,且不会持久化保存。
32 changes: 30 additions & 2 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,36 @@ enable_logging = true
log_level = "trace"

[dwarf]
# DWARF debug information search paths (for future --debug-file auto-discovery)
# Currently not implemented, reserved for future use
# DWARF debug information search paths for .gnu_debuglink files
#
# When a binary uses .gnu_debuglink to reference separate debug files,
# GhostScope searches these paths to locate the debug file.
#
# Search order (highest priority first):
# 1. Absolute path (if .gnu_debuglink contains an absolute path - rare)
# 2. User-configured search_paths + basename (configured here)
# 3. Same directory as the binary + basename
# 4. .debug subdirectory next to the binary + basename
#
# For each user-configured path, both direct and .debug subdirectory are checked:
# - <path>/debug_filename
# - <path>/.debug/debug_filename
#
# Features:
# - Home directory expansion: "~/" is replaced with your home directory
# - Duplicate paths are automatically removed to avoid redundant checks
# - Paths are tried in order until a matching debug file is found
#
# Common search paths:
# - System debug symbols: "/usr/lib/debug" (for installed debug packages)
# - Local debug symbols: "/usr/local/lib/debug"
# - User-specific: "~/.local/lib/debug"
# - Custom build output: "/path/to/build/debug"
#
# Note: .gnu_debuglink typically uses basename (relative path), but absolute paths
# are also supported. If you need system-wide debug directories like /usr/lib/debug,
# add them to search_paths.
#
# Default: ["/usr/lib/debug", "/usr/local/lib/debug"]
search_paths = [
"/usr/lib/debug",
Expand Down
46 changes: 39 additions & 7 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,18 @@ ghostscope --debug-file /path/to/binary.debug

# Auto-detection searches in order:
# 1. Binary itself (.debug_info sections)
# 2. .gnu_debuglink section
# 2. .gnu_debuglink section (see search paths below)
# 3. .gnu_debugdata section (Android/compressed)
# 4. /usr/lib/debug, /usr/local/lib/debug
# 5. Build-ID based paths
# 6. binary.debug, binary.dbg
# 4. Build-ID based paths

# .gnu_debuglink search paths (configurable in config.toml):
# 1. Absolute path (if .gnu_debuglink contains absolute path - rare)
# 2. User-configured search_paths + basename (highest priority)
# 3. Same directory as the binary + basename
# 4. .debug subdirectory next to the binary + basename
#
# Note: To use system-wide debug directories like /usr/lib/debug,
# add them to search_paths in config.toml
```

### Logging Configuration
Expand Down Expand Up @@ -176,10 +183,35 @@ enable_console_logging = false
log_level = "warn"

[dwarf]
# Debug information search paths
# Debug information search paths for .gnu_debuglink files
# When a binary uses .gnu_debuglink to reference separate debug files,
# GhostScope searches these paths to locate the debug file.
#
# Search order (highest priority first):
# 1. Absolute path (if .gnu_debuglink contains an absolute path - rare)
# 2. User-configured search_paths + basename (configured here)
# 3. Same directory as the binary + basename
# 4. .debug subdirectory next to the binary + basename
#
# For each user-configured path, both direct and .debug subdirectory are checked:
# - <path>/debug_filename
# - <path>/.debug/debug_filename
#
# Features:
# - Home directory expansion: "~/" is replaced with your home directory
# - Duplicate paths are automatically removed to avoid redundant checks
# - Paths are tried in order until a matching debug file is found
#
# Note: .gnu_debuglink typically uses basename (relative path), but absolute paths
# are also supported. If you need system-wide debug directories like /usr/lib/debug,
# add them to search_paths.
#
# Examples:
search_paths = [
"/usr/lib/debug",
"/usr/local/lib/debug"
"/usr/lib/debug", # System debug symbols (for installed packages)
"/usr/local/lib/debug", # Local debug symbols
"~/.local/lib/debug", # User debug symbols (~ expands to home)
"/opt/debug-symbols" # Custom debug symbol server
]

[files]
Expand Down
2 changes: 2 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ GhostScope automatically searches for debug files in the following locations:
2. `.debug` subdirectory: `/path/to/.debug/your_program.debug`
3. Global debug directory: `/usr/lib/debug/path/to/your_program.debug`

> **📝 Custom Search Paths**: You can configure additional search paths (including user-specific directories like `~/.local/lib/debug`) in the configuration file. See the [Configuration Reference - DWARF Debug Search Paths](configuration.md#dwarf) for detailed information.

**Installing system debug packages:**
```bash
# Ubuntu/Debian - install debug symbols for libc
Expand Down
45 changes: 38 additions & 7 deletions docs/zh/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,18 @@ ghostscope --debug-file /path/to/binary.debug

# 自动检测按以下顺序搜索:
# 1. 二进制文件本身(.debug_info 节)
# 2. .gnu_debuglink 节
# 2. .gnu_debuglink 节(参见下方搜索路径)
# 3. .gnu_debugdata 节(Android/压缩格式)
# 4. /usr/lib/debug, /usr/local/lib/debug
# 5. 基于 Build-ID 的路径
# 6. binary.debug, binary.dbg
# 4. 基于 Build-ID 的路径

# .gnu_debuglink 搜索路径(可在 config.toml 中配置):
# 1. 绝对路径(如果 .gnu_debuglink 包含绝对路径 - 罕见)
# 2. 用户配置的 search_paths + basename(最高优先级)
# 3. 二进制文件同目录 + basename
# 4. 二进制文件同目录的 .debug 子目录 + basename
#
# 注意:如需使用系统范围的调试目录(如 /usr/lib/debug),
# 请在 config.toml 的 search_paths 中添加
```

### 日志配置
Expand Down Expand Up @@ -176,10 +183,34 @@ enable_console_logging = false
log_level = "warn"

[dwarf]
# 调试信息搜索路径
# DWARF 调试信息搜索路径(用于 .gnu_debuglink 文件)
# 当二进制文件使用 .gnu_debuglink 引用独立的调试文件时,
# GhostScope 会在这些路径中搜索调试文件。
#
# 搜索顺序(优先级从高到低):
# 1. 绝对路径(如果 .gnu_debuglink 包含绝对路径 - 罕见)
# 2. 用户配置的 search_paths + basename(此处配置)
# 3. 二进制文件所在目录 + basename
# 4. 二进制文件所在目录的 .debug 子目录 + basename
#
# 对于每个用户配置的路径,会检查两种位置:
# - <路径>/debug_文件名
# - <路径>/.debug/debug_文件名
#
# 特性:
# - 主目录展开:"~/" 会被替换为你的主目录
# - 自动去除重复路径以避免冗余检查
# - 按顺序尝试路径,直到找到匹配的调试文件
#
# 注意:.gnu_debuglink 通常使用 basename(相对路径),但也支持绝对路径。
# 如需使用系统范围的调试目录(如 /usr/lib/debug),请添加到 search_paths。
#
# 示例:
search_paths = [
"/usr/lib/debug",
"/usr/local/lib/debug"
"/usr/lib/debug", # 系统调试符号(用于已安装的软件包)
"/usr/local/lib/debug", # 本地调试符号
"~/.local/lib/debug", # 用户调试符号(~ 会展开为主目录)
"/opt/debug-symbols" # 自定义调试符号服务器
]

[files]
Expand Down
2 changes: 2 additions & 0 deletions docs/zh/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ GhostScope 会自动在以下位置搜索调试文件:
2. `.debug` 子目录:`/path/to/.debug/your_program.debug`
3. 全局调试目录:`/usr/lib/debug/path/to/your_program.debug`

> **📝 自定义搜索路径**:你可以在配置文件中配置额外的搜索路径(包括用户特定目录如 `~/.local/lib/debug`)。详细信息请参阅 [配置参考 - DWARF 调试搜索路径](configuration.md#dwarf)。

**安装系统调试包:**
```bash
# Ubuntu/Debian - 安装 libc 的调试符号
Expand Down
3 changes: 3 additions & 0 deletions ghostscope-dwarf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ libc = "0.2"
# For .gnu_debuglink CRC validation
crc32fast = "1.4"

# For home directory expansion in debug search paths
dirs = "5.0"

34 changes: 30 additions & 4 deletions ghostscope-dwarf/src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,23 @@ impl DwarfAnalyzer {

/// Create DWARF analyzer from PID using parallel loading
pub async fn from_pid_parallel(pid: u32) -> Result<Self> {
Self::from_pid_parallel_with_progress(pid, |_event| {}).await
Self::from_pid_parallel_with_config(pid, &[], |_event| {}).await
}

/// Create DWARF analyzer from PID using parallel loading with progress callback
pub async fn from_pid_parallel_with_progress<F>(pid: u32, progress_callback: F) -> Result<Self>
where
F: Fn(ModuleLoadingEvent) + Send + Sync + 'static,
{
Self::from_pid_parallel_with_config(pid, &[], progress_callback).await
}

/// Create DWARF analyzer from PID using parallel loading with debug search paths and progress callback
pub async fn from_pid_parallel_with_config<F>(
pid: u32,
debug_search_paths: &[String],
progress_callback: F,
) -> Result<Self>
where
F: Fn(ModuleLoadingEvent) + Send + Sync + 'static,
{
Expand All @@ -164,8 +176,14 @@ impl DwarfAnalyzer {
}

// Load all modules in parallel with progress tracking
let modules = crate::loader::ModuleLoader::new(module_mappings)
.parallel()
let mut loader = crate::loader::ModuleLoader::new(module_mappings).parallel();

// Configure debug search paths if provided
if !debug_search_paths.is_empty() {
loader = loader.with_debug_search_paths(debug_search_paths.to_vec());
}

let modules = loader
.with_progress_callback(progress_callback)
.load()
.await?;
Expand All @@ -181,6 +199,14 @@ impl DwarfAnalyzer {

/// Create DWARF analyzer from executable path (single module mode, now async parallel)
pub async fn from_exec_path<P: AsRef<std::path::Path>>(exec_path: P) -> Result<Self> {
Self::from_exec_path_with_config(exec_path, &[]).await
}

/// Create DWARF analyzer from executable path with debug search paths
pub async fn from_exec_path_with_config<P: AsRef<std::path::Path>>(
exec_path: P,
debug_search_paths: &[String],
) -> Result<Self> {
let exec_path = exec_path.as_ref().to_path_buf();
tracing::info!(
"Creating DWARF analyzer for executable: {}",
Expand All @@ -201,7 +227,7 @@ impl DwarfAnalyzer {
};

// Load the single module using parallel loading
match ModuleData::load_parallel(module_mapping).await {
match ModuleData::load_parallel(module_mapping, debug_search_paths).await {
Ok(module_data) => {
analyzer.modules.insert(exec_path.clone(), module_data);
tracing::info!(
Expand Down
Loading