btf relocs: don't panic on failed relocation

Error out instead of panicing when we can't find a compatible target
candidate for a relocation.
pull/402/head
Alessandro Decina 2 years ago
parent aba99ea4b1
commit c6f93b1775

@ -71,6 +71,13 @@ enum RelocationError {
index: usize, index: usize,
error: String, error: String,
}, },
#[error("applying relocation `{kind:?}` missing target BTF info for type `{type_id}` at instruction #{ins_index}")]
MissingTargetDefinition {
kind: RelocationKind,
type_id: u32,
ins_index: usize,
},
} }
fn err_type_name(name: &Option<String>) -> String { fn err_type_name(name: &Option<String>) -> String {
@ -266,7 +273,7 @@ fn relocate_btf_program<'target>(
} else { } else {
// there are no candidate matches and therefore no target_spec. This might mean // there are no candidate matches and therefore no target_spec. This might mean
// that matching failed, or that the relocation can be applied looking at local // that matching failed, or that the relocation can be applied looking at local
// types only // types only (eg with EnumVariantExists, FieldExists etc)
ComputedRelocation::new(rel, &local_spec, None)? ComputedRelocation::new(rel, &local_spec, None)?
}; };
@ -882,18 +889,23 @@ impl ComputedRelocation {
spec: Option<&AccessSpec>, spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> { ) -> Result<ComputedRelocationValue, ErrorWrapper> {
use RelocationKind::*; use RelocationKind::*;
let value = match rel.kind { let value = match (rel.kind, spec) {
EnumVariantExists => spec.is_some() as u32, (EnumVariantExists, spec) => spec.is_some() as u32,
EnumVariantValue => { (EnumVariantValue, Some(spec)) => {
let spec = spec.unwrap();
let accessor = &spec.accessors[0]; let accessor = &spec.accessors[0];
match spec.btf.type_by_id(accessor.type_id)? { match spec.btf.type_by_id(accessor.type_id)? {
BtfType::Enum(en) => en.variants[accessor.index].value as u32, BtfType::Enum(en) => en.variants[accessor.index].value as u32,
_ => panic!("should not be reached"), // candidate selection ensures that rel_kind == local_kind == target_kind
_ => unreachable!(),
} }
} }
// this function is only called for enum relocations _ => {
_ => panic!("should not be reached"), return Err(RelocationError::MissingTargetDefinition {
kind: rel.kind,
type_id: rel.type_id,
ins_index: rel.ins_offset / mem::size_of::<bpf_insn>(),
})?;
}
}; };
Ok(ComputedRelocationValue { Ok(ComputedRelocationValue {
@ -919,7 +931,17 @@ impl ComputedRelocation {
}); });
} }
let spec = spec.unwrap(); let spec = match spec {
Some(spec) => spec,
None => {
return Err(RelocationError::MissingTargetDefinition {
kind: rel.kind,
type_id: rel.type_id,
ins_index: rel.ins_offset / mem::size_of::<bpf_insn>(),
})?;
}
};
let accessor = spec.accessors.last().unwrap(); let accessor = spec.accessors.last().unwrap();
if accessor.name.is_none() { if accessor.name.is_none() {
// the last accessor is unnamed, meaning that this is an array access // the last accessor is unnamed, meaning that this is an array access
@ -1035,19 +1057,21 @@ impl ComputedRelocation {
target_spec: Option<&AccessSpec>, target_spec: Option<&AccessSpec>,
) -> Result<ComputedRelocationValue, ErrorWrapper> { ) -> Result<ComputedRelocationValue, ErrorWrapper> {
use RelocationKind::*; use RelocationKind::*;
let value = match rel.kind {
TypeIdLocal => local_spec.root_type_id, let value = match (rel.kind, target_spec) {
_ => match target_spec { (TypeIdLocal, _) => local_spec.root_type_id,
Some(target_spec) => match rel.kind { (TypeIdTarget, Some(target_spec)) => target_spec.root_type_id,
TypeIdTarget => target_spec.root_type_id, (TypeExists, target_spec) => target_spec.is_some() as u32,
TypeExists => 1, (TypeSize, Some(target_spec)) => {
TypeSize => target_spec.btf.type_size(target_spec.root_type_id)? as u32, target_spec.btf.type_size(target_spec.root_type_id)? as u32
_ => panic!("bug! this should not be reached"), }
}, _ => {
// FIXME in the case of TypeIdTarget and TypeSize this should probably fail the return Err(RelocationError::MissingTargetDefinition {
// relocation... kind: rel.kind,
None => 0, type_id: rel.type_id,
}, ins_index: rel.ins_offset / mem::size_of::<bpf_insn>(),
})?;
}
}; };
Ok(ComputedRelocationValue { Ok(ComputedRelocationValue {

Loading…
Cancel
Save