|
|
@ -162,7 +162,7 @@ impl Object {
|
|
|
|
let section_name = local_btf.string_at(*sec_name_off)?;
|
|
|
|
let section_name = local_btf.string_at(*sec_name_off)?;
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME
|
|
|
|
// FIXME
|
|
|
|
let parts = section_name.split("/").collect::<Vec<_>>();
|
|
|
|
let parts = section_name.split('/').collect::<Vec<_>>();
|
|
|
|
if parts.len() < 2 {
|
|
|
|
if parts.len() < 2 {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -182,7 +182,7 @@ impl Object {
|
|
|
|
&mut candidates_cache,
|
|
|
|
&mut candidates_cache,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
Ok(_) => {}
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(ErrorWrapper::BtfError(e)) => return Err(e)?,
|
|
|
|
Err(ErrorWrapper::BtfError(e)) => return Err(e.into()),
|
|
|
|
Err(ErrorWrapper::RelocationError(error)) => {
|
|
|
|
Err(ErrorWrapper::RelocationError(error)) => {
|
|
|
|
return Err(BpfError::RelocationError {
|
|
|
|
return Err(BpfError::RelocationError {
|
|
|
|
function: section_name.to_owned(),
|
|
|
|
function: section_name.to_owned(),
|
|
|
@ -211,7 +211,8 @@ fn relocate_btf_program<'target>(
|
|
|
|
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)?;
|
|
|
@ -257,7 +258,7 @@ fn relocate_btf_program<'target>(
|
|
|
|
if cand_spec.bit_offset != target_spec.bit_offset
|
|
|
|
if cand_spec.bit_offset != target_spec.bit_offset
|
|
|
|
|| cand_comp_rel.target.value != target_comp_rel.target.value
|
|
|
|
|| cand_comp_rel.target.value != target_comp_rel.target.value
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Some(cand_name.clone())
|
|
|
|
Some(cand_name)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -267,7 +268,8 @@ 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 {
|
|
|
@ -277,7 +279,7 @@ fn relocate_btf_program<'target>(
|
|
|
|
ComputedRelocation::new(rel, &local_spec, None)?
|
|
|
|
ComputedRelocation::new(rel, &local_spec, None)?
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
comp_rel.apply(program, rel, local_btf, &target_btf)?;
|
|
|
|
comp_rel.apply(program, rel, local_btf, target_btf)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
@ -305,7 +307,7 @@ fn find_candidates<'target>(
|
|
|
|
|
|
|
|
|
|
|
|
candidates.push(Candidate {
|
|
|
|
candidates.push(Candidate {
|
|
|
|
name: name.to_owned(),
|
|
|
|
name: name.to_owned(),
|
|
|
|
btf: &target_btf,
|
|
|
|
btf: target_btf,
|
|
|
|
ty,
|
|
|
|
ty,
|
|
|
|
type_id: type_id as u32,
|
|
|
|
type_id: type_id as u32,
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -381,7 +383,7 @@ fn match_candidate<'target>(
|
|
|
|
if accessor.name.is_some() {
|
|
|
|
if accessor.name.is_some() {
|
|
|
|
if let Some(next_id) = match_member(
|
|
|
|
if let Some(next_id) = match_member(
|
|
|
|
local_spec.btf,
|
|
|
|
local_spec.btf,
|
|
|
|
&local_spec,
|
|
|
|
local_spec,
|
|
|
|
accessor,
|
|
|
|
accessor,
|
|
|
|
candidate.btf,
|
|
|
|
candidate.btf,
|
|
|
|
target_id,
|
|
|
|
target_id,
|
|
|
@ -419,7 +421,8 @@ 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);
|
|
|
@ -470,13 +473,14 @@ fn match_member<'local, '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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let bit_offset = member_bit_offset(target_ty.info().unwrap(), target_member);
|
|
|
|
let bit_offset = member_bit_offset(target_ty.info().unwrap(), target_member);
|
|
|
|
let target_name = &*target_btf.string_at(target_member.name_off)?;
|
|
|
|
let target_name = &*target_btf.string_at(target_member.name_off)?;
|
|
|
|
|
|
|
|
|
|
|
|
if target_name == "" {
|
|
|
|
if target_name.is_empty() {
|
|
|
|
let ret = match_member(
|
|
|
|
let ret = match_member(
|
|
|
|
local_btf,
|
|
|
|
local_btf,
|
|
|
|
local_spec,
|
|
|
|
local_spec,
|
|
|
@ -532,7 +536,7 @@ impl<'a> AccessSpec<'a> {
|
|
|
|
relocation: Relocation,
|
|
|
|
relocation: Relocation,
|
|
|
|
) -> Result<AccessSpec<'a>, ErrorWrapper> {
|
|
|
|
) -> Result<AccessSpec<'a>, ErrorWrapper> {
|
|
|
|
let parts = spec
|
|
|
|
let parts = spec
|
|
|
|
.split(":")
|
|
|
|
.split(':')
|
|
|
|
.map(|s| s.parse::<usize>())
|
|
|
|
.map(|s| s.parse::<usize>())
|
|
|
|
.collect::<Result<Vec<_>, _>>()
|
|
|
|
.collect::<Result<Vec<_>, _>>()
|
|
|
|
.map_err(|_| RelocationError::InvalidAccessString {
|
|
|
|
.map_err(|_| RelocationError::InvalidAccessString {
|
|
|
@ -550,7 +554,8 @@ 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,
|
|
|
@ -566,17 +571,19 @@ 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 >= members.len() {
|
|
|
|
if index >= members.len() {
|
|
|
|
return Err(RelocationError::InvalidAccessIndex {
|
|
|
|
return Err(RelocationError::InvalidAccessIndex {
|
|
|
|
type_name: btf.err_type_name(ty),
|
|
|
|
type_name: btf.err_type_name(ty),
|
|
|
|
spec: spec.to_string(),
|
|
|
|
spec: spec.to_string(),
|
|
|
|
index: index,
|
|
|
|
index,
|
|
|
|
max_index: members.len(),
|
|
|
|
max_index: members.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,
|
|
|
@ -599,7 +606,8 @@ impl<'a> AccessSpec<'a> {
|
|
|
|
relocation_kind: format!("{:?}", relocation.kind),
|
|
|
|
relocation_kind: format!("{:?}", relocation.kind),
|
|
|
|
type_kind: format!("{:?}", ty.kind()?.unwrap()),
|
|
|
|
type_kind: format!("{:?}", ty.kind()?.unwrap()),
|
|
|
|
error: "enum relocation on non-enum type".to_string(),
|
|
|
|
error: "enum relocation on non-enum type".to_string(),
|
|
|
|
})?
|
|
|
|
}
|
|
|
|
|
|
|
|
.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
@ -626,10 +634,11 @@ impl<'a> AccessSpec<'a> {
|
|
|
|
return Err(RelocationError::InvalidAccessIndex {
|
|
|
|
return Err(RelocationError::InvalidAccessIndex {
|
|
|
|
type_name: btf.err_type_name(ty),
|
|
|
|
type_name: btf.err_type_name(ty),
|
|
|
|
spec: spec.to_string(),
|
|
|
|
spec: spec.to_string(),
|
|
|
|
index: 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];
|
|
|
@ -665,7 +674,8 @@ impl<'a> AccessSpec<'a> {
|
|
|
|
index,
|
|
|
|
index,
|
|
|
|
max_index: array.nelems as usize,
|
|
|
|
max_index: array.nelems 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,
|
|
|
@ -682,7 +692,8 @@ 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -690,9 +701,9 @@ impl<'a> AccessSpec<'a> {
|
|
|
|
AccessSpec {
|
|
|
|
AccessSpec {
|
|
|
|
btf,
|
|
|
|
btf,
|
|
|
|
root_type_id,
|
|
|
|
root_type_id,
|
|
|
|
relocation,
|
|
|
|
|
|
|
|
parts,
|
|
|
|
parts,
|
|
|
|
accessors,
|
|
|
|
accessors,
|
|
|
|
|
|
|
|
relocation,
|
|
|
|
bit_offset,
|
|
|
|
bit_offset,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -787,7 +798,8 @@ impl ComputedRelocation {
|
|
|
|
relocation_number: rel.number,
|
|
|
|
relocation_number: rel.number,
|
|
|
|
index: ins_index,
|
|
|
|
index: ins_index,
|
|
|
|
error: format!("invalid src_reg={:x} expected {:x}", src_reg, BPF_K),
|
|
|
|
error: format!("invalid src_reg={:x} expected {:x}", src_reg, BPF_K),
|
|
|
|
})?;
|
|
|
|
}
|
|
|
|
|
|
|
|
.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ins.imm = target_value as i32;
|
|
|
|
ins.imm = target_value as i32;
|
|
|
@ -798,7 +810,8 @@ impl ComputedRelocation {
|
|
|
|
relocation_number: rel.number,
|
|
|
|
relocation_number: rel.number,
|
|
|
|
index: ins_index,
|
|
|
|
index: ins_index,
|
|
|
|
error: format!("value `{}` overflows 16 bits offset field", target_value),
|
|
|
|
error: format!("value `{}` overflows 16 bits offset field", target_value),
|
|
|
|
})?;
|
|
|
|
}
|
|
|
|
|
|
|
|
.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ins.off = target_value as i16;
|
|
|
|
ins.off = target_value as i16;
|
|
|
@ -823,7 +836,8 @@ 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())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -837,7 +851,8 @@ 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;
|
|
|
@ -860,7 +875,8 @@ impl ComputedRelocation {
|
|
|
|
relocation_number: rel.number,
|
|
|
|
relocation_number: rel.number,
|
|
|
|
index: ins_index,
|
|
|
|
index: ins_index,
|
|
|
|
error: format!("invalid instruction class {:x}", class),
|
|
|
|
error: format!("invalid instruction class {:x}", class),
|
|
|
|
})?
|
|
|
|
}
|
|
|
|
|
|
|
|
.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -931,7 +947,8 @@ 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -947,7 +964,8 @@ 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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -967,7 +985,7 @@ impl ComputedRelocation {
|
|
|
|
while bit_off + bit_size - byte_off * 8 > byte_size * 8 {
|
|
|
|
while bit_off + bit_size - byte_off * 8 > byte_size * 8 {
|
|
|
|
if byte_size >= 8 {
|
|
|
|
if byte_size >= 8 {
|
|
|
|
// the bitfield is larger than 8 bytes!?
|
|
|
|
// the bitfield is larger than 8 bytes!?
|
|
|
|
return Err(BtfError::InvalidTypeInfo)?;
|
|
|
|
return Err(BtfError::InvalidTypeInfo.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
byte_size *= 2;
|
|
|
|
byte_size *= 2;
|
|
|
|
byte_off = bit_off / 8 / byte_size * byte_size;
|
|
|
|
byte_off = bit_off / 8 / byte_size * byte_size;
|
|
|
@ -983,6 +1001,8 @@ impl ComputedRelocation {
|
|
|
|
size: 0,
|
|
|
|
size: 0,
|
|
|
|
type_id: None,
|
|
|
|
type_id: None,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[allow(clippy::wildcard_in_or_patterns)]
|
|
|
|
match rel.kind {
|
|
|
|
match rel.kind {
|
|
|
|
FieldByteOffset => {
|
|
|
|
FieldByteOffset => {
|
|
|
|
value.value = byte_off;
|
|
|
|
value.value = byte_off;
|
|
|
|