|
@@ -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),
|
|
|
|
-}
|
|
|