-
Notifications
You must be signed in to change notification settings - Fork 135
Expand file tree
/
Copy pathkallsyms.rs
More file actions
133 lines (115 loc) · 4.13 KB
/
Copy pathkallsyms.rs
File metadata and controls
133 lines (115 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::io::BufRead;
use std::str::FromStr;
use crate::{FromBufRead, ProcError, ProcResult};
#[cfg(feature = "serde1")]
use serde::{Deserialize, Serialize};
/// KAllSyms entries under `/proc/kallsyms`
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct KAllSyms {
/// Kernel symbols
pub symbols: Vec<KAllSymsEntry>,
}
/// A kernel symbol entry under `/proc/kallsyms`
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct KAllSymsEntry {
/// Address of the symbol
pub address: u64,
/// Symbol type
pub symbol_type: char,
/// Symbol name
pub name: String,
/// Optional module name
pub module_name: Option<String>,
}
impl FromBufRead for KAllSyms {
fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
let mut symbols = Vec::new();
for line in r.lines() {
let line = line?;
let entry = KAllSymsEntry::from_str(&line)?;
symbols.push(entry);
}
Ok(KAllSyms { symbols })
}
}
impl std::str::FromStr for KAllSymsEntry {
type Err = ProcError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut it = s.splitn(3, ' ');
let address = from_str!(u64, expect!(it.next()), 16);
let symbol_type = expect!(it.next());
let symbol_type = {
if symbol_type.len() != 1 {
return Err(ProcError::Other(format!(
"Invalid symbol type: {}, expected a single character",
symbol_type
)));
}
symbol_type.chars().next().unwrap()
};
let mut it = expect!(it.next()).splitn(2, '\t');
let name = expect!(it.next()).to_string();
let module_name = if let Some(module_name) = it.next() {
// Check [ and ] around module name
if module_name.starts_with('[') && module_name.ends_with(']') {
Some(module_name[1..module_name.len() - 1].to_string())
} else {
return Err(ProcError::Other(format!(
"Invalid module name format: {}, expected [module_name]",
module_name
)));
}
} else {
None
};
Ok(KAllSymsEntry {
address,
symbol_type,
name,
module_name,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_kallsymsentry() {
let s = "c000000000000000 T _text";
let entry = KAllSymsEntry::from_str(s).unwrap();
assert_eq!(entry.address, 0xc000000000000000);
assert_eq!(entry.symbol_type, 'T');
assert_eq!(entry.name, "_text");
assert!(entry.module_name.is_none());
let s = "c000000000000000 T _text\t[module_name]";
let entry = KAllSymsEntry::from_str(s).unwrap();
assert_eq!(entry.address, 0xc000000000000000);
assert_eq!(entry.symbol_type, 'T');
assert_eq!(entry.name, "_text");
assert_eq!(entry.module_name.unwrap(), "module_name");
}
#[test]
fn test_kallsyms() {
let data = "cb00000000000000 T _text
c000000000000000 T _start
c000000000000100 t bpf_text\t[bpf]
";
let mut reader = std::io::Cursor::new(data);
let kallsyms = KAllSyms::from_buf_read(&mut reader).unwrap();
assert_eq!(kallsyms.symbols.len(), 3);
assert_eq!(kallsyms.symbols[0].address, 0xcb00000000000000);
assert_eq!(kallsyms.symbols[0].symbol_type, 'T');
assert_eq!(kallsyms.symbols[0].name, "_text");
assert!(kallsyms.symbols[0].module_name.is_none());
assert_eq!(kallsyms.symbols[1].address, 0xc000000000000000);
assert_eq!(kallsyms.symbols[1].symbol_type, 'T');
assert_eq!(kallsyms.symbols[1].name, "_start");
assert!(kallsyms.symbols[1].module_name.is_none());
assert_eq!(kallsyms.symbols[2].address, 0xc000000000000100);
assert_eq!(kallsyms.symbols[2].symbol_type, 't');
assert_eq!(kallsyms.symbols[2].name, "bpf_text");
assert_eq!(kallsyms.symbols[2].module_name.as_ref().unwrap(), "bpf");
}
}