1use std::error;
4use std::ffi::CString;
5use std::rc::Rc;
6use std::fmt;
7use std::mem;
8use byteorder::{ByteOrder, LE};
9use errno::Errno;
10use xmas_elf::ElfFile;
11use xmas_elf::sections::SectionHeader;
12use xmas_elf::sections::SectionData::*;
13use xmas_elf::sections::ShType::*;
14use xmas_elf::symbol_table::Entry;
15use xmas_elf::symbol_table::Binding::*;
16use zero::read_array;
17use bpf::{self, Kind, Program};
18use ffi::*;
19use sys;
20use self::Error::*;
21use self::Item::*;
22use self::Kind::*;
23
24#[derive(Debug)]
25pub struct Loader {
26 pub code: Vec<Code>,
27 pub maps: Vec<Map>,
28 pub rels: Vec<Relocation>,
29 pub symbols: Vec<Symbol>,
30 pub license: CString,
31 pub version: u32,
32}
33
34pub struct Code {
35 pub symbol: Symbol,
36 pub kind: Kind,
37 pub code: Vec<bpf_insn>,
38}
39
40#[derive(Debug)]
41pub struct Map {
42 pub symbol: Symbol,
43 pub create: bpf_map_create_arg,
44}
45
46#[derive(Debug)]
47pub struct Relocation {
48 pub section: u16,
49 pub offset: usize,
50 pub symbol: Symbol,
51}
52
53#[derive(Debug, Clone, Eq, PartialEq)]
54pub struct Symbol {
55 pub section: u16,
56 pub name: String,
57 pub value: u64,
58}
59
60#[derive(Debug)]
61pub enum Error {
62 ELF(&'static str),
63 Invalid(Item),
64 Missing(Item),
65 Syscall(Errno),
66 Program(sys::Error),
67}
68
69#[derive(Debug)]
70pub enum Item {
71 License,
72 Map,
73 Version,
74 Symbol,
75}
76
77impl Loader {
78 pub fn new(bytes: &[u8]) -> Result<Self, Error> {
79 let elf = ElfFile::new(bytes)?;
80
81 let mut loader = Loader {
82 code: Vec::new(),
83 maps: Vec::new(),
84 rels: Vec::new(),
85 symbols: Vec::new(),
86 license: CString::default(),
87 version: 0,
88 };
89
90 for (index, sec) in elf.section_iter().enumerate() {
91 let kind = sec.get_type()?;
92 let name = sec.get_name(&elf);
93 let data = match sec.size() {
94 n if n > 0 => sec.raw_data(&elf),
95 _ => &[],
96 };
97
98 match (kind, name) {
99 (ProgBits, Ok("maps"), ) => loader.maps.extend(maps(data, &elf, index)?),
100 (ProgBits, Ok("license")) => loader.license = license(data)?,
101 (ProgBits, Ok("version")) => loader.version = version(data)?,
102 (ProgBits, Ok(name), ) => loader.code.extend(code(name, &elf, index)?),
103 (Rel, _, ) => loader.rels.extend(relocations(sec, &elf)?),
104 _ => (),
105 };
106
107 loader.symbols.extend(symbols(&elf, index as u16)?);
108 }
109
110 Ok(loader)
111 }
112
113 pub fn load(&mut self) -> Result<Vec<Program>, Error> {
114 let rels = &self.rels;
115 let maps = self.maps.iter().flat_map(|map| {
116 let rels: Vec<_> = rels.iter().filter(|r| r.symbol == map.symbol).collect();
117
118 let arg = bpf_map_create_arg {
119 map_name: sys::name(&map.symbol.name),
120 map_type: map.create.map_type,
121 key_size: map.create.key_size,
122 val_size: map.create.val_size,
123 max_entries: map.create.max_entries,
124 map_flags: 0,
125 .. Default::default()
126 };
127
128 rels.first().cloned().map(|_| {
129 let fd = sys::bpf_create_map(&arg)?;
130 Ok((Rc::new(bpf::Map {
131 name: map.symbol.name.to_owned(),
132 fd: fd,
133 ksize: arg.key_size as usize,
134 vsize: arg.val_size as usize,
135 limit: arg.max_entries as usize,
136 }), rels))
137 })
138 }).collect::<Result<Vec<_>, Error>>()?;
139
140 let license = &self.license;
141 let version = self.version;
142 let mut log = [0u8; 65535];
143
144 self.code.iter_mut().map(|ref mut code| {
145 let section = code.symbol.section;
146 let name = code.symbol.name.clone();
147 let kind = code.kind.clone();
148 let code = &mut code.code;
149
150 let maps = maps.iter().flat_map(|&(ref map, ref rels)| {
151 let mut maps = rels.iter().filter(|r| r.section == section).map(|rel| {
152 let offset = rel.offset / mem::size_of::<bpf_insn>();
153 let insn = &mut code[offset as usize];
154
155 insn.regs |= BPF_PSEUDO_MAP_FD << 4;
156 insn.imm = map.fd;
157
158 Rc::clone(map)
159 }).collect::<Vec<_>>();
160
161 maps.dedup_by_key(|map| map.fd);
162
163 maps
164 }).collect::<Vec<_>>();
165
166 let arg = bpf_prog_load_arg {
167 prog_name: sys::name(&name),
168 prog_type: prog_type(&kind) as u32,
169 insns: code.as_ptr() as u64,
170 insn_cnt: code.len() as u32,
171 license: license.as_ptr() as u64,
172 kern_version: version as u32,
173 .. Default::default()
174 };
175
176 let fd = sys::bpf_prog_load(&arg, &mut log)?;
177
178 Ok(Program{ name, kind, fd, maps })
179 }).collect()
180 }
181}
182
183fn relocations(sec: SectionHeader, elf: &ElfFile) -> Result<Vec<Relocation>, Error> {
184 let symtab = sec.link() as u16;
185 let section = sec.info() as u16;
186
187 let rel = |offset: usize, symbol: u32| {
188 Ok(Relocation {
189 section: section,
190 offset: offset,
191 symbol: resolve(elf, symtab, symbol as usize)?,
192 })
193 };
194
195 match sec.get_data(elf)? {
196 Rel32(rs) => rs.iter().map(|r| rel(r.get_offset() as usize, r.get_symbol_table_index())).collect(),
197 Rel64(rs) => rs.iter().map(|r| rel(r.get_offset() as usize, r.get_symbol_table_index())).collect(),
198 _ => unreachable!(),
199 }
200}
201
202fn code(name: &str, elf: &ElfFile, index: usize) -> Result<Option<Code>, Error> {
203 let index = index as u16;
204 let sec = elf.section_header(index)?;
205 let syms = symbols(elf, index)?;
206 let data = sec.raw_data(&elf);
207
208 let code = |kind| {
209 syms.first().map(|sym| {
210 Code {
211 symbol: sym.clone(),
212 kind: kind,
213 code: read_array(data).to_vec(),
214 }
215 })
216 };
217
218 let mut split = name.splitn(2, '/');
219 let code = match (split.next(), split.next()) {
220 (Some("kprobe"), Some(event)) => code(Kprobe(event.into())),
221 (Some("kretprobe"), Some(event)) => code(Kretprobe(event.into())),
222 (Some("tracepoint"), Some(event)) => code(Tracepoint(event.into())),
223 (Some("xdp"), Some(name)) => code(XDP(name.into())),
224 _ => None,
225 };
226
227 Ok(code)
228}
229
230fn maps(data: &[u8], elf: &ElfFile, index: usize) -> Result<Vec<Map>, Error> {
231 let args = read_array(data);
232 symbols(elf, index as u16)?.iter().map(|sym| {
233 let size = mem::size_of::<bpf_map_create_arg>();
234 let offset = sym.value as usize / size;
235 let create = *args.get(offset).ok_or(Missing(Map))?;
236 let symbol = sym.clone();
237 Ok(Map { create, symbol })
238 }).collect()
239}
240
241fn license(data: &[u8]) -> Result<CString, Error> {
242 let n = data.len() - 1;
243 let data = data[..n].to_vec();
244 CString::new(data).map_err(|_| Invalid(License))
245}
246
247fn version(data: &[u8]) -> Result<u32, Error> {
248 match data.len() {
249 4 => Ok(LE::read_u32(data)),
250 _ => Err(Invalid(Version)),
251 }
252}
253
254fn resolve(elf: &ElfFile, section: u16, index: usize) -> Result<Symbol, Error> {
255 let symtab = match elf.header.pt2.sh_count() {
256 n if n > section => elf.section_header(section)?,
257 _ => return Err(Missing(Symbol)),
258 };
259
260 match symtab.get_data(elf)? {
261 SymbolTable32(entries) => entries.get(index).map(|e| sym(e, elf)),
262 SymbolTable64(entries) => entries.get(index).map(|e| sym(e, elf)),
263 _ => None,
264 }.unwrap_or(Err(Missing(Symbol)))
265}
266
267fn symbols(elf: &ElfFile, section: u16) -> Result<Vec<Symbol>, Error> {
268 let filter = |e: &Entry| {
269 match (e.get_binding(), e.shndx() == section) {
270 (Ok(Global), true) => Some(sym(e, elf)),
271 _ => None,
272 }
273 };
274
275 let mut syms = Vec::new();
276 for sec in elf.section_iter().filter(|s| s.get_type() == Ok(SymTab)) {
277 match sec.get_data(elf)? {
278 SymbolTable32(entries) => syms.extend(entries.iter().flat_map(|e| filter(e))),
279 SymbolTable64(entries) => syms.extend(entries.iter().flat_map(|e| filter(e))),
280 _ => (),
281 }
282 }
283
284 syms.into_iter().collect()
285}
286
287fn sym(e: &Entry, elf: &ElfFile) -> Result<Symbol, Error> {
288 Ok(Symbol {
289 section: e.shndx(),
290 name: e.get_name(elf)?.into(),
291 value: e.value(),
292 })
293}
294
295fn prog_type(kind: &Kind) -> bpf_prog_type {
296 use ffi::bpf_prog_type::*;
297 match *kind {
298 Kprobe(..) => BPF_PROG_TYPE_KPROBE,
299 Kretprobe(..) => BPF_PROG_TYPE_KPROBE,
300 Socket => BPF_PROG_TYPE_SOCKET_FILTER,
301 Tracepoint(..) => BPF_PROG_TYPE_TRACEPOINT,
302 XDP(..) => BPF_PROG_TYPE_XDP,
303 }
304}
305
306impl From<&'static str> for Error {
307 fn from(err: &'static str) -> Self {
308 ELF(err)
309 }
310}
311
312impl From<Errno> for Error {
313 fn from(err: Errno) -> Self {
314 Syscall(err)
315 }
316}
317
318impl From<sys::Error> for Error {
319 fn from(err: sys::Error) -> Self {
320 Program(err)
321 }
322}
323
324impl error::Error for Error {
325 fn description(&self) -> &str {
326 match self {
327 ELF(..) => "ELF loader error",
328 Invalid(..) => "invalid item",
329 Missing(..) => "missing item",
330 Syscall(..) => "syscall error",
331 Program(..) => "program error",
332 }
333 }
334
335 fn cause(&self) -> Option<&error::Error> {
336 match self {
337 ELF(..) => None,
338 Invalid(..) => None,
339 Missing(..) => None,
340 Syscall(..) => None,
341 Program(e) => Some(e),
342 }
343 }
344}
345
346impl fmt::Display for Error {
347 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
348 write!(f, "{:?}", self)
349 }
350}
351
352impl fmt::Debug for Code {
353 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
354 let count = format!("[{} instructions]", self.code.len());
355 f.debug_struct("Code")
356 .field("kind", &self.kind)
357 .field("code", &count)
358 .finish()
359
360 }
361}