|
|
@ -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 {
|
|
|
|