浏览代码

bpf: add explicit BTF argument to the load API

Add a `target_btf: Option<Btf>` argument to Bpf::load. None can be
passed to indicate to skip BTF relocation, for example for kernels that
don't support it. Some(btf) can be used to pass BTF parsed with
Btf::from_sys_fs() or Btf::parse/parse_file.

Finally, add a simpler Bpf::load_file(path) that uses from_sys_fs()
internally to simplify the common case.
Alessandro Decina 4 年之前
父节点
当前提交
2cec04c578
共有 4 个文件被更改,包括 63 次插入22 次删除
  1. 33 7
      aya/src/bpf.rs
  2. 2 0
      aya/src/lib.rs
  3. 26 2
      aya/src/obj/btf/btf.rs
  4. 2 13
      aya/src/obj/btf/relocation.rs

+ 33 - 7
aya/src/bpf.rs

@@ -1,10 +1,19 @@
-use std::{collections::HashMap, convert::TryFrom, error::Error, io};
+use std::{
+    collections::HashMap,
+    convert::TryFrom,
+    error::Error,
+    fs, io,
+    path::{Path, PathBuf},
+};
 
 use thiserror::Error;
 
 use crate::{
     maps::{Map, MapError, MapLock, MapRef, MapRefMut},
-    obj::{btf::BtfError, Object, ParseError},
+    obj::{
+        btf::{Btf, BtfError},
+        Object, ParseError,
+    },
     programs::{KProbe, Program, ProgramData, ProgramError, SocketFilter, TracePoint, UProbe, Xdp},
     sys::bpf_map_update_elem_ptr,
 };
@@ -46,10 +55,23 @@ pub struct Bpf {
 }
 
 impl Bpf {
-    pub fn load(data: &[u8]) -> Result<Bpf, BpfError> {
+    pub fn load_file<P: AsRef<Path>>(path: P) -> Result<Bpf, BpfError> {
+        let path = path.as_ref();
+        Bpf::load(
+            &fs::read(path).map_err(|error| BpfError::FileError {
+                path: path.to_owned(),
+                error,
+            })?,
+            Some(Btf::from_sys_fs()?),
+        )
+    }
+
+    pub fn load(data: &[u8], target_btf: Option<Btf>) -> Result<Bpf, BpfError> {
         let mut obj = Object::parse(data)?;
 
-        obj.relocate_btf()?;
+        if let Some(btf) = target_btf {
+            obj.relocate_btf(btf)?;
+        }
 
         let mut maps = Vec::new();
         for (_, obj) in obj.maps.drain() {
@@ -152,13 +174,17 @@ impl Bpf {
 
 #[derive(Debug, Error)]
 pub enum BpfError {
-    #[error("IO error: {0}")]
-    IO(#[from] io::Error),
+    #[error("error loading {path}")]
+    FileError {
+        path: PathBuf,
+        #[source]
+        error: io::Error,
+    },
 
     #[error("error parsing BPF object: {0}")]
     ParseError(#[from] ParseError),
 
-    #[error("BTF error: {0}")]
+    #[error("BTF error")]
     BtfError(#[from] BtfError),
 
     #[error("error relocating BPF program `{program_name}`: {error}")]

+ 2 - 0
aya/src/lib.rs

@@ -14,3 +14,5 @@ mod sys;
 pub mod util;
 
 pub use bpf::*;
+pub use obj::btf::{Btf, BtfError};
+pub use object::Endianness;

+ 26 - 2
aya/src/obj/btf/btf.rs

@@ -2,7 +2,9 @@ use std::{
     borrow::Cow,
     convert::TryInto,
     ffi::{c_void, CStr},
-    mem, ptr,
+    fs, io, mem,
+    path::{Path, PathBuf},
+    ptr,
 };
 
 use object::Endianness;
@@ -17,8 +19,15 @@ use crate::{
 pub(crate) const MAX_RESOLVE_DEPTH: u8 = 32;
 pub(crate) const MAX_SPEC_LEN: usize = 64;
 
-#[derive(Error, Debug, Clone, Eq, PartialEq)]
+#[derive(Error, Debug)]
 pub enum BtfError {
+    #[error("error parsing {path}")]
+    FileError {
+        path: PathBuf,
+        #[source]
+        error: io::Error,
+    },
+
     #[error("error parsing BTF header")]
     InvalidHeader,
 
@@ -70,6 +79,21 @@ pub struct Btf {
 }
 
 impl Btf {
+    pub fn from_sys_fs() -> Result<Btf, BtfError> {
+        Btf::parse_file("/sys/kernel/btf/vmlinux", Endianness::default())
+    }
+
+    pub fn parse_file<P: AsRef<Path>>(path: P, endianness: Endianness) -> Result<Btf, BtfError> {
+        let path = path.as_ref();
+        Btf::parse(
+            &fs::read(path).map_err(|error| BtfError::FileError {
+                path: path.to_owned(),
+                error,
+            })?,
+            endianness,
+        )
+    }
+
     pub(crate) fn parse(data: &[u8], endianness: Endianness) -> Result<Btf, BtfError> {
         if data.len() < mem::size_of::<btf_header>() {
             return Err(BtfError::InvalidHeader);

+ 2 - 13
aya/src/obj/btf/relocation.rs

@@ -1,10 +1,9 @@
 use std::{
     collections::HashMap,
     convert::{TryFrom, TryInto},
-    fs, io, mem, ptr,
+    io, mem, ptr,
 };
 
-use object::{Endian, Endianness, NativeEndian};
 use thiserror::Error;
 
 use crate::{
@@ -152,22 +151,12 @@ impl Relocation {
 }
 
 impl Object {
-    pub fn relocate_btf(&mut self) -> Result<(), BpfError> {
+    pub fn relocate_btf(&mut self, target_btf: Btf) -> Result<(), BpfError> {
         let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) {
             (Some(btf), Some(btf_ext)) => (btf, btf_ext),
             _ => return Ok(()),
         };
 
-        let target_btf = fs::read("/sys/kernel/btf/vmlinux")?;
-        let target_btf = Btf::parse(&target_btf, {
-            let e = NativeEndian;
-            if e.is_little_endian() {
-                Endianness::Little
-            } else {
-                Endianness::Big
-            }
-        })?;
-
         let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new();
         for (sec_name_off, relos) in btf_ext.relocations() {
             let section_name = local_btf.string_at(*sec_name_off)?;