Issue: #162 — Please add support for FreeBSD 分析日期: 2026-05-14
| 項目 | 評估 |
|---|---|
| 可行性 | ✅ 可行 — FreeBSD 具備所有核心能力 (ptrace, procfs, process memory access) |
| 工作量 | 🔶 中大型 — 約 15–25 工程師天 (僅 x86_64, 有 Linux 經驗) |
| 主要風險 | procfs 格式差異大、無 /proc/<pid>/task/、DSO debug 移植困難 |
| 好消息 | FreeBSD 14+ 有 PT_COREDUMP、nix crate 支援 FreeBSD ptrace |
Issue #162 要求為 minidump-writer crate 新增 FreeBSD 平台支援。
- 來源: crash-handling#108 討論串
- 影響: FreeBSD 版 Zed 編輯器 因此卡在
v0.198.6,無法升級(新版依賴不支援 FreeBSD 的crash-handlercrate) - 維護者態度: 願意 mentor、review 和 merge 貢獻,但無餘力自行實作
- 關鍵線索: FreeBSD 有
ptrace()與 Linux 相似,預期移植工作量不算太大
src/linux/ 共 33 個檔案,依平台相依性分三類:
| 檔案 | 用途 | Linux 特定 API | FreeBSD 替代方案 |
|---|---|---|---|
process_reader.rs |
讀取目標行程記憶體 | process_vm_readv, /proc/pid/mem, PTRACE_PEEKDATA |
PT_IO (bulk read), /proc/pid/mem |
maps_reader.rs |
記憶體映射列舉 | /proc/pid/maps + procfs-core crate |
kinfo_getvmmap() 或 /proc/pid/map |
minidump_writer/mod.rs |
核心 writer 協調 | ptrace::attach/cont/detach, waitpid(__WALL), SIGSTOP, /proc/pid/stat, /proc/pid/task/ |
PT_ATTACH/PT_CONTINUE/PT_DETACH, sysctl KERN_PROC_* |
thread_info/*.rs |
暫存器讀取 | PTRACE_GETREGSET, PTRACE_GETREGS, NT_PRSTATUS |
PT_GETREGS, PT_GETFPREGS + struct reg |
auxv/mod.rs + reader.rs |
ELF auxiliary vector | /proc/pid/auxv + AT_SYSINFO_EHDR |
sysctl KERN_PROC_AUXV (無 vDSO) |
dumper_cpu_info/x86.rs |
CPU 資訊 | /proc/cpuinfo |
sysctl hw.model, hw.ncpu |
minidump_writer/memory_info_list_stream.rs |
Memory info stream | procfs_core::MemoryMaps |
kinfo_getvmmap() 轉換 |
minidump_writer/handle_data_stream.rs |
FD 列舉 | /proc/pid/fd + readlink |
kinfo_getfiles() 或 /proc/pid/fd |
crash_context/x86_64.rs |
ucontext 轉換 | REG_RIP, REG_RSP 等 glibc 常數 |
FreeBSD struct reg 欄位名不同 (r_rip, r_rsp) |
| 檔案 | 原因 |
|---|---|
dso_debug.rs |
讀取 r_debug/link_map — FreeBSD rtld 結構不同,可能需大幅改動或暫時省略 |
android.rs |
Android 專用,FreeBSD 不需要 |
maps_reader.rs 中的 vdso/linux-gate 處理 |
FreeBSD 沒有 vDSO |
| 檔案 | 原因 |
|---|---|
module_reader.rs |
ELF 解析 (goblin) — FreeBSD 也是 ELF,完全通用 |
app_memory.rs |
純資料結構 |
serializers.rs |
序列化工具 |
minidump_writer/ 子 stream writers (多數) |
呼叫 copy_from_process 的上層邏輯可重用 |
| 功能 | Linux | FreeBSD |
|---|---|---|
| 附加 | PTRACE_ATTACH |
PT_ATTACH |
| 分離 | PTRACE_DETACH |
PT_DETACH |
| 繼續 | PTRACE_CONT |
PT_CONTINUE |
| 讀暫存器 | PTRACE_GETREGSET + NT_PRSTATUS |
PT_GETREGS (直接取得 struct reg) |
| 讀 FP 暫存器 | PTRACE_GETREGSET + NT_PRFPREGSET |
PT_GETFPREGS |
| 讀記憶體 (word) | PTRACE_PEEKDATA |
PT_READ_D |
| 讀記憶體 (bulk) | process_vm_readv() |
PT_IO + PIOD_READ_D ✨ |
| 核心傾印 | N/A | PT_COREDUMP (FreeBSD 14+) ✨ |
| 暫停執行緒 | SIGSTOP + PTRACE_ATTACH |
PT_SUSPEND |
亮點:FreeBSD 的 PT_IO 可一次讀取任意長度記憶體,比 Linux word-by-word PTRACE_PEEKDATA 高效得多。
| 資訊 | Linux | FreeBSD |
|---|---|---|
| 記憶體映射 | /proc/pid/maps (6 欄位, 純文字) |
/proc/pid/map (10+ 欄位, 不同格式) 或 kinfo_getvmmap() |
| Thread 列舉 | /proc/pid/task/ 目錄 |
無 — 需 sysctl KERN_PROC_THREADS 或 libprocstat |
| auxv | /proc/pid/auxv (binary) |
sysctl KERN_PROC_AUXV 或 /proc/pid/auxv |
| CPU 資訊 | /proc/cpuinfo |
sysctl hw.model, hw.ncpu, hw.machine |
| 記憶體讀取 | /proc/pid/mem |
/proc/pid/mem ✅ |
| 可執行路徑 | /proc/pid/exe symlink |
/proc/pid/file symlink |
// Linux struct user_regs_struct:
r15, r14, r13, r12, rbp, rbx, r11, r10,
r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax,
rip, eflags, rsp, cs, ss, ...
// FreeBSD struct reg:
r_r15, r_r14, r_r13, r_r12, r_rbp, r_rbx, r_r11, r_r10,
r_r9, r_r8, r_rax, r_rcx, r_rdx, r_rsi, r_rdi,
r_rflags, r_rip, r_rsp
// 注意: 無 orig_rax, 無 segment registers (cs, ss 等)| 常數 | Linux | FreeBSD | 備註 |
|---|---|---|---|
AT_PHDR |
✅ | ✅ | Program header 地址 |
AT_PHNUM |
✅ | ✅ | Program header 數量 |
AT_ENTRY |
✅ | ✅ | 進入點 |
AT_SYSINFO_EHDR |
✅ | ❌ | FreeBSD 無 vDSO |
AT_RANDOM |
✅ | ❌ | FreeBSD 用不同機制 |
AT_BASE |
✅ | ❌ | — |
AT_EXECPATH |
❌ | ✅ | FreeBSD 特有 |
AT_NCPUS |
❌ | ✅ | FreeBSD 特有 |
FreeBSD 也提供 elf_aux_info() 函式可直接查詢 auxv 值。
仿照 Linux 模式,逐步實作每個子系統:
- ProcessReader — 用
PT_IO(PIOD_READ_D) 讀記憶體 +/proc/pid/mem回退 - MapsReader — 用
kinfo_getvmmap()(sysctl wrapper) 取得映射 - ThreadInfo —
sysctl KERN_PROC_THREADS列舉 +PT_GETREGS/PT_GETFPREGS取暫存器 - AuxvReader —
sysctl KERN_PROC_AUXV - CpuInfo —
sysctl hw.model, hw.ncpu - CrashContext — FreeBSD
ucontext_t→ minidumpRawContextCPU映射 - DSO Debug — 初期可省略或簡化
優點:完整控制、可重用大部分 minidump stream writer、可測試每個子系統 缺點:工作量較大
利用 FreeBSD 14+ 的 ptrace(PT_COREDUMP) 生成 core file,再用 minidump crate 解析轉換:
ptrace(PT_ATTACH, pid, NULL, 0);
waitpid(pid, &status, 0);
struct ptrace_coredump pc = {
.pc_fd = fd, // 寫入的 file descriptor
.pc_flags = 0, // 或 PC_COMPRESS | PC_ALL
.pc_limit = 0, // 大小限制 (0 = 無限制)
};
ptrace(PT_COREDUMP, pid, &pc, sizeof(pc));
ptrace(PT_DETACH, pid, NULL, 0);優點:kernel 幫你做完大部分工作 缺點:依賴 FreeBSD 14+、core→minidump 轉換需額外實作、控制粒度較粗
| 檔案 | 改動 |
|---|---|
src/lib.rs |
cfg_if 加入 else if #[cfg(target_os = "freebsd")] { mod freebsd; pub use freebsd::*; } |
src/module_reader.rs |
加入 #[cfg(target_os = "freebsd")] re-export |
src/process_reader.rs |
加入 #[cfg(target_os = "freebsd")] re-export |
Cargo.toml |
加入 [target.'cfg(target_os = "freebsd")'.dependencies] |
src/bin/test.rs |
加入 FreeBSD 分支實作 test child commands |
tests/freebsd_minidump_writer.rs |
新增 — 複製 Linux 測試並調整 |
src/freebsd/
├── mod.rs # 模組根 + pub type Pid = i32
├── minidump_writer/
│ ├── mod.rs # MinidumpWriter + MinidumpWriterConfig
│ ├── errors.rs # WriterError 等
│ ├── thread_list_stream.rs # (可複用 Linux 版)
│ ├── thread_names_stream.rs # 需改用 sysctl 取 thread name
│ ├── systeminfo_stream.rs # sysctl 取 CPU/OS 資訊
│ ├── memory_info_list_stream.rs # kinfo_getvmmap 轉換
│ ├── mappings.rs # (可複用大部分)
│ ├── exception_stream.rs # (可複用大部分)
│ ├── handle_data_stream.rs # kinfo_getfiles 或 /proc/pid/fd
│ ├── app_memory.rs # (可複用)
│ └── memory_list_stream.rs # (可複用)
├── process_reader.rs # PT_IO + /proc/pid/mem
├── maps_reader.rs # kinfo_getvmmap() 或 /proc/pid/map
├── thread_info/
│ ├── mod.rs # FreeBSD thread 列舉 + 暫存器讀取
│ └── x86.rs # struct reg → RawContextCPU
├── module_reader.rs # (可複用 Linux 版或直接 re-export)
├── auxv.rs # sysctl KERN_PROC_AUXV
├── crash_context/
│ ├── mod.rs
│ └── x86_64.rs # FreeBSD ucontext_t 映射
├── dumper_cpu_info.rs # sysctl hw.model, hw.ncpu
├── dso_debug.rs # 初期可省略
├── app_memory.rs # (可複用)
└── serializers.rs # (可複用)
| 風險 | 嚴重度 | 說明 |
|---|---|---|
procfs-core crate 不支援 FreeBSD |
🔴 高 | 需要替代方案 (kinfo_getvmmap 等),或自己寫 /proc/pid/map parser |
nix 缺少 PT_IO/PT_COREDUMP 綁定 |
🟡 中 | 需直接用 libc::ptrace() 或貢獻上游 |
DSO debug (r_debug/link_map) |
🟡 中 | FreeBSD rtld 結構不同,初期可省略此 stream |
| Thread 列舉無 procfs | 🟡 中 | 需透過 sysctl 或 libprocstat |
| CI 測試環境 | 🟡 中 | 需 FreeBSD runner 或 QEMU |
| FreeBSD 14+ 限定功能 | 🟢 低 | PT_COREDUMP 是額外選項,不阻塞基本功能 |
ptrace(2)— PT_ATTACH, PT_IO, PT_GETREGS, PT_COREDUMPkinfo_getvmmap(3)— 記憶體映射kinfo_getproc(3)— 行程資訊sysctl(3)— KERN_PROC_* MIBsprocfs(5)— /proc 佈局
- Breakpad: 無 BSD 支援,但有完整的 Linux 實作可參考 (
src/client/linux/minidump_writer/) - Crashpad: 無 BSD 支援
- nix crate:
src/sys/ptrace/bsd.rs— FreeBSD ptrace 綁定(缺少 PT_IO/PT_COREDUMP)
- EmbarkStudios/crash-handling#108 — 原始需求討論
- rust-minidump/minidump-writer#162 — 本 Issue
FreeBSD 支援完全可行。核心 ptrace 機制相似,且 FreeBSD 的 PT_IO 在記憶體讀取上比 Linux 更優雅。主要工作量在於:
- 替換 procfs 依賴 —
procfs-corecrate 無法在 FreeBSD 使用,需改用kinfo_getvmmap()+sysctl - 重寫 thread 列舉 — 沒有
/proc/pid/task/,需 sysctl - 適應暫存器結構 — 欄位名不同但語義相同
- 新增 Cargo 目標 — FreeBSD 條件依賴
建議從 路線 A (手動組裝) 開始,先實作 x86_64 架構,驗證基本 minidump 生成後再擴展。