aya-obj: Mutate BTF in-place without clone

The BTF we're working on is Cow anyway so modifying in-place is fine.
All we need to do is store some information before we start our
mutable iteration to avoid concurrently borrowing types both mutably and
immutably.

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
reviewable/pr731/r2
Dave Tucker 1 year ago
parent 761e4ddbe3
commit 098d4364bd

@ -475,7 +475,7 @@ impl Btf {
) -> Result<(), BtfError> { ) -> Result<(), BtfError> {
let mut types = mem::take(&mut self.types); let mut types = mem::take(&mut self.types);
for i in 0..types.types.len() { for i in 0..types.types.len() {
let t = &types.types[i]; let t = &mut types.types[i];
let kind = t.kind(); let kind = t.kind();
match t { match t {
// Fixup PTR for Rust // Fixup PTR for Rust
@ -483,9 +483,7 @@ impl Btf {
// While I figure out if this needs fixing in the Kernel or LLVM, we'll // While I figure out if this needs fixing in the Kernel or LLVM, we'll
// do a fixup here // do a fixup here
BtfType::Ptr(ptr) => { BtfType::Ptr(ptr) => {
let mut fixed_ty = ptr.clone(); ptr.name_offset = 0;
fixed_ty.name_offset = 0;
types.types[i] = BtfType::Ptr(fixed_ty)
} }
// Sanitize VAR if they are not supported // Sanitize VAR if they are not supported
BtfType::Var(v) if !features.btf_datasec => { BtfType::Var(v) if !features.btf_datasec => {
@ -496,7 +494,7 @@ impl Btf {
debug!("{}: not supported. replacing with STRUCT", kind); debug!("{}: not supported. replacing with STRUCT", kind);
// STRUCT aren't allowed to have "." in their name, fixup this if needed. // STRUCT aren't allowed to have "." in their name, fixup this if needed.
let mut name_offset = t.name_offset(); let mut name_offset = d.name_offset;
let name = self.string_at(name_offset)?; let name = self.string_at(name_offset)?;
// Handle any "." characters in struct names // Handle any "." characters in struct names
@ -506,18 +504,22 @@ impl Btf {
name_offset = self.add_string(&fixed_name); name_offset = self.add_string(&fixed_name);
} }
let mut members = vec![]; let entries = std::mem::take(&mut d.entries);
for member in d.entries.iter() {
let mt = types.type_by_id(member.btf_type).unwrap(); let members = entries
members.push(BtfMember { .iter()
name_offset: mt.name_offset(), .map(|e| {
btf_type: member.btf_type, let mt = types.type_by_id(e.btf_type).unwrap();
offset: member.offset * 8, BtfMember {
name_offset: mt.name_offset(),
btf_type: e.btf_type,
offset: e.offset * 8,
}
}) })
} .collect();
types.types[i] = types.types[i] =
BtfType::Struct(Struct::new(name_offset, members, d.entries.len() as u32)); BtfType::Struct(Struct::new(name_offset, members, entries.len() as u32));
} }
// Fixup DATASEC // Fixup DATASEC
// DATASEC sizes aren't always set by LLVM // DATASEC sizes aren't always set by LLVM
@ -527,18 +529,16 @@ impl Btf {
let name = self.string_at(d.name_offset)?; let name = self.string_at(d.name_offset)?;
let name = name.into_owned(); let name = name.into_owned();
let mut fixed_ty = d.clone();
// Handle any "/" characters in section names // Handle any "/" characters in section names
// Example: "maps/hashmap" // Example: "maps/hashmap"
let fixed_name = name.replace('/', "."); let fixed_name = name.replace('/', ".");
if fixed_name != name { if fixed_name != name {
fixed_ty.name_offset = self.add_string(&fixed_name); d.name_offset = self.add_string(&fixed_name);
} }
// There are some cases when the compiler does indeed populate the // There are some cases when the compiler does indeed populate the
// size // size
if t.size().unwrap() > 0 { if d.size > 0 {
debug!("{} {}: size fixup not required", kind, name); debug!("{} {}: size fixup not required", kind, name);
} else { } else {
// We need to get the size of the section from the ELF file // We need to get the size of the section from the ELF file
@ -551,22 +551,23 @@ impl Btf {
} }
}; };
debug!("{} {}: fixup size to {}", kind, name, size); debug!("{} {}: fixup size to {}", kind, name, size);
fixed_ty.size = *size as u32; d.size = *size as u32;
// The Vec<btf_var_secinfo> contains BTF_KIND_VAR sections // The Vec<btf_var_secinfo> contains BTF_KIND_VAR sections
// that need to have their offsets adjusted. To do this, // that need to have their offsets adjusted. To do this,
// we need to get the offset from the ELF file. // we need to get the offset from the ELF file.
// This was also cached during initial parsing and // This was also cached during initial parsing and
// we can query by name in symbol_offsets // we can query by name in symbol_offsets
for d in &mut fixed_ty.entries.iter_mut() { let mut entries = mem::take(&mut d.entries);
let var_type = types.type_by_id(d.btf_type)?; let mut fixed_section = d.clone();
let var_kind = var_type.kind();
if let BtfType::Var(var) = var_type { for e in entries.iter_mut() {
if let BtfType::Var(var) = types.type_by_id(e.btf_type)? {
let var_name = self.string_at(var.name_offset)?; let var_name = self.string_at(var.name_offset)?;
if var.linkage == VarLinkage::Static { if var.linkage == VarLinkage::Static {
debug!( debug!(
"{} {}: {} {}: fixup not required", "{} {}: VAR {}: fixup not required",
kind, name, var_kind, var_name kind, name, var_name
); );
continue; continue;
} }
@ -579,27 +580,26 @@ impl Btf {
}); });
} }
}; };
d.offset = *offset as u32; e.offset = *offset as u32;
debug!( debug!(
"{} {}: {} {}: fixup offset {}", "{} {}: VAR {}: fixup offset {}",
kind, name, var_kind, var_name, offset kind, name, var_name, offset
); );
} else { } else {
return Err(BtfError::InvalidDatasec); return Err(BtfError::InvalidDatasec);
} }
} }
fixed_section.entries = entries;
types.types[i] = BtfType::DataSec(fixed_section);
} }
types.types[i] = BtfType::DataSec(fixed_ty);
} }
// Fixup FUNC_PROTO // Fixup FUNC_PROTO
BtfType::FuncProto(ty) if features.btf_func => { BtfType::FuncProto(ty) if features.btf_func => {
let mut ty = ty.clone();
for (i, param) in ty.params.iter_mut().enumerate() { for (i, param) in ty.params.iter_mut().enumerate() {
if param.name_offset == 0 && param.btf_type != 0 { if param.name_offset == 0 && param.btf_type != 0 {
param.name_offset = self.add_string(&format!("param{i}")); param.name_offset = self.add_string(&format!("param{i}"));
} }
} }
types.types[i] = BtfType::FuncProto(ty);
} }
// Sanitize FUNC_PROTO // Sanitize FUNC_PROTO
BtfType::FuncProto(ty) if !features.btf_func => { BtfType::FuncProto(ty) if !features.btf_func => {
@ -635,7 +635,6 @@ impl Btf {
// and verified separately from their callers, while instead we // and verified separately from their callers, while instead we
// want tracking info (eg bound checks) to be propagated to the // want tracking info (eg bound checks) to be propagated to the
// memory builtins. // memory builtins.
let mut fixed_ty = ty.clone();
if ty.linkage() == FuncLinkage::Global { if ty.linkage() == FuncLinkage::Global {
if !features.btf_func_global { if !features.btf_func_global {
debug!( debug!(
@ -645,9 +644,8 @@ impl Btf {
} else { } else {
debug!("changing FUNC {name} linkage to BTF_FUNC_STATIC"); debug!("changing FUNC {name} linkage to BTF_FUNC_STATIC");
} }
fixed_ty.set_linkage(FuncLinkage::Static); ty.set_linkage(FuncLinkage::Static);
} }
types.types[i] = BtfType::Func(fixed_ty);
} }
} }
// Sanitize FLOAT // Sanitize FLOAT
@ -1244,9 +1242,9 @@ mod tests {
0, 0,
))); )));
let name_offset = btf.add_string("foo"); let var_name_offset = btf.add_string("foo");
let var_type_id = btf.add_type(BtfType::Var(Var::new( let var_type_id = btf.add_type(BtfType::Var(Var::new(
name_offset, var_name_offset,
int_type_id, int_type_id,
VarLinkage::Static, VarLinkage::Static,
))); )));
@ -1271,11 +1269,14 @@ mod tests {
assert_eq!(fixed.name_offset , name_offset); assert_eq!(fixed.name_offset , name_offset);
assert_matches!(*fixed.members, [ assert_matches!(*fixed.members, [
BtfMember { BtfMember {
name_offset: _, name_offset: name_offset1,
btf_type, btf_type,
offset: 0, offset: 0,
}, },
] => assert_eq!(btf_type, var_type_id)); ] => {
assert_eq!(name_offset1, var_name_offset);
assert_eq!(btf_type, var_type_id);
})
}); });
// Ensure we can convert to bytes and back again // Ensure we can convert to bytes and back again
let raw = btf.to_bytes(); let raw = btf.to_bytes();

Loading…
Cancel
Save