aya-obj: rework `maps` section parsing

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

@ -762,37 +762,6 @@ impl Object {
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(
&mut self,
section: &Section,
@ -875,19 +844,24 @@ impl Object {
self.parse_btf_maps(&section, symbols)?
}
BpfSectionKind::Maps => {
let symbols: Vec<Symbol> = self
.symbols_by_index
.values()
.filter(|s| {
if let Some(idx) = s.section_index {
idx == section.index.0
} else {
false
}
})
.cloned()
.collect();
self.parse_map_section(&section, symbols)?
// take out self.maps so we can borrow the iterator below
// without cloning or collecting
let mut maps = mem::take(&mut self.maps);
// extract the symbols for the .maps section, we'll need them
// during parsing
let symbols = self.symbols_by_index.values().filter(|s| {
s.section_index
.map(|idx| idx == section.index.0)
.unwrap_or(false)
});
let res = parse_maps_section(&mut maps, &section, symbols);
// put the maps back
self.maps = maps;
res?
}
BpfSectionKind::Program => {
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
#[derive(Debug, Error)]
#[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")]
MapSymbolNameNotFound { i: usize },
#[error("no symbols found for the maps included in the maps section")]
NoSymbolsInMapSection {},
#[error("no symbols for `maps` section, can't parse maps")]
NoSymbolsForMapsSection,
/// No BTF parsed for object
#[error("no BTF parsed for object")]

Loading…
Cancel
Save