diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index a36eb684..3a9eb038 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -123,6 +123,7 @@ pub struct Object { pub functions: BTreeMap<(usize, u64), Function>, pub(crate) relocations: HashMap>, pub(crate) symbol_table: HashMap, + pub(crate) symbols_by_section: HashMap>, pub(crate) section_infos: HashMap, // symbol_offset_by_name caches symbols that could be referenced from a // BTF VAR type so the offsets can be fixed up @@ -600,7 +601,13 @@ impl Object { kind: symbol.kind(), }; bpf_obj.symbol_table.insert(symbol.index().0, sym); - + if let Some(section_idx) = symbol.section().index() { + bpf_obj + .symbols_by_section + .entry(section_idx) + .or_default() + .push(symbol.index().0); + } if symbol.is_global() || symbol.kind() == SymbolKind::Data { bpf_obj.symbol_offset_by_name.insert(name, symbol.address()); } @@ -642,6 +649,7 @@ impl Object { functions: BTreeMap::new(), relocations: HashMap::new(), symbol_table: HashMap::new(), + symbols_by_section: HashMap::new(), section_infos: HashMap::new(), symbol_offset_by_name: HashMap::new(), } @@ -711,10 +719,42 @@ impl Object { Ok(()) } - fn parse_program(&self, section: &Section) -> Result<(Program, Function), ParseError> { - let prog_sec = ProgramSection::from_str(section.name)?; - let name = prog_sec.name().to_owned(); + fn parse_programs(&mut self, section: &Section) -> Result<(), ParseError> { + let program_section = ProgramSection::from_str(section.name)?; + let syms = + self.symbols_by_section + .get(§ion.index) + .ok_or(ParseError::NoSymbolsForSection { + section_name: section.name.to_string(), + })?; + for symbol_index in syms { + let symbol = self + .symbol_table + .get(symbol_index) + .expect("all symbols in symbols_by_section are also in symbol_table"); + + let Some(name) = symbol.name.as_ref() else { + continue; + }; + if name.is_empty() { + continue; + } + let (p, f) = + self.parse_program(section, program_section.clone(), name.to_string(), symbol)?; + let key = p.function_key(); + self.programs.insert(f.name.clone(), p); + self.functions.insert(key, f); + } + Ok(()) + } + fn parse_program( + &self, + section: &Section, + program_section: ProgramSection, + name: String, + symbol: &Symbol, + ) -> Result<(Program, Function), ParseError> { let (func_info, line_info, func_info_rec_size, line_info_rec_size) = if let Some(btf_ext) = &self.btf_ext { let func_info = btf_ext.func_info.get(section.name); @@ -729,12 +769,15 @@ impl Object { (FuncSecInfo::default(), LineSecInfo::default(), 0, 0) }; + let start = symbol.address as usize; + let end = (symbol.address + symbol.size) as usize; + let function = Function { - name, - address: section.address, + name: name.to_owned(), + address: symbol.address, section_index: section.index, - section_offset: 0, - instructions: copy_instructions(section.data)?, + section_offset: start, + instructions: copy_instructions(§ion.data[start..end])?, func_info, line_info, func_info_rec_size, @@ -745,9 +788,9 @@ impl Object { Program { license: self.license.clone(), kernel_version: self.kernel_version, - section: prog_sec, - section_index: function.section_index.0, - address: function.address, + section: program_section.clone(), + section_index: section.index.0, + address: symbol.address, }, function, )) @@ -845,15 +888,23 @@ impl Object { Ok(()) } - fn parse_btf_maps( - &mut self, - section: &Section, - symbols: HashMap, - ) -> Result<(), ParseError> { + fn parse_btf_maps(&mut self, section: &Section) -> Result<(), ParseError> { if self.btf.is_none() { return Err(ParseError::NoBTF); } let btf = self.btf.as_ref().unwrap(); + let maps: HashMap<&String, usize> = self + .symbols_by_section + .get(§ion.index) + .ok_or(ParseError::NoSymbolsForSection { + section_name: section.name.to_owned(), + })? + .iter() + .filter_map(|s| { + let symbol = self.symbol_table.get(s).unwrap(); + symbol.name.as_ref().map(|name| (name, symbol.index)) + }) + .collect(); for t in btf.types() { if let BtfType::DataSec(datasec) = &t { @@ -865,18 +916,17 @@ impl Object { // each btf_var_secinfo contains a map for info in &datasec.entries { let (map_name, def) = parse_btf_map_def(btf, info)?; - let symbol_index = symbols - .get(&map_name) - .ok_or_else(|| ParseError::SymbolNotFound { - name: map_name.to_string(), - })? - .index; + let symbol_index = + maps.get(&map_name) + .ok_or_else(|| ParseError::SymbolNotFound { + name: map_name.to_string(), + })?; self.maps.insert( map_name, Map::Btf(BtfMap { def, section_index: section.index.0, - symbol_index, + symbol_index: *symbol_index, data: Vec::new(), }), ); @@ -887,6 +937,50 @@ impl Object { Ok(()) } + // 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>( + &self, + maps: &mut HashMap, + section: &Section, + symbols: I, + ) -> Result<(), ParseError> { + let mut have_symbols = false; + // each symbol in the section is a separate map + for i in symbols { + let sym = self.symbol_table.get(i).ok_or(ParseError::SymbolNotFound { + name: i.to_string(), + })?; + let start = sym.address as usize; + let end = start + sym.size as usize; + let data = §ion.data[start..end]; + let name = sym + .name + .as_ref() + .ok_or(ParseError::MapSymbolNameNotFound { i: *i })?; + let def = parse_map_def(name, data)?; + maps.insert( + name.to_string(), + Map::Legacy(LegacyMap { + section_index: section.index.0, + section_kind: section.kind, + symbol_index: Some(sym.index), + def, + data: Vec::new(), + }), + ); + have_symbols = true; + } + if !have_symbols { + return Err(ParseError::NoSymbolsForSection { + section_name: section.name.to_owned(), + }); + } + + Ok(()) + } + fn parse_section(&mut self, section: Section) -> Result<(), ParseError> { self.section_infos .insert(section.name.to_owned(), (section.index, section.size)); @@ -898,22 +992,7 @@ impl Object { BpfSectionKind::Text => self.parse_text_section(section)?, BpfSectionKind::Btf => self.parse_btf(§ion)?, BpfSectionKind::BtfExt => self.parse_btf_ext(§ion)?, - BpfSectionKind::BtfMaps => { - let symbols: HashMap = self - .symbol_table - .values() - .filter(|s| { - if let Some(idx) = s.section_index { - idx == section.index.0 && s.name.is_some() - } else { - false - } - }) - .cloned() - .map(|s| (s.name.as_ref().unwrap().to_string(), s)) - .collect(); - self.parse_btf_maps(§ion, symbols)? - } + BpfSectionKind::BtfMaps => self.parse_btf_maps(§ion)?, BpfSectionKind::Maps => { // take out self.maps so we can borrow the iterator below // without cloning or collecting @@ -921,13 +1000,15 @@ impl Object { // extract the symbols for the .maps section, we'll need them // during parsing - let symbols = self.symbol_table.values().filter(|s| { - s.section_index - .map(|idx| idx == section.index.0) - .unwrap_or(false) - }); + let symbols = self + .symbols_by_section + .get(§ion.index) + .ok_or(ParseError::NoSymbolsForSection { + section_name: section.name.to_owned(), + })? + .iter(); - let res = parse_maps_section(&mut maps, §ion, symbols); + let res = self.parse_maps_section(&mut maps, §ion, symbols); // put the maps back self.maps = maps; @@ -935,10 +1016,7 @@ impl Object { res? } BpfSectionKind::Program => { - let (program, function) = self.parse_program(§ion)?; - self.functions.insert(program.function_key(), function); - self.programs - .insert(program.section.name().to_owned(), program); + self.parse_programs(§ion)?; if !section.relocations.is_empty() { self.relocations.insert( section.index, @@ -1003,45 +1081,6 @@ impl Function { } } -// 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>( - maps: &mut HashMap, - 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 = §ion.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, - section_kind: section.kind, - symbol_index: Some(sym.index), - def, - data: Vec::new(), - }), - ); - have_symbols = true; - } - if !have_symbols { - return Err(ParseError::NoSymbolsForMapsSection); - } - - Ok(()) -} - /// Errors caught during parsing the object file #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] @@ -1105,8 +1144,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 for `maps` section, can't parse maps")] - NoSymbolsForMapsSection, + #[error("no symbols found in the {section_name} section")] + NoSymbolsForSection { section_name: String }, /// No BTF parsed for object #[error("no BTF parsed for object")] @@ -1480,9 +1519,17 @@ mod tests { use super::*; use crate::maps::PinningType; - fn fake_section<'a>(kind: BpfSectionKind, name: &'a str, data: &'a [u8]) -> Section<'a> { + const FAKE_INS_LEN: u64 = 8; + + fn fake_section<'a>( + kind: BpfSectionKind, + name: &'a str, + data: &'a [u8], + index: Option, + ) -> Section<'a> { + let idx = index.unwrap_or(0); Section { - index: SectionIndex(0), + index: SectionIndex(idx), kind, address: 0, name, @@ -1513,9 +1560,13 @@ mod tests { address, size, is_definition: false, - kind: SymbolKind::Data, + kind: SymbolKind::Text, }, ); + obj.symbols_by_section + .entry(SectionIndex(section_index)) + .or_default() + .push(idx + 1); } fn bytes_of(val: &T) -> &[u8] { @@ -1637,6 +1688,7 @@ mod tests { BpfSectionKind::Data, ".bss", map_data, + None, ), ), Ok(Map::Legacy(LegacyMap { @@ -1670,6 +1722,7 @@ mod tests { &[ 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, ], + None, )) .unwrap(); obj.parse_section(fake_section( @@ -1679,6 +1732,7 @@ mod tests { 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, ], + None, )) .unwrap(); @@ -1688,36 +1742,54 @@ mod tests { #[test] fn test_parse_program_error() { - let obj = fake_obj(); - + let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", 1); assert_matches!( - obj.parse_program(&fake_section( + obj.parse_programs(&fake_section( BpfSectionKind::Program, "kprobe/foo", &42u32.to_ne_bytes(), - )), + None, + ),), Err(ParseError::InvalidProgramCode) ); } #[test] fn test_parse_program() { - let obj = fake_obj(); + let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); + + obj.parse_programs(&fake_section( + BpfSectionKind::Program, + "kprobe/foo", + bytes_of(&fake_ins()), + None, + )) + .unwrap(); + + let prog_foo = obj.programs.get("foo").unwrap(); assert_matches!( - obj.parse_program(&fake_section(BpfSectionKind::Program,"kprobe/foo", bytes_of(&fake_ins()))), - Ok((Program { + prog_foo, + Program { license, kernel_version: None, section: ProgramSection::KProbe { .. }, - .. }, Function { - name, - address: 0, - section_index: SectionIndex(0), - section_offset: 0, - instructions, - ..})) if license.to_string_lossy() == "GPL" && name == "foo" && instructions.len() == 1 + .. + } if license.to_str().unwrap() == "GPL" ); + + assert_matches!( + obj.functions.get(&prog_foo.function_key()), + Some(Function { + name, + address: 0, + section_index: SectionIndex(0), + section_offset: 0, + instructions, + ..}) if name == "foo" && instructions.len() == 1 + ) } #[test] @@ -1735,13 +1807,72 @@ mod tests { max_entries: 4, map_flags: 5, ..Default::default() - }) + }), + None, )), Ok(()) ); assert!(obj.maps.get("foo").is_some()); } + #[test] + fn test_parse_multiple_program_in_same_section() { + let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); + fake_sym(&mut obj, 0, FAKE_INS_LEN, "bar", FAKE_INS_LEN); + + let insns = [fake_ins(), fake_ins()]; + let data = bytes_of(&insns); + + obj.parse_programs(&fake_section(BpfSectionKind::Program, "kprobe", data, None)) + .unwrap(); + + let prog_foo = obj.programs.get("foo").unwrap(); + let function_foo = obj.functions.get(&prog_foo.function_key()).unwrap(); + let prog_bar = obj.programs.get("bar").unwrap(); + let function_bar = obj.functions.get(&prog_bar.function_key()).unwrap(); + + assert_matches!(prog_foo, + Program { + license, + kernel_version: None, + section: ProgramSection::KProbe { .. }, + .. + } if license.to_string_lossy() == "GPL" + ); + assert_matches!( + function_foo, + Function { + name, + address: 0, + section_index: SectionIndex(0), + section_offset: 0, + instructions, + .. + } if name == "foo" && instructions.len() == 1 + ); + + assert_matches!(prog_bar, + Program { + license, + kernel_version: None, + section: ProgramSection::KProbe { .. }, + .. + } if license.to_string_lossy() == "GPL" + ); + assert_matches!( + function_bar, + Function { + name, + address: 8, + section_index: SectionIndex(0), + section_offset: 8, + instructions, + .. + } if name == "bar" && instructions.len() == 1 + ); + } + #[test] fn test_parse_section_multiple_maps() { let mut obj = fake_obj(); @@ -1764,7 +1895,12 @@ mod tests { buf.extend([0, 0, 0, 0]); buf.extend(&map_data); assert_matches!( - obj.parse_section(fake_section(BpfSectionKind::Maps, "maps", buf.as_slice(),)), + obj.parse_section(fake_section( + BpfSectionKind::Maps, + "maps", + buf.as_slice(), + None + )), Ok(()) ); assert!(obj.maps.get("foo").is_some()); @@ -1783,13 +1919,23 @@ mod tests { fn test_parse_section_data() { let mut obj = fake_obj(); assert_matches!( - obj.parse_section(fake_section(BpfSectionKind::Data, ".bss", b"map data")), + obj.parse_section(fake_section( + BpfSectionKind::Data, + ".bss", + b"map data", + None + )), Ok(()) ); assert!(obj.maps.get(".bss").is_some()); assert_matches!( - obj.parse_section(fake_section(BpfSectionKind::Data, ".rodata", b"map data")), + obj.parse_section(fake_section( + BpfSectionKind::Data, + ".rodata", + b"map data", + None + )), Ok(()) ); assert!(obj.maps.get(".rodata").is_some()); @@ -1798,20 +1944,31 @@ mod tests { obj.parse_section(fake_section( BpfSectionKind::Data, ".rodata.boo", - b"map data" + b"map data", + None )), Ok(()) ); assert!(obj.maps.get(".rodata.boo").is_some()); assert_matches!( - obj.parse_section(fake_section(BpfSectionKind::Data, ".data", b"map data")), + obj.parse_section(fake_section( + BpfSectionKind::Data, + ".data", + b"map data", + None + )), Ok(()) ); assert!(obj.maps.get(".data").is_some()); assert_matches!( - obj.parse_section(fake_section(BpfSectionKind::Data, ".data.boo", b"map data")), + obj.parse_section(fake_section( + BpfSectionKind::Data, + ".data.boo", + b"map data", + None + )), Ok(()) ); assert!(obj.maps.get(".data.boo").is_some()); @@ -1820,12 +1977,14 @@ mod tests { #[test] fn test_parse_section_kprobe() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "kprobe/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1841,12 +2000,14 @@ mod tests { #[test] fn test_parse_section_uprobe() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "uprobe/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1862,12 +2023,15 @@ mod tests { #[test] fn test_parse_section_trace_point() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); + fake_sym(&mut obj, 1, 0, "bar", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "tracepoint/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1883,12 +2047,13 @@ mod tests { obj.parse_section(fake_section( BpfSectionKind::Program, "tp/foo/bar", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + Some(1), )), Ok(()) ); assert_matches!( - obj.programs.get("foo/bar"), + obj.programs.get("bar"), Some(Program { section: ProgramSection::TracePoint { .. }, .. @@ -1899,12 +2064,14 @@ mod tests { #[test] fn test_parse_section_socket_filter() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "socket/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1920,12 +2087,14 @@ mod tests { #[test] fn test_parse_section_xdp() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "xdp/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1941,12 +2110,14 @@ mod tests { #[test] fn test_parse_section_xdp_frags() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "xdp.frags/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1962,12 +2133,15 @@ mod tests { #[test] fn test_parse_section_raw_tp() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); + fake_sym(&mut obj, 1, 0, "bar", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "raw_tp/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -1983,7 +2157,8 @@ mod tests { obj.parse_section(fake_section( BpfSectionKind::Program, "raw_tracepoint/bar", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + Some(1) )), Ok(()) ); @@ -1999,12 +2174,14 @@ mod tests { #[test] fn test_parse_section_lsm() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "lsm/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2023,12 +2200,14 @@ mod tests { #[test] fn test_parse_section_lsm_sleepable() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "lsm.s/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2047,12 +2226,14 @@ mod tests { #[test] fn test_parse_section_btf_tracepoint() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "tp_btf/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2068,12 +2249,14 @@ mod tests { #[test] fn test_parse_section_skskb_unnamed() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "stream_parser", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "sk_skb/stream_parser", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2089,12 +2272,14 @@ mod tests { #[test] fn test_parse_section_skskb_named() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "my_parser", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "sk_skb/stream_parser/my_parser", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2110,12 +2295,14 @@ mod tests { #[test] fn test_parse_section_fentry() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "fentry/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2131,12 +2318,14 @@ mod tests { #[test] fn test_parse_section_fexit() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "fexit/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2152,12 +2341,14 @@ mod tests { #[test] fn test_parse_section_cgroup_skb_ingress_unnamed() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "ingress", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup_skb/ingress", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2173,12 +2364,14 @@ mod tests { #[test] fn test_parse_section_cgroup_skb_ingress_named() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup_skb/ingress/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2194,12 +2387,14 @@ mod tests { #[test] fn test_parse_section_cgroup_skb_no_direction_unamed() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "skb", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup/skb", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2215,12 +2410,14 @@ mod tests { #[test] fn test_parse_section_cgroup_skb_no_direction_named() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup/skb/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2236,12 +2433,14 @@ mod tests { #[test] fn test_parse_section_sock_addr_named() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup/connect4/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2260,12 +2459,14 @@ mod tests { #[test] fn test_parse_section_sock_addr_unnamed() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "connect4", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup/connect4", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2284,12 +2485,14 @@ mod tests { #[test] fn test_parse_section_sockopt_named() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup/getsockopt/foo", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2308,12 +2511,14 @@ mod tests { #[test] fn test_parse_section_sockopt_unnamed() { let mut obj = fake_obj(); + fake_sym(&mut obj, 0, 0, "getsockopt", FAKE_INS_LEN); assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, "cgroup/getsockopt", - bytes_of(&fake_ins()) + bytes_of(&fake_ins()), + None )), Ok(()) ); @@ -2455,10 +2660,10 @@ mod tests { 0x2E, 0x6D, 0x61, 0x70, 0x73, 0x00, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00, ]; - let btf_section = fake_section(BpfSectionKind::Btf, ".BTF", data); + let btf_section = fake_section(BpfSectionKind::Btf, ".BTF", data, None); obj.parse_section(btf_section).unwrap(); - let map_section = fake_section(BpfSectionKind::BtfMaps, ".maps", &[]); + let map_section = fake_section(BpfSectionKind::BtfMaps, ".maps", &[], None); obj.parse_section(map_section).unwrap(); let map = obj.maps.get("map_1").unwrap(); diff --git a/test/integration-ebpf/src/name_test.rs b/test/integration-ebpf/src/name_test.rs index 1a5f870c..a9208e95 100644 --- a/test/integration-ebpf/src/name_test.rs +++ b/test/integration-ebpf/src/name_test.rs @@ -3,7 +3,7 @@ use aya_bpf::{bindings::xdp_action, macros::xdp, programs::XdpContext}; -#[xdp(name = "ihaveaverylongname")] +#[xdp] pub fn ihaveaverylongname(ctx: XdpContext) -> u32 { match unsafe { try_pass(ctx) } { Ok(ret) => ret, diff --git a/test/integration-test/bpf/ext.bpf.c b/test/integration-test/bpf/ext.bpf.c index 6c77127a..dc82f5cf 100644 --- a/test/integration-test/bpf/ext.bpf.c +++ b/test/integration-test/bpf/ext.bpf.c @@ -1,7 +1,7 @@ #include #include -SEC("xdp/drop") +SEC("xdp") int xdp_drop(struct xdp_md *ctx) { return XDP_DROP; diff --git a/test/integration-test/bpf/main.bpf.c b/test/integration-test/bpf/main.bpf.c index 79c82041..2a30577f 100644 --- a/test/integration-test/bpf/main.bpf.c +++ b/test/integration-test/bpf/main.bpf.c @@ -1,7 +1,7 @@ #include #include -SEC("xdp/pass") +SEC("xdp") int xdp_pass(struct xdp_md *ctx) { return XDP_PASS; diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 8958ae59..4c366e46 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -36,7 +36,7 @@ fn multiple_btf_maps() { let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); - let prog: &mut TracePoint = bpf.program_mut("tracepoint").unwrap().try_into().unwrap(); + let prog: &mut TracePoint = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); prog.load().unwrap(); prog.attach("sched", "sched_switch").unwrap(); @@ -110,26 +110,26 @@ macro_rules! assert_loaded { #[test] fn unload_xdp() { let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); prog.load().unwrap(); - assert_loaded!("test_xdp", true); + assert_loaded!("pass", true); let link = prog.attach("lo", XdpFlags::default()).unwrap(); { let _link_owned = prog.take_link(link).unwrap(); prog.unload().unwrap(); - assert_loaded_and_linked!("test_xdp", true); + assert_loaded_and_linked!("pass", true); }; - assert_loaded!("test_xdp", false); + assert_loaded!("pass", false); prog.load().unwrap(); - assert_loaded!("test_xdp", true); + assert_loaded!("pass", true); prog.attach("lo", XdpFlags::default()).unwrap(); - assert_loaded!("test_xdp", true); + assert_loaded!("pass", true); prog.unload().unwrap(); - assert_loaded!("test_xdp", false); + assert_loaded!("pass", false); } #[test] @@ -224,26 +224,26 @@ fn pin_link() { } let mut bpf = Bpf::load(crate::TEST).unwrap(); - let prog: &mut Xdp = bpf.program_mut("test_xdp").unwrap().try_into().unwrap(); + let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); prog.load().unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); - assert_loaded!("test_xdp", true); + assert_loaded!("pass", true); let fd_link: FdLink = link.try_into().unwrap(); let pinned = fd_link.pin("/sys/fs/bpf/aya-xdp-test-lo").unwrap(); // because of the pin, the program is still attached prog.unload().unwrap(); - assert_loaded!("test_xdp", true); + assert_loaded!("pass", true); // delete the pin, but the program is still attached let new_link = pinned.unpin().unwrap(); - assert_loaded!("test_xdp", true); + assert_loaded!("pass", true); // finally when new_link is dropped we're detached drop(new_link); - assert_loaded!("test_xdp", false); + assert_loaded!("pass", false); } #[test] diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index 790b2fdc..c12bbce8 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -36,10 +36,10 @@ fn use_map_with_rbpf() { assert_eq!(object.programs.len(), 1); assert_matches::assert_matches!( - object.programs["tracepoint"].section, + object.programs["bpf_prog"].section, ProgramSection::TracePoint { .. } ); - assert_eq!(object.programs["tracepoint"].section.name(), "tracepoint"); + assert_eq!(object.programs["bpf_prog"].section.name(), "tracepoint"); // Initialize maps: // - fd: 0xCAFE00 or 0xCAFE01 (the 0xCAFE00 part is used to distinguish fds from indices), @@ -83,7 +83,7 @@ fn use_map_with_rbpf() { assert_eq!(object.programs.len(), 1); let instructions = &object .functions - .get(&object.programs["tracepoint"].function_key()) + .get(&object.programs["bpf_prog"].function_key()) .unwrap() .instructions; let data = unsafe { diff --git a/test/integration-test/src/tests/smoke.rs b/test/integration-test/src/tests/smoke.rs index 30a97a39..89f7d0a1 100644 --- a/test/integration-test/src/tests/smoke.rs +++ b/test/integration-test/src/tests/smoke.rs @@ -32,11 +32,14 @@ fn extension() { return; } let mut bpf = Bpf::load(crate::MAIN).unwrap(); - let pass: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let pass: &mut Xdp = bpf.program_mut("xdp_pass").unwrap().try_into().unwrap(); pass.load().unwrap(); pass.attach("lo", XdpFlags::default()).unwrap(); - let mut bpf = BpfLoader::new().extension("drop").load(crate::EXT).unwrap(); - let drop_: &mut Extension = bpf.program_mut("drop").unwrap().try_into().unwrap(); + let mut bpf = BpfLoader::new() + .extension("xdp_drop") + .load(crate::EXT) + .unwrap(); + let drop_: &mut Extension = bpf.program_mut("xdp_drop").unwrap().try_into().unwrap(); drop_.load(pass.fd().unwrap(), "xdp_pass").unwrap(); } diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index 53fb9207..8144037f 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -5764,7 +5764,8 @@ pub aya_obj::obj::ParseError::MapSymbolNameNotFound::i: usize pub aya_obj::obj::ParseError::MissingLicenseNullTerminator pub aya_obj::obj::ParseError::MissingLicenseNullTerminator::data: alloc::vec::Vec pub aya_obj::obj::ParseError::NoBTF -pub aya_obj::obj::ParseError::NoSymbolsForMapsSection +pub aya_obj::obj::ParseError::NoSymbolsForSection +pub aya_obj::obj::ParseError::NoSymbolsForSection::section_name: alloc::string::String pub aya_obj::obj::ParseError::SectionError pub aya_obj::obj::ParseError::SectionError::error: object::read::Error pub aya_obj::obj::ParseError::SectionError::index: usize @@ -6511,7 +6512,8 @@ pub aya_obj::ParseError::MapSymbolNameNotFound::i: usize pub aya_obj::ParseError::MissingLicenseNullTerminator pub aya_obj::ParseError::MissingLicenseNullTerminator::data: alloc::vec::Vec pub aya_obj::ParseError::NoBTF -pub aya_obj::ParseError::NoSymbolsForMapsSection +pub aya_obj::ParseError::NoSymbolsForSection +pub aya_obj::ParseError::NoSymbolsForSection::section_name: alloc::string::String pub aya_obj::ParseError::SectionError pub aya_obj::ParseError::SectionError::error: object::read::Error pub aya_obj::ParseError::SectionError::index: usize