diff --git a/aya/src/obj/btf/relocation.rs b/aya/src/obj/btf/relocation.rs index eec03ecf0..285c5c030 100644 --- a/aya/src/obj/btf/relocation.rs +++ b/aya/src/obj/btf/relocation.rs @@ -71,6 +71,13 @@ enum RelocationError { index: usize, 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 { @@ -266,7 +273,7 @@ fn relocate_btf_program<'target>( } else { // 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 - // types only + // types only (eg with EnumVariantExists, FieldExists etc) ComputedRelocation::new(rel, &local_spec, None)? }; @@ -882,18 +889,23 @@ impl ComputedRelocation { spec: Option<&AccessSpec>, ) -> Result { use RelocationKind::*; - let value = match rel.kind { - EnumVariantExists => spec.is_some() as u32, - EnumVariantValue => { - let spec = spec.unwrap(); + let value = match (rel.kind, spec) { + (EnumVariantExists, spec) => spec.is_some() as u32, + (EnumVariantValue, Some(spec)) => { let accessor = &spec.accessors[0]; match spec.btf.type_by_id(accessor.type_id)? { 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::(), + })?; + } }; 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::(), + })?; + } + }; + let accessor = spec.accessors.last().unwrap(); if accessor.name.is_none() { // the last accessor is unnamed, meaning that this is an array access @@ -1035,19 +1057,21 @@ impl ComputedRelocation { target_spec: Option<&AccessSpec>, ) -> Result { use RelocationKind::*; - let value = match rel.kind { - TypeIdLocal => local_spec.root_type_id, - _ => match target_spec { - Some(target_spec) => match rel.kind { - TypeIdTarget => target_spec.root_type_id, - TypeExists => 1, - TypeSize => 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 - // relocation... - None => 0, - }, + + let value = match (rel.kind, target_spec) { + (TypeIdLocal, _) => local_spec.root_type_id, + (TypeIdTarget, Some(target_spec)) => target_spec.root_type_id, + (TypeExists, target_spec) => target_spec.is_some() as u32, + (TypeSize, Some(target_spec)) => { + target_spec.btf.type_size(target_spec.root_type_id)? as u32 + } + _ => { + return Err(RelocationError::MissingTargetDefinition { + kind: rel.kind, + type_id: rel.type_id, + ins_index: rel.ins_offset / mem::size_of::(), + })?; + } }; Ok(ComputedRelocationValue {