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

qmonnet / rbpf / 14187764789

01 Apr 2025 05:14AM UTC coverage: 94.767% (-0.5%) from 95.255%
14187764789

Pull #122

github

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

110 of 138 new or added lines in 4 files covered. (79.71%)

2 existing lines in 2 files now uncovered.

4274 of 4510 relevant lines covered (94.77%)

255.15 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 {
161✔
19
        Self {
161✔
20
            return_address: 0,
161✔
21
            saved_registers: [0; 4],
161✔
22
            stack_usage: StackUsageType::Default,
161✔
23
        }
161✔
24
    }
161✔
25
    /// Save the callee-saved registers
26
    pub fn save_registers(&mut self, regs: &[u64]) {
1✔
27
        self.saved_registers.copy_from_slice(regs);
1✔
28
    }
1✔
29

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

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

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

45
    /// Set the stack usage
46
    pub fn set_stack_usage(&mut self, usage: StackUsageType) {
169✔
47
        self.stack_usage = usage;
169✔
48
    }
169✔
49
    /// Get the stack usage
50
    pub fn get_stack_usage(&self) -> StackUsageType {
2✔
51
        self.stack_usage
2✔
52
    }
2✔
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 {
448✔
63
        match self {
448✔
64
            StackUsageType::Default => RBPF_EBPF_LOCAL_FUNCTION_STACK_SIZE,
448✔
NEW
65
            StackUsageType::Custom(size) => *size,
×
66
        }
67
    }
448✔
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(
439✔
77
        stack_usage_calculator: Option<StackUsageCalculator>,
439✔
78
        data: Option<Box<dyn Any>>,
439✔
79
    ) -> Self {
439✔
80
        Self {
439✔
81
            calculator: stack_usage_calculator,
439✔
82
            data,
439✔
83
        }
439✔
84
    }
439✔
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> {
426✔
94
        let mut stack_usage = HashMap::new();
426✔
95
        let ty = self.calculate_stack_usage_for_local_func(prog, 0)?;
426✔
96
        stack_usage.insert(0, ty);
426✔
97
        for idx in 0..prog.len() / ebpf::INSN_SIZE {
3,809✔
98
            let insn = ebpf::get_insn(prog, idx);
3,809✔
99
            if insn.opc == ebpf::CALL {
3,809✔
100
                let dst_insn_ptr = idx as isize + 1 + insn.imm as isize;
20✔
101
                let ty = self.calculate_stack_usage_for_local_func(prog, dst_insn_ptr as usize)?;
20✔
102
                stack_usage.insert(dst_insn_ptr as usize, ty);
20✔
103
            }
3,789✔
104
        }
105
        Ok(StackUsage(stack_usage))
426✔
106
    }
426✔
107

108
    /// Calculate the stack usage for a local function
109
    fn calculate_stack_usage_for_local_func(
446✔
110
        &mut self,
446✔
111
        prog: &[u8],
446✔
112
        pc: usize,
446✔
113
    ) -> Result<StackUsageType, Error> {
446✔
114
        let mut ty = StackUsageType::Default;
446✔
115
        if let Some(calculator) = self.calculator {
446✔
NEW
116
            let size = calculator(prog, pc, self.data.as_mut().unwrap());
×
NEW
117
            ty = StackUsageType::Custom(size);
×
118
        }
446✔
119
        if ty.stack_usage() % 16 > 0 {
446✔
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
        }
446✔
129
        Ok(ty)
446✔
130
    }
446✔
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,954✔
138
        self.0.get(&pc).cloned()
1,954✔
139
    }
1,954✔
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