aya-obj: rework `maps` section parsing

Avoid allocations and add comments explaining how things work.
pull/572/head
Alessandro Decina 2 years ago
parent bc8f4ef1c8
commit 5c4f1d69a6

@ -762,37 +762,6 @@ impl Object {
Ok(()) Ok(())
} }
fn parse_map_section(
&mut self,
section: &Section,
symbols: Vec<Symbol>,
) -> Result<(), ParseError> {
if symbols.is_empty() {
return Err(ParseError::NoSymbolsInMapSection {});
}
for (i, sym) in symbols.iter().enumerate() {
let start = sym.address as usize;
let end = start + sym.size as usize;
let data = &section.data[start..end];
let name = sym
.name
.as_ref()
.ok_or(ParseError::MapSymbolNameNotFound { i })?;
let def = parse_map_def(name, data)?;
self.maps.insert(
name.to_string(),
Map::Legacy(LegacyMap {
section_index: section.index.0,
symbol_index: sym.index,
def,
data: Vec::new(),
kind: MapKind::Other,
}),
);
}
Ok(())
}
fn parse_btf_maps( fn parse_btf_maps(
&mut self, &mut self,
section: &Section, section: &Section,
@ -875,19 +844,24 @@ impl Object {
self.parse_btf_maps(&section, symbols)? self.parse_btf_maps(&section, symbols)?
} }
BpfSectionKind::Maps => { BpfSectionKind::Maps => {
let symbols: Vec<Symbol> = self // take out self.maps so we can borrow the iterator below
.symbols_by_index // without cloning or collecting
.values() let mut maps = mem::take(&mut self.maps);
.filter(|s| {
if let Some(idx) = s.section_index { // extract the symbols for the .maps section, we'll need them
idx == section.index.0 // during parsing
} else { let symbols = self.symbols_by_index.values().filter(|s| {
false s.section_index
} .map(|idx| idx == section.index.0)
}) .unwrap_or(false)
.cloned() });
.collect();
self.parse_map_section(&section, symbols)? let res = parse_maps_section(&mut maps, &section, symbols);
// put the maps back
self.maps = maps;
res?
} }
BpfSectionKind::Program => { BpfSectionKind::Program => {
let program = self.parse_program(&section)?; let program = self.parse_program(&section)?;
@ -911,6 +885,45 @@ impl Object {
} }
} }
// Parses multiple map definition contained in a single `maps` section (which is
// different from `.maps` which is used for BTF). We can tell where each map is
// based on the symbol table.
fn parse_maps_section<'a, I: Iterator<Item = &'a Symbol>>(
maps: &mut HashMap<String, Map>,
section: &Section,
symbols: I,
) -> Result<(), ParseError> {
let mut have_symbols = false;
// each symbol in the section is a separate map
for (i, sym) in symbols.enumerate() {
let start = sym.address as usize;
let end = start + sym.size as usize;
let data = &section.data[start..end];
let name = sym
.name
.as_ref()
.ok_or(ParseError::MapSymbolNameNotFound { i })?;
let def = parse_map_def(name, data)?;
maps.insert(
name.to_string(),
Map::Legacy(LegacyMap {
section_index: section.index.0,
symbol_index: sym.index,
def,
data: Vec::new(),
kind: MapKind::Other,
}),
);
have_symbols = true;
}
if !have_symbols {
return Err(ParseError::NoSymbolsForMapSection);
}
Ok(())
}
/// Errors caught during parsing the object file /// Errors caught during parsing the object file
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[allow(missing_docs)] #[allow(missing_docs)]
@ -974,8 +987,8 @@ pub enum ParseError {
#[error("the map number {i} in the `maps` section doesn't have a symbol name")] #[error("the map number {i} in the `maps` section doesn't have a symbol name")]
MapSymbolNameNotFound { i: usize }, MapSymbolNameNotFound { i: usize },
#[error("no symbols found for the maps included in the maps section")] #[error("no symbols for `maps` section, can't parse maps")]
NoSymbolsInMapSection {}, NoSymbolsForMapsSection,
/// No BTF parsed for object /// No BTF parsed for object
#[error("no BTF parsed for object")] #[error("no BTF parsed for object")]

Loading…
Cancel
Save