|
@@ -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>) -> 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<ComputedRelocationValue, ErrorWrapper> {
|
|
|
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::<bpf_insn>(),
|
|
|
+ })?;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
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();
|
|
|
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<ComputedRelocationValue, ErrorWrapper> {
|
|
|
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::<bpf_insn>(),
|
|
|
+ })?;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
Ok(ComputedRelocationValue {
|