• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

qmonnet / rbpf / 14311537349

07 Apr 2025 02:14PM UTC coverage: 94.952% (-0.3%) from 95.255%
14311537349

Pull #122

github

web-flow
Merge e5911d21f into 9642917c9
Pull Request #122: feat: Add bpf to bpf call support

145 of 170 new or added lines in 5 files covered. (85.29%)

2 existing lines in 2 files now uncovered.

4270 of 4497 relevant lines covered (94.95%)

257.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/stack.rs
1
use core::any::Any;
2

3
use crate::{
4
    ebpf::{self, RBPF_EBPF_LOCAL_FUNCTION_STACK_SIZE},
5
    lib::*,
6
    StackUsageCalculator,
7
};
8

9
#[derive(Debug, Copy, Clone)]
10
pub struct StackFrame {
11
    return_address: usize,
12
    saved_registers: [u64; 4],
13
    stack_usage: StackUsageType,
14
}
15

16
impl StackFrame {
17
    /// Create a new stack frame
18
    pub const fn new() -> Self {
162✔
19
        Self {
162✔
20
            return_address: 0,
162✔
21
            saved_registers: [0; 4],
162✔
22
            stack_usage: StackUsageType::Default,
162✔
23
        }
162✔
24
    }
162✔
25
    /// Save the callee-saved registers
26
    pub fn save_registers(&mut self, regs: &[u64]) {
2✔
27
        self.saved_registers.copy_from_slice(regs);
2✔
28
    }
2✔
29

30
    /// Get the callee-saved registers
31
    pub fn get_registers(&self) -> [u64; 4] {
2✔
32
        self.saved_registers
2✔
33
    }
2✔
34

35
    /// Save the return address
36
    pub fn save_return_address(&mut self, address: usize) {
2✔
37
        self.return_address = address;
2✔
38
    }
2✔
39

40
    /// Get the return address
41
    pub fn get_return_address(&self) -> usize {
2✔
42
        self.return_address
2✔
43
    }
2✔
44

45
    /// Set the stack usage
46
    pub fn set_stack_usage(&mut self, usage: StackUsageType) {
170✔
47
        self.stack_usage = usage;
170✔
48
    }
170✔
49
    /// Get the stack usage
50
    pub fn get_stack_usage(&self) -> StackUsageType {
4✔
51
        self.stack_usage
4✔
52
    }
4✔
53
}
54

55
#[derive(Debug, Copy, Clone)]
56
pub enum StackUsageType {
57
    Default,
58
    Custom(u16),
59
}
60

61
impl StackUsageType {
62
    pub fn stack_usage(&self) -> u16 {
458✔
63
        match self {
458✔
64
            StackUsageType::Default => RBPF_EBPF_LOCAL_FUNCTION_STACK_SIZE,
458✔
NEW
65
            StackUsageType::Custom(size) => *size,
×
66
        }
67
    }
458✔
68
}
69

70
pub struct StackVerifier {
71
    calculator: Option<StackUsageCalculator>,
72
    data: Option<Box<dyn Any>>,
73
}
74

75
impl StackVerifier {
76
    pub fn new(
444✔
77
        stack_usage_calculator: Option<StackUsageCalculator>,
444✔
78
        data: Option<Box<dyn Any>>,
444✔
79
    ) -> Self {
444✔
80
        Self {
444✔
81
            calculator: stack_usage_calculator,
444✔
82
            data,
444✔
83
        }
444✔
84
    }
444✔
85
    /// Validate the stack usage of a program
86
    ///
87
    /// This function checks the stack usage of a program and returns a `StackUsage` object
88
    /// containing the stack usage for each local function in the program.
89
    ///
90
    /// # Returns
91
    /// - `Ok(StackUsage)` if the stack usage is valid
92
    /// - `Err(Error)` if the stack usage is invalid
93
    pub fn stack_validate(&mut self, prog: &[u8]) -> Result<StackUsage, Error> {
429✔
94
        let mut stack_usage = HashMap::new();
429✔
95
        let ty = self.calculate_stack_usage_for_local_func(prog, 0)?;
429✔
96
        stack_usage.insert(0, ty);
429✔
97
        for idx in 0..prog.len() / ebpf::INSN_SIZE {
3,834✔
98
            let insn = ebpf::get_insn(prog, idx);
3,834✔
99
            if insn.opc == ebpf::CALL {
3,834✔
100
                let dst_insn_ptr = idx as isize + 1 + insn.imm as isize;
25✔
101
                let ty = self.calculate_stack_usage_for_local_func(prog, dst_insn_ptr as usize)?;
25✔
102
                stack_usage.insert(dst_insn_ptr as usize, ty);
25✔
103
            }
3,809✔
104
        }
105
        Ok(StackUsage(stack_usage))
429✔
106
    }
429✔
107

108
    /// Calculate the stack usage for a local function
109
    fn calculate_stack_usage_for_local_func(
454✔
110
        &mut self,
454✔
111
        prog: &[u8],
454✔
112
        pc: usize,
454✔
113
    ) -> Result<StackUsageType, Error> {
454✔
114
        let mut ty = StackUsageType::Default;
454✔
115
        if let Some(calculator) = self.calculator {
454✔
NEW
116
            let size = calculator(prog, pc, self.data.as_mut().unwrap());
×
NEW
117
            ty = StackUsageType::Custom(size);
×
118
        }
454✔
119
        if ty.stack_usage() % 16 > 0 {
454✔
NEW
120
            Err(Error::new(
×
NEW
121
                ErrorKind::Other,
×
NEW
122
                format!(
×
NEW
123
                    "local function (at PC {}) has improperly sized stack use ({})",
×
NEW
124
                    pc,
×
NEW
125
                    ty.stack_usage()
×
NEW
126
                ),
×
NEW
127
            ))?;
×
128
        }
454✔
129
        Ok(ty)
454✔
130
    }
454✔
131
}
132

133
pub struct StackUsage(HashMap<usize, StackUsageType>);
134

135
impl StackUsage {
136
    /// Get the stack usage for a local function
137
    pub fn stack_usage_for_local_func(&self, pc: usize) -> Option<StackUsageType> {
1,961✔
138
        self.0.get(&pc).cloned()
1,961✔
139
    }
1,961✔
140
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc