1#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum Availability {
6 Available,
7 PartiallyAvailable,
8 OptimizedOut,
9 NotInScope,
10 Unsupported(UnsupportedReason),
11 Requires(RuntimeRequirement),
12 Ambiguous(AmbiguityReason),
13}
14
15impl Availability {
16 pub fn is_available(&self) -> bool {
17 matches!(self, Self::Available | Self::PartiallyAvailable)
18 }
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum UnsupportedReason {
24 DwarfOp { op: String },
25 ExpressionShape { detail: String },
26 TypeLayout { detail: String },
27 AddressClass { detail: String },
28 RegisterMapping { dwarf_reg: u16 },
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
33pub enum RuntimeRequirement {
34 CallerFrame,
35 SleepableUprobe,
36 UserMemoryRead,
37 DwarfCfiRecovery,
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
42pub enum AmbiguityReason {
43 InlineContext { detail: String },
44 VariableDeclaration { detail: String },
45 TypeResolution { detail: String },
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum Provenance {
51 DirectDie,
52 AbstractOrigin,
53 Specification,
54 LocationList,
55 CallSite,
56 Cfi,
57 Synthesized { detail: String },
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
62pub enum DebugInfoSource {
63 Embedded { path: String },
64 Explicit { path: String },
65 Debuglink { path: String },
66 Debuginfod { path: String },
67 Missing,
68}
69
70impl DebugInfoSource {
71 pub fn kind_label(&self) -> &'static str {
72 match self {
73 Self::Embedded { .. } => "embedded",
74 Self::Explicit { .. } => "explicit",
75 Self::Debuglink { .. } => "debuglink",
76 Self::Debuginfod { .. } => "debuginfod",
77 Self::Missing => "missing",
78 }
79 }
80
81 pub fn display_path(&self) -> Option<&str> {
82 match self {
83 Self::Embedded { path }
84 | Self::Explicit { path }
85 | Self::Debuglink { path }
86 | Self::Debuginfod { path } => Some(path),
87 Self::Missing => None,
88 }
89 }
90
91 pub fn summary(&self) -> String {
92 match self.display_path() {
93 Some(path) => format!("{} ({path})", self.kind_label()),
94 None => self.kind_label().to_string(),
95 }
96 }
97}
98
99#[derive(Debug, Clone, PartialEq, Eq)]
101pub struct RuntimeCapabilities {
102 pub regular_uprobe: bool,
103 pub sleepable_uprobe: bool,
104 pub uprobe_multi: bool,
105 pub copy_from_user_task: bool,
106 pub max_bpf_stack_bytes: usize,
107 pub bounded_loops: bool,
108 pub arch: TargetArch,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub enum TargetArch {
113 X86_64,
114 Aarch64,
115 Unknown,
116}
117
118impl TargetArch {
119 pub fn current() -> Self {
120 if cfg!(target_arch = "x86_64") {
121 Self::X86_64
122 } else if cfg!(target_arch = "aarch64") {
123 Self::Aarch64
124 } else {
125 Self::Unknown
126 }
127 }
128}
129
130impl Default for RuntimeCapabilities {
131 fn default() -> Self {
132 Self {
133 regular_uprobe: true,
134 sleepable_uprobe: false,
135 uprobe_multi: false,
136 copy_from_user_task: false,
137 max_bpf_stack_bytes: 512,
138 bounded_loops: true,
139 arch: TargetArch::current(),
140 }
141 }
142}
143
144#[derive(Debug, Clone, PartialEq, Eq)]
146pub enum HelperMode {
147 NoUserMemoryRead,
148 ProbeReadUser,
149 CopyFromUserTask,
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
154pub enum VerifierRisk {
155 Low,
156 RequiresBoundedLoops,
157 StackBudgetExceeded { estimated: usize, max: usize },
158 Unsupported { reason: String },
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164 use crate::core::{PieceLocation, VariableLocation};
165
166 #[test]
167 fn optimized_location_is_unavailable() {
168 assert_eq!(
169 Availability::from_variable_location(&VariableLocation::OptimizedOut),
170 Availability::OptimizedOut
171 );
172 }
173
174 #[test]
175 fn mixed_composite_location_is_partially_available() {
176 let location = VariableLocation::Pieces(vec![
177 PieceLocation {
178 location: Box::new(VariableLocation::RegisterValue { dwarf_reg: 0 }),
179 bit_size: 32,
180 bit_offset: 0,
181 },
182 PieceLocation {
183 location: Box::new(VariableLocation::OptimizedOut),
184 bit_size: 32,
185 bit_offset: 32,
186 },
187 ]);
188
189 assert_eq!(
190 Availability::from_variable_location(&location),
191 Availability::PartiallyAvailable
192 );
193 }
194}