ghostscope_dwarf/semantics/
unwind_plan.rs1use crate::core::{ModuleId, PlanExprOp};
2
3#[derive(Debug, Clone, PartialEq)]
5pub struct CompactUnwindTable {
6 pub module: ModuleId,
7 pub rows: Vec<CompactUnwindRow>,
8 pub diagnostics: Vec<UnwindDiagnostic>,
9}
10
11impl CompactUnwindTable {
12 pub fn row_for_pc(&self, pc: u64) -> Option<&CompactUnwindRow> {
13 self.rows
14 .iter()
15 .find(|row| row.pc_start <= pc && pc < row.pc_end)
16 }
17
18 pub fn stats(&self) -> CompactUnwindStats {
19 let bpf_supported_rows = self.rows.iter().filter(|row| row.bpf_supported).count();
20 CompactUnwindStats {
21 row_count: self.rows.len(),
22 bpf_supported_rows,
23 unsupported_rows: self.rows.len().saturating_sub(bpf_supported_rows),
24 diagnostic_count: self.diagnostics.len(),
25 }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct CompactUnwindStats {
31 pub row_count: usize,
32 pub bpf_supported_rows: usize,
33 pub unsupported_rows: usize,
34 pub diagnostic_count: usize,
35}
36
37#[derive(Debug, Clone, PartialEq)]
38pub struct CompactUnwindRow {
39 pub module: ModuleId,
40 pub pc_start: u64,
41 pub pc_end: u64,
42 pub cfa: CfaRulePlan,
43 pub return_address_register: u16,
44 pub return_address: RegisterRecoveryPlan,
45 pub sp: Option<RegisterRecoveryPlan>,
46 pub rbp: Option<RegisterRecoveryPlan>,
47 pub bpf_supported: bool,
48}
49
50#[derive(Debug, Clone, PartialEq)]
51pub enum CfaRulePlan {
52 RegPlusOffset { register: u16, offset: i64 },
53 Expression { steps: Vec<PlanExprOp> },
54 Unsupported { reason: String },
55}
56
57impl CfaRulePlan {
58 pub fn is_bpf_fast_path_supported(&self) -> bool {
59 matches!(
60 self,
61 Self::RegPlusOffset {
62 register: 6 | 7,
63 ..
64 }
65 )
66 }
67}
68
69#[derive(Debug, Clone, PartialEq)]
70pub enum RegisterRecoveryPlan {
71 Undefined,
72 SameValue {
73 register: u16,
74 },
75 Register {
76 register: u16,
77 },
78 AtCfaOffset {
79 offset: i64,
80 },
81 ValCfaOffset {
82 offset: i64,
83 },
84 Constant {
85 value: u64,
86 },
87 Expression {
88 steps: Vec<PlanExprOp>,
89 dereference: bool,
90 },
91 Unsupported {
92 reason: String,
93 },
94}
95
96impl RegisterRecoveryPlan {
97 pub fn is_bpf_fast_path_supported(&self) -> bool {
98 matches!(
99 self,
100 Self::SameValue { .. }
101 | Self::Register { .. }
102 | Self::AtCfaOffset { .. }
103 | Self::ValCfaOffset { .. }
104 )
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct UnwindDiagnostic {
110 pub pc_start: u64,
111 pub pc_end: u64,
112 pub kind: UnwindDiagnosticKind,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub enum UnwindDiagnosticKind {
117 UnsupportedCfaRule { reason: String },
118 UnsupportedRegisterRule { register: u16, reason: String },
119 MissingReturnAddressRule { register: u16 },
120}