|  | @@ -1,74 +1,124 @@
 | 
											
												
													
														|  | -use std::{collections::HashMap, io, mem, ptr, str::FromStr};
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -use thiserror::Error;
 |  | 
 | 
											
												
													
														|  | 
 |  | +use core::{mem, ptr, str::FromStr};
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +use alloc::{
 | 
											
												
													
														|  | 
 |  | +    borrow::ToOwned,
 | 
											
												
													
														|  | 
 |  | +    format,
 | 
											
												
													
														|  | 
 |  | +    string::{String, ToString},
 | 
											
												
													
														|  | 
 |  | +    vec,
 | 
											
												
													
														|  | 
 |  | +    vec::Vec,
 | 
											
												
													
														|  | 
 |  | +};
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  use crate::{
 |  |  use crate::{
 | 
											
												
													
														|  | 
 |  | +    btf::{
 | 
											
												
													
														|  | 
 |  | +        fields_are_compatible, types_are_compatible, Array, Btf, BtfError, BtfMember, BtfType,
 | 
											
												
													
														|  | 
 |  | +        IntEncoding, Struct, Union, MAX_SPEC_LEN,
 | 
											
												
													
														|  | 
 |  | +    },
 | 
											
												
													
														|  |      generated::{
 |  |      generated::{
 | 
											
												
													
														|  |          bpf_core_relo, bpf_core_relo_kind::*, bpf_insn, BPF_ALU, BPF_ALU64, BPF_B, BPF_DW, BPF_H,
 |  |          bpf_core_relo, bpf_core_relo_kind::*, bpf_insn, BPF_ALU, BPF_ALU64, BPF_B, BPF_DW, BPF_H,
 | 
											
												
													
														|  |          BPF_K, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, BPF_W, BTF_INT_SIGNED,
 |  |          BPF_K, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, BPF_W, BTF_INT_SIGNED,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  | -    obj::{
 |  | 
 | 
											
												
													
														|  | -        btf::{
 |  | 
 | 
											
												
													
														|  | -            fields_are_compatible, types_are_compatible, Array, BtfMember, BtfType, IntEncoding,
 |  | 
 | 
											
												
													
														|  | -            Struct, Union, MAX_SPEC_LEN,
 |  | 
 | 
											
												
													
														|  | -        },
 |  | 
 | 
											
												
													
														|  | -        Btf, BtfError, Object, Program, ProgramSection,
 |  | 
 | 
											
												
													
														|  | -    },
 |  | 
 | 
											
												
													
														|  | -    BpfError,
 |  | 
 | 
											
												
													
														|  | 
 |  | +    thiserror::{self, Error},
 | 
											
												
													
														|  | 
 |  | +    util::HashMap,
 | 
											
												
													
														|  | 
 |  | +    Object, Program, ProgramSection,
 | 
											
												
													
														|  |  };
 |  |  };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +/// The error type returned by [`Object::relocate_btf`].
 | 
											
												
													
														|  | 
 |  | +#[derive(Error, Debug)]
 | 
											
												
													
														|  | 
 |  | +#[error("error relocating `{section}`")]
 | 
											
												
													
														|  | 
 |  | +pub struct BtfRelocationError {
 | 
											
												
													
														|  | 
 |  | +    /// The function name
 | 
											
												
													
														|  | 
 |  | +    pub section: String,
 | 
											
												
													
														|  | 
 |  | +    #[source]
 | 
											
												
													
														|  | 
 |  | +    /// The original error
 | 
											
												
													
														|  | 
 |  | +    error: RelocationError,
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +/// Relocation failures
 | 
											
												
													
														|  |  #[derive(Error, Debug)]
 |  |  #[derive(Error, Debug)]
 | 
											
												
													
														|  |  enum RelocationError {
 |  |  enum RelocationError {
 | 
											
												
													
														|  | 
 |  | +    #[cfg(not(feature = "no_std"))]
 | 
											
												
													
														|  | 
 |  | +    /// I/O error
 | 
											
												
													
														|  |      #[error(transparent)]
 |  |      #[error(transparent)]
 | 
											
												
													
														|  | -    IOError(#[from] io::Error),
 |  | 
 | 
											
												
													
														|  | 
 |  | +    IOError(#[from] std::io::Error),
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Program not found
 | 
											
												
													
														|  |      #[error("program not found")]
 |  |      #[error("program not found")]
 | 
											
												
													
														|  |      ProgramNotFound,
 |  |      ProgramNotFound,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Invalid relocation access string
 | 
											
												
													
														|  |      #[error("invalid relocation access string {access_str}")]
 |  |      #[error("invalid relocation access string {access_str}")]
 | 
											
												
													
														|  | -    InvalidAccessString { access_str: String },
 |  | 
 | 
											
												
													
														|  | 
 |  | +    InvalidAccessString {
 | 
											
												
													
														|  | 
 |  | +        /// The access string
 | 
											
												
													
														|  | 
 |  | +        access_str: String,
 | 
											
												
													
														|  | 
 |  | +    },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Invalid instruction index referenced by relocation
 | 
											
												
													
														|  |      #[error("invalid instruction index #{index} referenced by relocation #{relocation_number}, the program contains {num_instructions} instructions")]
 |  |      #[error("invalid instruction index #{index} referenced by relocation #{relocation_number}, the program contains {num_instructions} instructions")]
 | 
											
												
													
														|  |      InvalidInstructionIndex {
 |  |      InvalidInstructionIndex {
 | 
											
												
													
														|  | 
 |  | +        /// The invalid instruction index
 | 
											
												
													
														|  |          index: usize,
 |  |          index: usize,
 | 
											
												
													
														|  | 
 |  | +        /// Number of instructions in the program
 | 
											
												
													
														|  |          num_instructions: usize,
 |  |          num_instructions: usize,
 | 
											
												
													
														|  | 
 |  | +        /// The relocation number
 | 
											
												
													
														|  |          relocation_number: usize,
 |  |          relocation_number: usize,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Multiple candidate target types found with different memory layouts
 | 
											
												
													
														|  |      #[error("error relocating {type_name}, multiple candidate target types found with different memory layouts: {candidates:?}")]
 |  |      #[error("error relocating {type_name}, multiple candidate target types found with different memory layouts: {candidates:?}")]
 | 
											
												
													
														|  |      ConflictingCandidates {
 |  |      ConflictingCandidates {
 | 
											
												
													
														|  | 
 |  | +        /// The type name
 | 
											
												
													
														|  |          type_name: String,
 |  |          type_name: String,
 | 
											
												
													
														|  | 
 |  | +        /// The candidates
 | 
											
												
													
														|  |          candidates: Vec<String>,
 |  |          candidates: Vec<String>,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Maximum nesting level reached evaluating candidate type
 | 
											
												
													
														|  |      #[error("maximum nesting level reached evaluating candidate type `{}`", err_type_name(.type_name))]
 |  |      #[error("maximum nesting level reached evaluating candidate type `{}`", err_type_name(.type_name))]
 | 
											
												
													
														|  | -    MaximumNestingLevelReached { type_name: Option<String> },
 |  | 
 | 
											
												
													
														|  | 
 |  | +    MaximumNestingLevelReached {
 | 
											
												
													
														|  | 
 |  | +        /// The type name
 | 
											
												
													
														|  | 
 |  | +        type_name: Option<String>,
 | 
											
												
													
														|  | 
 |  | +    },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Invalid access string
 | 
											
												
													
														|  |      #[error("invalid access string `{spec}` for type `{}`: {error}", err_type_name(.type_name))]
 |  |      #[error("invalid access string `{spec}` for type `{}`: {error}", err_type_name(.type_name))]
 | 
											
												
													
														|  |      InvalidAccessIndex {
 |  |      InvalidAccessIndex {
 | 
											
												
													
														|  | 
 |  | +        /// The type name
 | 
											
												
													
														|  |          type_name: Option<String>,
 |  |          type_name: Option<String>,
 | 
											
												
													
														|  | 
 |  | +        /// The access string
 | 
											
												
													
														|  |          spec: String,
 |  |          spec: String,
 | 
											
												
													
														|  | 
 |  | +        /// The index
 | 
											
												
													
														|  |          index: usize,
 |  |          index: usize,
 | 
											
												
													
														|  | 
 |  | +        /// The max index
 | 
											
												
													
														|  |          max_index: usize,
 |  |          max_index: usize,
 | 
											
												
													
														|  | 
 |  | +        /// The error message
 | 
											
												
													
														|  |          error: String,
 |  |          error: String,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Relocation not valid for type
 | 
											
												
													
														|  |      #[error(
 |  |      #[error(
 | 
											
												
													
														|  |          "relocation #{relocation_number} of kind `{relocation_kind}` not valid for type `{type_kind}`: {error}"
 |  |          "relocation #{relocation_number} of kind `{relocation_kind}` not valid for type `{type_kind}`: {error}"
 | 
											
												
													
														|  |      )]
 |  |      )]
 | 
											
												
													
														|  |      InvalidRelocationKindForType {
 |  |      InvalidRelocationKindForType {
 | 
											
												
													
														|  | 
 |  | +        /// The relocation number
 | 
											
												
													
														|  |          relocation_number: usize,
 |  |          relocation_number: usize,
 | 
											
												
													
														|  | 
 |  | +        /// The relocation kind
 | 
											
												
													
														|  |          relocation_kind: String,
 |  |          relocation_kind: String,
 | 
											
												
													
														|  | 
 |  | +        /// The type kind
 | 
											
												
													
														|  |          type_kind: String,
 |  |          type_kind: String,
 | 
											
												
													
														|  | 
 |  | +        /// The error message
 | 
											
												
													
														|  |          error: String,
 |  |          error: String,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /// Invalid instruction referenced by relocation
 | 
											
												
													
														|  |      #[error(
 |  |      #[error(
 | 
											
												
													
														|  |          "instruction #{index} referenced by relocation #{relocation_number} is invalid: {error}"
 |  |          "instruction #{index} referenced by relocation #{relocation_number} is invalid: {error}"
 | 
											
												
													
														|  |      )]
 |  |      )]
 | 
											
												
													
														|  |      InvalidInstruction {
 |  |      InvalidInstruction {
 | 
											
												
													
														|  | 
 |  | +        /// The relocation number
 | 
											
												
													
														|  |          relocation_number: usize,
 |  |          relocation_number: usize,
 | 
											
												
													
														|  | 
 |  | +        /// The instruction index
 | 
											
												
													
														|  |          index: usize,
 |  |          index: usize,
 | 
											
												
													
														|  | 
 |  | +        /// The error message
 | 
											
												
													
														|  |          error: String,
 |  |          error: String,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -78,6 +128,10 @@ enum RelocationError {
 | 
											
												
													
														|  |          type_id: u32,
 |  |          type_id: u32,
 | 
											
												
													
														|  |          ins_index: usize,
 |  |          ins_index: usize,
 | 
											
												
													
														|  |      },
 |  |      },
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /// BTF error
 | 
											
												
													
														|  | 
 |  | +    #[error("invalid BTF")]
 | 
											
												
													
														|  | 
 |  | +    BtfError(#[from] BtfError),
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  fn err_type_name(name: &Option<String>) -> String {
 |  |  fn err_type_name(name: &Option<String>) -> String {
 | 
											
										
											
												
													
														|  | @@ -126,7 +180,7 @@ impl TryFrom<u32> for RelocationKind {
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #[derive(Debug, Copy, Clone)]
 |  |  #[derive(Debug, Copy, Clone)]
 | 
											
												
													
														|  | -pub struct Relocation {
 |  | 
 | 
											
												
													
														|  | 
 |  | +pub(crate) struct Relocation {
 | 
											
												
													
														|  |      kind: RelocationKind,
 |  |      kind: RelocationKind,
 | 
											
												
													
														|  |      ins_offset: usize,
 |  |      ins_offset: usize,
 | 
											
												
													
														|  |      type_id: u32,
 |  |      type_id: u32,
 | 
											
										
											
												
													
														|  | @@ -154,7 +208,8 @@ impl Relocation {
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl Object {
 |  |  impl Object {
 | 
											
												
													
														|  | -    pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BpfError> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    /// Relocates programs inside this object file with loaded BTF info.
 | 
											
												
													
														|  | 
 |  | +    pub fn relocate_btf(&mut self, target_btf: &Btf) -> Result<(), BtfRelocationError> {
 | 
											
												
													
														|  |          let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) {
 |  |          let (local_btf, btf_ext) = match (&self.btf, &self.btf_ext) {
 | 
											
												
													
														|  |              (Some(btf), Some(btf_ext)) => (btf, btf_ext),
 |  |              (Some(btf), Some(btf_ext)) => (btf, btf_ext),
 | 
											
												
													
														|  |              _ => return Ok(()),
 |  |              _ => return Ok(()),
 | 
											
										
											
												
													
														|  | @@ -162,7 +217,13 @@ impl Object {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new();
 |  |          let mut candidates_cache = HashMap::<u32, Vec<Candidate>>::new();
 | 
											
												
													
														|  |          for (sec_name_off, relos) in btf_ext.relocations() {
 |  |          for (sec_name_off, relos) in btf_ext.relocations() {
 | 
											
												
													
														|  | -            let section_name = local_btf.string_at(*sec_name_off)?;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            let section_name =
 | 
											
												
													
														|  | 
 |  | +                local_btf
 | 
											
												
													
														|  | 
 |  | +                    .string_at(*sec_name_off)
 | 
											
												
													
														|  | 
 |  | +                    .map_err(|e| BtfRelocationError {
 | 
											
												
													
														|  | 
 |  | +                        section: format!("section@{sec_name_off}"),
 | 
											
												
													
														|  | 
 |  | +                        error: RelocationError::BtfError(e),
 | 
											
												
													
														|  | 
 |  | +                    })?;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |              let program_section = match ProgramSection::from_str(§ion_name) {
 |  |              let program_section = match ProgramSection::from_str(§ion_name) {
 | 
											
												
													
														|  |                  Ok(program) => program,
 |  |                  Ok(program) => program,
 | 
											
										
											
												
													
														|  | @@ -173,18 +234,17 @@ impl Object {
 | 
											
												
													
														|  |              let program = self
 |  |              let program = self
 | 
											
												
													
														|  |                  .programs
 |  |                  .programs
 | 
											
												
													
														|  |                  .get_mut(section_name)
 |  |                  .get_mut(section_name)
 | 
											
												
													
														|  | -                .ok_or(BpfError::RelocationError {
 |  | 
 | 
											
												
													
														|  | -                    function: section_name.to_owned(),
 |  | 
 | 
											
												
													
														|  | -                    error: Box::new(RelocationError::ProgramNotFound),
 |  | 
 | 
											
												
													
														|  | 
 |  | +                .ok_or(BtfRelocationError {
 | 
											
												
													
														|  | 
 |  | +                    section: section_name.to_owned(),
 | 
											
												
													
														|  | 
 |  | +                    error: RelocationError::ProgramNotFound,
 | 
											
												
													
														|  |                  })?;
 |  |                  })?;
 | 
											
												
													
														|  |              match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache)
 |  |              match relocate_btf_program(program, relos, local_btf, target_btf, &mut candidates_cache)
 | 
											
												
													
														|  |              {
 |  |              {
 | 
											
												
													
														|  |                  Ok(_) => {}
 |  |                  Ok(_) => {}
 | 
											
												
													
														|  | -                Err(ErrorWrapper::BtfError(e)) => return Err(e.into()),
 |  | 
 | 
											
												
													
														|  | -                Err(ErrorWrapper::RelocationError(error)) => {
 |  | 
 | 
											
												
													
														|  | -                    return Err(BpfError::RelocationError {
 |  | 
 | 
											
												
													
														|  | -                        function: section_name.to_owned(),
 |  | 
 | 
											
												
													
														|  | -                        error: Box::new(error),
 |  | 
 | 
											
												
													
														|  | 
 |  | +                Err(error) => {
 | 
											
												
													
														|  | 
 |  | +                    return Err(BtfRelocationError {
 | 
											
												
													
														|  | 
 |  | +                        section: section_name.to_owned(),
 | 
											
												
													
														|  | 
 |  | +                        error,
 | 
											
												
													
														|  |                      })
 |  |                      })
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
										
											
												
													
														|  | @@ -200,17 +260,16 @@ fn relocate_btf_program<'target>(
 | 
											
												
													
														|  |      local_btf: &Btf,
 |  |      local_btf: &Btf,
 | 
											
												
													
														|  |      target_btf: &'target Btf,
 |  |      target_btf: &'target Btf,
 | 
											
												
													
														|  |      candidates_cache: &mut HashMap<u32, Vec<Candidate<'target>>>,
 |  |      candidates_cache: &mut HashMap<u32, Vec<Candidate<'target>>>,
 | 
											
												
													
														|  | -) -> Result<(), ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +) -> Result<(), RelocationError> {
 | 
											
												
													
														|  |      for rel in relos {
 |  |      for rel in relos {
 | 
											
												
													
														|  |          let instructions = &mut program.function.instructions;
 |  |          let instructions = &mut program.function.instructions;
 | 
											
												
													
														|  | -        let ins_index = rel.ins_offset / std::mem::size_of::<bpf_insn>();
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let ins_index = rel.ins_offset / mem::size_of::<bpf_insn>();
 | 
											
												
													
														|  |          if ins_index >= instructions.len() {
 |  |          if ins_index >= instructions.len() {
 | 
											
												
													
														|  |              return Err(RelocationError::InvalidInstructionIndex {
 |  |              return Err(RelocationError::InvalidInstructionIndex {
 | 
											
												
													
														|  |                  index: ins_index,
 |  |                  index: ins_index,
 | 
											
												
													
														|  |                  num_instructions: instructions.len(),
 |  |                  num_instructions: instructions.len(),
 | 
											
												
													
														|  |                  relocation_number: rel.number,
 |  |                  relocation_number: rel.number,
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          let local_ty = local_btf.type_by_id(rel.type_id)?;
 |  |          let local_ty = local_btf.type_by_id(rel.type_id)?;
 | 
											
										
											
												
													
														|  | @@ -266,8 +325,7 @@ fn relocate_btf_program<'target>(
 | 
											
												
													
														|  |                  return Err(RelocationError::ConflictingCandidates {
 |  |                  return Err(RelocationError::ConflictingCandidates {
 | 
											
												
													
														|  |                      type_name: local_name.to_string(),
 |  |                      type_name: local_name.to_string(),
 | 
											
												
													
														|  |                      candidates: conflicts,
 |  |                      candidates: conflicts,
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | -                .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                });
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              target_comp_rel
 |  |              target_comp_rel
 | 
											
												
													
														|  |          } else {
 |  |          } else {
 | 
											
										
											
												
													
														|  | @@ -317,7 +375,7 @@ fn find_candidates<'target>(
 | 
											
												
													
														|  |  fn match_candidate<'target>(
 |  |  fn match_candidate<'target>(
 | 
											
												
													
														|  |      local_spec: &AccessSpec,
 |  |      local_spec: &AccessSpec,
 | 
											
												
													
														|  |      candidate: &'target Candidate,
 |  |      candidate: &'target Candidate,
 | 
											
												
													
														|  | -) -> Result<Option<AccessSpec<'target>>, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +) -> Result<Option<AccessSpec<'target>>, RelocationError> {
 | 
											
												
													
														|  |      let mut target_spec = AccessSpec {
 |  |      let mut target_spec = AccessSpec {
 | 
											
												
													
														|  |          btf: candidate.btf,
 |  |          btf: candidate.btf,
 | 
											
												
													
														|  |          root_type_id: candidate.type_id,
 |  |          root_type_id: candidate.type_id,
 | 
											
										
											
												
													
														|  | @@ -419,8 +477,7 @@ fn match_candidate<'target>(
 | 
											
												
													
														|  |                      if target_spec.parts.len() == MAX_SPEC_LEN {
 |  |                      if target_spec.parts.len() == MAX_SPEC_LEN {
 | 
											
												
													
														|  |                          return Err(RelocationError::MaximumNestingLevelReached {
 |  |                          return Err(RelocationError::MaximumNestingLevelReached {
 | 
											
												
													
														|  |                              type_name: Some(candidate.name.clone()),
 |  |                              type_name: Some(candidate.name.clone()),
 | 
											
												
													
														|  | -                        }
 |  | 
 | 
											
												
													
														|  | -                        .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        });
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                      target_spec.parts.push(accessor.index);
 |  |                      target_spec.parts.push(accessor.index);
 | 
											
										
											
												
													
														|  | @@ -446,7 +503,7 @@ fn match_member<'target>(
 | 
											
												
													
														|  |      target_btf: &'target Btf,
 |  |      target_btf: &'target Btf,
 | 
											
												
													
														|  |      target_id: u32,
 |  |      target_id: u32,
 | 
											
												
													
														|  |      target_spec: &mut AccessSpec<'target>,
 |  |      target_spec: &mut AccessSpec<'target>,
 | 
											
												
													
														|  | -) -> Result<Option<u32>, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +) -> Result<Option<u32>, RelocationError> {
 | 
											
												
													
														|  |      let local_ty = local_btf.type_by_id(local_accessor.type_id)?;
 |  |      let local_ty = local_btf.type_by_id(local_accessor.type_id)?;
 | 
											
												
													
														|  |      let local_member = match local_ty {
 |  |      let local_member = match local_ty {
 | 
											
												
													
														|  |          // this won't panic, bounds are checked when local_spec is built in AccessSpec::new
 |  |          // this won't panic, bounds are checked when local_spec is built in AccessSpec::new
 | 
											
										
											
												
													
														|  | @@ -470,8 +527,7 @@ fn match_member<'target>(
 | 
											
												
													
														|  |              let root_ty = target_spec.btf.type_by_id(target_spec.root_type_id)?;
 |  |              let root_ty = target_spec.btf.type_by_id(target_spec.root_type_id)?;
 | 
											
												
													
														|  |              return Err(RelocationError::MaximumNestingLevelReached {
 |  |              return Err(RelocationError::MaximumNestingLevelReached {
 | 
											
												
													
														|  |                  type_name: target_spec.btf.err_type_name(root_ty),
 |  |                  type_name: target_spec.btf.err_type_name(root_ty),
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +            });
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          // this will not panic as we've already established these are fields types
 |  |          // this will not panic as we've already established these are fields types
 | 
											
										
											
												
													
														|  | @@ -532,7 +588,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |          root_type_id: u32,
 |  |          root_type_id: u32,
 | 
											
												
													
														|  |          spec: &str,
 |  |          spec: &str,
 | 
											
												
													
														|  |          relocation: Relocation,
 |  |          relocation: Relocation,
 | 
											
												
													
														|  | -    ) -> Result<AccessSpec<'a>, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    ) -> Result<AccessSpec<'a>, RelocationError> {
 | 
											
												
													
														|  |          let parts = spec
 |  |          let parts = spec
 | 
											
												
													
														|  |              .split(':')
 |  |              .split(':')
 | 
											
												
													
														|  |              .map(|s| s.parse::<usize>())
 |  |              .map(|s| s.parse::<usize>())
 | 
											
										
											
												
													
														|  | @@ -552,8 +608,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                  if parts != [0] {
 |  |                  if parts != [0] {
 | 
											
												
													
														|  |                      return Err(RelocationError::InvalidAccessString {
 |  |                      return Err(RelocationError::InvalidAccessString {
 | 
											
												
													
														|  |                          access_str: spec.to_string(),
 |  |                          access_str: spec.to_string(),
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    });
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |                  AccessSpec {
 |  |                  AccessSpec {
 | 
											
												
													
														|  |                      btf,
 |  |                      btf,
 | 
											
										
											
												
													
														|  | @@ -569,8 +624,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                      if parts.len() != 1 {
 |  |                      if parts.len() != 1 {
 | 
											
												
													
														|  |                          return Err(RelocationError::InvalidAccessString {
 |  |                          return Err(RelocationError::InvalidAccessString {
 | 
											
												
													
														|  |                              access_str: spec.to_string(),
 |  |                              access_str: spec.to_string(),
 | 
											
												
													
														|  | -                        }
 |  | 
 | 
											
												
													
														|  | -                        .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        });
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |                      let index = parts[0];
 |  |                      let index = parts[0];
 | 
											
												
													
														|  |                      if index >= en.variants.len() {
 |  |                      if index >= en.variants.len() {
 | 
											
										
											
												
													
														|  | @@ -580,8 +634,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                              index,
 |  |                              index,
 | 
											
												
													
														|  |                              max_index: en.variants.len(),
 |  |                              max_index: en.variants.len(),
 | 
											
												
													
														|  |                              error: "tried to access nonexistant enum variant".to_string(),
 |  |                              error: "tried to access nonexistant enum variant".to_string(),
 | 
											
												
													
														|  | -                        }
 |  | 
 | 
											
												
													
														|  | -                        .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        });
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |                      let accessors = vec![Accessor {
 |  |                      let accessors = vec![Accessor {
 | 
											
												
													
														|  |                          type_id,
 |  |                          type_id,
 | 
											
										
											
												
													
														|  | @@ -607,8 +660,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                          relocation_kind: format!("{:?}", relocation.kind),
 |  |                          relocation_kind: format!("{:?}", relocation.kind),
 | 
											
												
													
														|  |                          type_kind: format!("{:?}", ty.kind()),
 |  |                          type_kind: format!("{:?}", ty.kind()),
 | 
											
												
													
														|  |                          error: "enum relocation on non-enum type".to_string(),
 |  |                          error: "enum relocation on non-enum type".to_string(),
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    .into())
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    })
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |              },
 |  |              },
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -638,8 +690,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                                      index,
 |  |                                      index,
 | 
											
												
													
														|  |                                      max_index: members.len(),
 |  |                                      max_index: members.len(),
 | 
											
												
													
														|  |                                      error: "out of bounds struct or union access".to_string(),
 |  |                                      error: "out of bounds struct or union access".to_string(),
 | 
											
												
													
														|  | -                                }
 |  | 
 | 
											
												
													
														|  | -                                .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                                });
 | 
											
												
													
														|  |                              }
 |  |                              }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                              let member = &members[index];
 |  |                              let member = &members[index];
 | 
											
										
											
												
													
														|  | @@ -675,8 +726,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                                      index,
 |  |                                      index,
 | 
											
												
													
														|  |                                      max_index: array.len as usize,
 |  |                                      max_index: array.len as usize,
 | 
											
												
													
														|  |                                      error: "array index out of bounds".to_string(),
 |  |                                      error: "array index out of bounds".to_string(),
 | 
											
												
													
														|  | -                                }
 |  | 
 | 
											
												
													
														|  | -                                .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                                });
 | 
											
												
													
														|  |                              }
 |  |                              }
 | 
											
												
													
														|  |                              accessors.push(Accessor {
 |  |                              accessors.push(Accessor {
 | 
											
												
													
														|  |                                  type_id,
 |  |                                  type_id,
 | 
											
										
											
												
													
														|  | @@ -693,8 +743,7 @@ impl<'a> AccessSpec<'a> {
 | 
											
												
													
														|  |                                  type_kind: format!("{:?}", ty.kind()),
 |  |                                  type_kind: format!("{:?}", ty.kind()),
 | 
											
												
													
														|  |                                  error: "field relocation on a type that doesn't have fields"
 |  |                                  error: "field relocation on a type that doesn't have fields"
 | 
											
												
													
														|  |                                      .to_string(),
 |  |                                      .to_string(),
 | 
											
												
													
														|  | -                            }
 |  | 
 | 
											
												
													
														|  | -                            .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                            });
 | 
											
												
													
														|  |                          }
 |  |                          }
 | 
											
												
													
														|  |                      };
 |  |                      };
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
										
											
												
													
														|  | @@ -747,7 +796,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |          rel: &Relocation,
 |  |          rel: &Relocation,
 | 
											
												
													
														|  |          local_spec: &AccessSpec,
 |  |          local_spec: &AccessSpec,
 | 
											
												
													
														|  |          target_spec: Option<&AccessSpec>,
 |  |          target_spec: Option<&AccessSpec>,
 | 
											
												
													
														|  | -    ) -> Result<ComputedRelocation, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    ) -> Result<ComputedRelocation, RelocationError> {
 | 
											
												
													
														|  |          use RelocationKind::*;
 |  |          use RelocationKind::*;
 | 
											
												
													
														|  |          let ret = match rel.kind {
 |  |          let ret = match rel.kind {
 | 
											
												
													
														|  |              FieldByteOffset | FieldByteSize | FieldExists | FieldSigned | FieldLShift64
 |  |              FieldByteOffset | FieldByteSize | FieldExists | FieldSigned | FieldLShift64
 | 
											
										
											
												
													
														|  | @@ -774,10 +823,10 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |          rel: &Relocation,
 |  |          rel: &Relocation,
 | 
											
												
													
														|  |          local_btf: &Btf,
 |  |          local_btf: &Btf,
 | 
											
												
													
														|  |          target_btf: &Btf,
 |  |          target_btf: &Btf,
 | 
											
												
													
														|  | -    ) -> Result<(), ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    ) -> Result<(), RelocationError> {
 | 
											
												
													
														|  |          let instructions = &mut program.function.instructions;
 |  |          let instructions = &mut program.function.instructions;
 | 
											
												
													
														|  |          let num_instructions = instructions.len();
 |  |          let num_instructions = instructions.len();
 | 
											
												
													
														|  | -        let ins_index = rel.ins_offset / std::mem::size_of::<bpf_insn>();
 |  | 
 | 
											
												
													
														|  | 
 |  | +        let ins_index = rel.ins_offset / mem::size_of::<bpf_insn>();
 | 
											
												
													
														|  |          let mut ins =
 |  |          let mut ins =
 | 
											
												
													
														|  |              instructions
 |  |              instructions
 | 
											
												
													
														|  |                  .get_mut(ins_index)
 |  |                  .get_mut(ins_index)
 | 
											
										
											
												
													
														|  | @@ -799,20 +848,18 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |                          relocation_number: rel.number,
 |  |                          relocation_number: rel.number,
 | 
											
												
													
														|  |                          index: ins_index,
 |  |                          index: ins_index,
 | 
											
												
													
														|  |                          error: format!("invalid src_reg={src_reg:x} expected {BPF_K:x}"),
 |  |                          error: format!("invalid src_reg={src_reg:x} expected {BPF_K:x}"),
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    });
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  ins.imm = target_value as i32;
 |  |                  ins.imm = target_value as i32;
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              BPF_LDX | BPF_ST | BPF_STX => {
 |  |              BPF_LDX | BPF_ST | BPF_STX => {
 | 
											
												
													
														|  | -                if target_value > std::i16::MAX as u32 {
 |  | 
 | 
											
												
													
														|  | 
 |  | +                if target_value > i16::MAX as u32 {
 | 
											
												
													
														|  |                      return Err(RelocationError::InvalidInstruction {
 |  |                      return Err(RelocationError::InvalidInstruction {
 | 
											
												
													
														|  |                          relocation_number: rel.number,
 |  |                          relocation_number: rel.number,
 | 
											
												
													
														|  |                          index: ins_index,
 |  |                          index: ins_index,
 | 
											
												
													
														|  |                          error: format!("value `{target_value}` overflows 16 bits offset field"),
 |  |                          error: format!("value `{target_value}` overflows 16 bits offset field"),
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    });
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |                  ins.off = target_value as i16;
 |  |                  ins.off = target_value as i16;
 | 
											
										
											
												
													
														|  | @@ -837,8 +884,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |                                      err_type_name(&target_btf.err_type_name(target_ty)),
 |  |                                      err_type_name(&target_btf.err_type_name(target_ty)),
 | 
											
												
													
														|  |                                      self.target.size,
 |  |                                      self.target.size,
 | 
											
												
													
														|  |                                  ),
 |  |                                  ),
 | 
											
												
													
														|  | -                            }
 |  | 
 | 
											
												
													
														|  | -                            .into())
 |  | 
 | 
											
												
													
														|  | 
 |  | +                            })
 | 
											
												
													
														|  |                          }
 |  |                          }
 | 
											
												
													
														|  |                      }
 |  |                      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -852,8 +898,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |                                  relocation_number: rel.number,
 |  |                                  relocation_number: rel.number,
 | 
											
												
													
														|  |                                  index: ins_index,
 |  |                                  index: ins_index,
 | 
											
												
													
														|  |                                  error: format!("invalid target size {size}"),
 |  |                                  error: format!("invalid target size {size}"),
 | 
											
												
													
														|  | -                            }
 |  | 
 | 
											
												
													
														|  | -                            .into())
 |  | 
 | 
											
												
													
														|  | 
 |  | +                            })
 | 
											
												
													
														|  |                          }
 |  |                          }
 | 
											
												
													
														|  |                      } as u8;
 |  |                      } as u8;
 | 
											
												
													
														|  |                      ins.code = ins.code & 0xE0 | size | ins.code & 0x07;
 |  |                      ins.code = ins.code & 0xE0 | size | ins.code & 0x07;
 | 
											
										
											
												
													
														|  | @@ -876,8 +921,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |                      relocation_number: rel.number,
 |  |                      relocation_number: rel.number,
 | 
											
												
													
														|  |                      index: ins_index,
 |  |                      index: ins_index,
 | 
											
												
													
														|  |                      error: format!("invalid instruction class {class:x}"),
 |  |                      error: format!("invalid instruction class {class:x}"),
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | -                .into())
 |  | 
 | 
											
												
													
														|  | 
 |  | +                })
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          };
 |  |          };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -887,7 +931,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |      fn compute_enum_relocation(
 |  |      fn compute_enum_relocation(
 | 
											
												
													
														|  |          rel: &Relocation,
 |  |          rel: &Relocation,
 | 
											
												
													
														|  |          spec: Option<&AccessSpec>,
 |  |          spec: Option<&AccessSpec>,
 | 
											
												
													
														|  | -    ) -> Result<ComputedRelocationValue, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    ) -> Result<ComputedRelocationValue, RelocationError> {
 | 
											
												
													
														|  |          use RelocationKind::*;
 |  |          use RelocationKind::*;
 | 
											
												
													
														|  |          let value = match (rel.kind, spec) {
 |  |          let value = match (rel.kind, spec) {
 | 
											
												
													
														|  |              (EnumVariantExists, spec) => spec.is_some() as u32,
 |  |              (EnumVariantExists, spec) => spec.is_some() as u32,
 | 
											
										
											
												
													
														|  | @@ -918,7 +962,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |      fn compute_field_relocation(
 |  |      fn compute_field_relocation(
 | 
											
												
													
														|  |          rel: &Relocation,
 |  |          rel: &Relocation,
 | 
											
												
													
														|  |          spec: Option<&AccessSpec>,
 |  |          spec: Option<&AccessSpec>,
 | 
											
												
													
														|  | -    ) -> Result<ComputedRelocationValue, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    ) -> Result<ComputedRelocationValue, RelocationError> {
 | 
											
												
													
														|  |          use RelocationKind::*;
 |  |          use RelocationKind::*;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          if let FieldExists = rel.kind {
 |  |          if let FieldExists = rel.kind {
 | 
											
										
											
												
													
														|  | @@ -963,8 +1007,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |                          relocation_kind: format!("{rel_kind:?}"),
 |  |                          relocation_kind: format!("{rel_kind:?}"),
 | 
											
												
													
														|  |                          type_kind: format!("{:?}", ty.kind()),
 |  |                          type_kind: format!("{:?}", ty.kind()),
 | 
											
												
													
														|  |                          error: "invalid relocation kind for array type".to_string(),
 |  |                          error: "invalid relocation kind for array type".to_string(),
 | 
											
												
													
														|  | -                    }
 |  | 
 | 
											
												
													
														|  | -                    .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                    });
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  |              };
 |  |              };
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -979,8 +1022,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |                      relocation_kind: format!("{:?}", rel.kind),
 |  |                      relocation_kind: format!("{:?}", rel.kind),
 | 
											
												
													
														|  |                      type_kind: format!("{:?}", ty.kind()),
 |  |                      type_kind: format!("{:?}", ty.kind()),
 | 
											
												
													
														|  |                      error: "field relocation on a type that doesn't have fields".to_string(),
 |  |                      error: "field relocation on a type that doesn't have fields".to_string(),
 | 
											
												
													
														|  | -                }
 |  | 
 | 
											
												
													
														|  | -                .into());
 |  | 
 | 
											
												
													
														|  | 
 |  | +                });
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          };
 |  |          };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1055,7 +1097,7 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |          rel: &Relocation,
 |  |          rel: &Relocation,
 | 
											
												
													
														|  |          local_spec: &AccessSpec,
 |  |          local_spec: &AccessSpec,
 | 
											
												
													
														|  |          target_spec: Option<&AccessSpec>,
 |  |          target_spec: Option<&AccessSpec>,
 | 
											
												
													
														|  | -    ) -> Result<ComputedRelocationValue, ErrorWrapper> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    ) -> Result<ComputedRelocationValue, RelocationError> {
 | 
											
												
													
														|  |          use RelocationKind::*;
 |  |          use RelocationKind::*;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          let value = match (rel.kind, target_spec) {
 |  |          let value = match (rel.kind, target_spec) {
 | 
											
										
											
												
													
														|  | @@ -1081,14 +1123,3 @@ impl ComputedRelocation {
 | 
											
												
													
														|  |          })
 |  |          })
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -// this exists only to simplify propagating errors from relocate_btf() and to associate
 |  | 
 | 
											
												
													
														|  | -// RelocationError(s) with their respective program name
 |  | 
 | 
											
												
													
														|  | -#[derive(Error, Debug)]
 |  | 
 | 
											
												
													
														|  | -enum ErrorWrapper {
 |  | 
 | 
											
												
													
														|  | -    #[error(transparent)]
 |  | 
 | 
											
												
													
														|  | -    BtfError(#[from] BtfError),
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -    #[error(transparent)]
 |  | 
 | 
											
												
													
														|  | -    RelocationError(#[from] RelocationError),
 |  | 
 | 
											
												
													
														|  | -}
 |  | 
 |