|  |  | @ -3,14 +3,14 @@ mod relocation; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | use object::{ |  |  |  | use object::{ | 
			
		
	
		
		
			
				
					
					|  |  |  |     pod, |  |  |  |     pod, | 
			
		
	
		
		
			
				
					
					|  |  |  |     read::{Object as ElfObject, ObjectSection, Section}, |  |  |  |     read::{Object as ElfObject, ObjectSection, Section as ObjSection}, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     Endianness, ObjectSymbol, ObjectSymbolTable, SectionIndex, SymbolIndex, |  |  |  |     Endianness, ObjectSymbol, ObjectSymbolTable, SectionIndex, SymbolIndex, | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | use std::{ |  |  |  | use std::{ | 
			
		
	
		
		
			
				
					
					|  |  |  |     collections::HashMap, |  |  |  |     collections::HashMap, | 
			
		
	
		
		
			
				
					
					|  |  |  |     convert::{TryFrom, TryInto}, |  |  |  |     convert::{TryFrom, TryInto}, | 
			
		
	
		
		
			
				
					
					|  |  |  |     ffi::{CStr, CString}, |  |  |  |     ffi::{CStr, CString}, | 
			
		
	
		
		
			
				
					
					|  |  |  |     mem, |  |  |  |     mem, ptr, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     str::FromStr, |  |  |  |     str::FromStr, | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | use thiserror::Error; |  |  |  | use thiserror::Error; | 
			
		
	
	
		
		
			
				
					|  |  | @ -93,27 +93,17 @@ impl Object { | 
			
		
	
		
		
			
				
					
					|  |  |  |         let section = obj |  |  |  |         let section = obj | 
			
		
	
		
		
			
				
					
					|  |  |  |             .section_by_name("license") |  |  |  |             .section_by_name("license") | 
			
		
	
		
		
			
				
					
					|  |  |  |             .ok_or(ParseError::MissingLicense)?; |  |  |  |             .ok_or(ParseError::MissingLicense)?; | 
			
		
	
		
		
			
				
					
					|  |  |  |         let license = parse_license(BPFSection::try_from(§ion)?.data)?; |  |  |  |         let license = parse_license(Section::try_from(§ion)?.data)?; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         let section = obj |  |  |  |         let section = obj | 
			
		
	
		
		
			
				
					
					|  |  |  |             .section_by_name("version") |  |  |  |             .section_by_name("version") | 
			
		
	
		
		
			
				
					
					|  |  |  |             .ok_or(ParseError::MissingKernelVersion)?; |  |  |  |             .ok_or(ParseError::MissingKernelVersion)?; | 
			
		
	
		
		
			
				
					
					|  |  |  |         let kernel_version = parse_version(BPFSection::try_from(§ion)?.data, endianness)?; |  |  |  |         let kernel_version = parse_version(Section::try_from(§ion)?.data, endianness)?; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         let mut bpf_obj = Object { |  |  |  |         let mut bpf_obj = Object::new(endianness, license, kernel_version); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             endianness: endianness.into(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             license, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             kernel_version, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             btf: None, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             btf_ext: None, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             maps: HashMap::new(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             programs: HashMap::new(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             relocations: HashMap::new(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             symbol_table: HashMap::new(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         for s in obj.sections() { |  |  |  |         for s in obj.sections() { | 
			
		
	
		
		
			
				
					
					|  |  |  |             parse_section(&mut bpf_obj, BPFSection::try_from(&s)?)?; |  |  |  |             bpf_obj.parse_section(Section::try_from(&s)?)?; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if let Some(symbol_table) = obj.symbol_table() { |  |  |  |         if let Some(symbol_table) = obj.symbol_table() { | 
			
		
	
	
		
		
			
				
					|  |  | @ -131,6 +121,90 @@ impl Object { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         return Ok(bpf_obj); |  |  |  |         return Ok(bpf_obj); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn new(endianness: Endianness, license: CString, kernel_version: KernelVersion) -> Object { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Object { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             endianness: endianness.into(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             license, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             kernel_version, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             btf: None, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             btf_ext: None, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             maps: HashMap::new(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             programs: HashMap::new(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             relocations: HashMap::new(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             symbol_table: HashMap::new(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn parse_program(&self, section: &Section, ty: &str) -> Result<Program, ParseError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let num_instructions = section.data.len() / mem::size_of::<bpf_insn>(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if section.data.len() % mem::size_of::<bpf_insn>() > 0 { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return Err(ParseError::InvalidProgramCode { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 name: section.name.to_owned(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let instructions = (0..num_instructions) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             .map(|i| unsafe { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 ptr::read_unaligned( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     (section.data.as_ptr() as usize + i * mem::size_of::<bpf_insn>()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         as *const bpf_insn, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             .collect::<Vec<_>>(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Ok(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             section_index: section.index, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             license: self.license.clone(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             kernel_version: self.kernel_version, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             instructions, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             kind: ProgramKind::from_str(ty)?, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn parse_btf(&mut self, section: &Section) -> Result<(), BtfError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         self.btf = Some(Btf::parse(section.data)?); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn parse_btf_ext(&mut self, section: &Section) -> Result<(), BtfError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         self.btf_ext = Some(BtfExt::parse(section.data)?); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn parse_section(&mut self, section: Section) -> Result<(), ParseError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let parts = section.name.split("/").collect::<Vec<_>>(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         match parts.as_slice() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             &[name] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") => | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.maps | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     .insert(name.to_string(), parse_map(§ion, name)?); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             &[".BTF"] => self.parse_btf(§ion)?, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             &[".BTF.ext"] => self.parse_btf_ext(§ion)?, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             &["maps", name] => { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.maps | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     .insert(name.to_string(), parse_map(§ion, name)?); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             &[ty @ "kprobe", name] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             | &[ty @ "uprobe", name] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             | &[ty @ "socket_filter", name] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             | &[ty @ "xdp", name] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             | &[ty @ "trace_point", name] => { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.programs | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     .insert(name.to_string(), self.parse_program(§ion, ty)?); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 if !section.relocations.is_empty() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     self.relocations.insert(section.index, section.relocations); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             _ => {} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[derive(Debug, Clone, Error)] |  |  |  | #[derive(Debug, Clone, Error)] | 
			
		
	
	
		
		
			
				
					|  |  | @ -179,23 +253,23 @@ pub enum ParseError { | 
			
		
	
		
		
			
				
					
					|  |  |  |     InvalidMapDefinition { name: String }, |  |  |  |     InvalidMapDefinition { name: String }, | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | struct BPFSection<'s> { |  |  |  | struct Section<'a> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     index: SectionIndex, |  |  |  |     index: SectionIndex, | 
			
		
	
		
		
			
				
					
					|  |  |  |     name: &'s str, |  |  |  |     name: &'a str, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     data: &'s [u8], |  |  |  |     data: &'a [u8], | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     relocations: Vec<Relocation>, |  |  |  |     relocations: Vec<Relocation>, | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | impl<'data, 'file, 's> TryFrom<&'s Section<'data, 'file>> for BPFSection<'s> { |  |  |  | impl<'data, 'file, 'a> TryFrom<&'a ObjSection<'data, 'file>> for Section<'a> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     type Error = ParseError; |  |  |  |     type Error = ParseError; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     fn try_from(section: &'s Section) -> Result<BPFSection<'s>, ParseError> { |  |  |  |     fn try_from(section: &'a ObjSection) -> Result<Section<'a>, ParseError> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         let index = section.index(); |  |  |  |         let index = section.index(); | 
			
		
	
		
		
			
				
					
					|  |  |  |         let map_err = |source| ParseError::SectionError { |  |  |  |         let map_err = |source| ParseError::SectionError { | 
			
		
	
		
		
			
				
					
					|  |  |  |             index: index.0, |  |  |  |             index: index.0, | 
			
		
	
		
		
			
				
					
					|  |  |  |             source, |  |  |  |             source, | 
			
		
	
		
		
			
				
					
					|  |  |  |         }; |  |  |  |         }; | 
			
		
	
		
		
			
				
					
					|  |  |  |         Ok(BPFSection { |  |  |  |         Ok(Section { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             index, |  |  |  |             index, | 
			
		
	
		
		
			
				
					
					|  |  |  |             name: section.name().map_err(map_err)?, |  |  |  |             name: section.name().map_err(map_err)?, | 
			
		
	
		
		
			
				
					
					|  |  |  |             data: section.data().map_err(map_err)?, |  |  |  |             data: section.data().map_err(map_err)?, | 
			
		
	
	
		
		
			
				
					|  |  | @ -269,7 +343,7 @@ impl From<KernelVersion> for u32 { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_map(section: &BPFSection, name: &str) -> Result<Map, ParseError> { |  |  |  | fn parse_map(section: &Section, name: &str) -> Result<Map, ParseError> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     let (def, data) = if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") |  |  |  |     let (def, data) = if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         let def = bpf_map_def { |  |  |  |         let def = bpf_map_def { | 
			
		
	
	
		
		
			
				
					|  |  | @ -293,90 +367,46 @@ fn parse_map(section: &BPFSection, name: &str) -> Result<Map, ParseError> { | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_map_def(name: &str, data: &[u8]) -> Result<bpf_map_def, ParseError> { |  |  |  | fn parse_map_def(name: &str, data: &[u8]) -> Result<bpf_map_def, ParseError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     let (def, rest) = |  |  |  |     if mem::size_of::<bpf_map_def>() > data.len() { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         pod::from_bytes::<bpf_map_def>(data).map_err(|_| ParseError::InvalidMapDefinition { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             name: name.to_string(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         })?; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if !rest.is_empty() { |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return Err(ParseError::InvalidMapDefinition { |  |  |  |         return Err(ParseError::InvalidMapDefinition { | 
			
		
	
		
		
			
				
					
					|  |  |  |             name: name.to_string(), |  |  |  |             name: name.to_owned(), | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         }); |  |  |  |         }); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     Ok(*def) |  |  |  |     Ok(unsafe { ptr::read_unaligned(data.as_ptr() as *const bpf_map_def) }) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_program(bpf: &Object, section: &BPFSection, ty: &str) -> Result<Program, ParseError> { |  |  |  | #[cfg(test)] | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     let (code, rest) = pod::slice_from_bytes::<bpf_insn>( |  |  |  | mod tests { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         section.data, |  |  |  |     use matches::assert_matches; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         section.data.len() / mem::size_of::<bpf_insn>(), |  |  |  |     use object::Endianness; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     ) |  |  |  |     use std::slice; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     .map_err(|_| ParseError::InvalidProgramCode { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         name: section.name.to_string(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     })?; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if !rest.is_empty() { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         return Err(ParseError::InvalidProgramCode { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             name: section.name.to_string(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         }); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     Ok(Program { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         section_index: section.index, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         license: bpf.license.clone(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         kernel_version: bpf.kernel_version, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         instructions: code.to_vec(), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         kind: ProgramKind::from_str(ty)?, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     }) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_btf(obj: &mut Object, section: &BPFSection) -> Result<(), BtfError> { |  |  |  |     use super::*; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     obj.btf = Some(Btf::parse(section.data)?); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     Ok(()) |  |  |  |     fn fake_section<'a>(name: &'a str, data: &'a [u8]) -> Section<'a> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Section { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             index: SectionIndex(0), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             name, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             data, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             relocations: Vec::new(), | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_btf_ext(obj: &mut Object, section: &BPFSection) -> Result<(), BtfError> { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     obj.btf_ext = Some(BtfExt::parse(section.data)?); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     Ok(()) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn parse_section(bpf: &mut Object, section: BPFSection) -> Result<(), ParseError> { |  |  |  |     fn fake_ins() -> bpf_insn { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     let parts = section.name.split("/").collect::<Vec<_>>(); |  |  |  |         bpf_insn { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |             code: 0, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     match parts.as_slice() { |  |  |  |             _bitfield_1: bpf_insn::new_bitfield_1(0, 0), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         &[name] if name == ".bss" || name.starts_with(".data") || name.starts_with(".rodata") => { |  |  |  |             off: 0, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             bpf.maps |  |  |  |             imm: 0, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 .insert(name.to_string(), parse_map(§ion, name)?); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         &[".BTF"] => parse_btf(bpf, §ion)?, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         &[".BTF.ext"] => parse_btf_ext(bpf, §ion)?, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         &["maps", name] => { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             bpf.maps |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 .insert(name.to_string(), parse_map(§ion, name)?); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         &[ty @ "kprobe", name] |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | &[ty @ "uprobe", name] |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | &[ty @ "xdp", name] |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | &[ty @ "trace_point", name] => { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             bpf.programs |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 .insert(name.to_string(), parse_program(bpf, §ion, ty)?); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             if !section.relocations.is_empty() { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 bpf.relocations.insert(section.index, section.relocations); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         _ => {} |  |  |  |     fn bytes_of<T>(val: &T) -> &[u8] { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |         let size = mem::size_of::<T>(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |         unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     Ok(()) |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[cfg(test)] |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | mod tests { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     use super::*; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     use object::Endianness; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     #[test] |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |     fn test_parse_generic_error() { |  |  |  |     fn test_parse_generic_error() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         assert!(matches!( |  |  |  |         assert!(matches!( | 
			
		
	
	
		
		
			
				
					|  |  | @ -435,4 +465,275 @@ mod tests { | 
			
		
	
		
		
			
				
					
					|  |  |  |             KernelVersion::Version(1234) |  |  |  |             KernelVersion::Version(1234) | 
			
		
	
		
		
			
				
					
					|  |  |  |         ); |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_map_def() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             parse_map_def("foo", &[]), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Err(ParseError::InvalidMapDefinition { .. }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             parse_map_def( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "foo", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 bytes_of(&bpf_map_def { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_type: 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     key_size: 2, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     value_size: 3, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     max_entries: 4, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_flags: 5 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(bpf_map_def { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 map_type: 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 key_size: 2, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 value_size: 3, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 max_entries: 4, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 map_flags: 5 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_map_error() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             parse_map(&fake_section("maps/foo", &[]), "foo"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Err(ParseError::InvalidMapDefinition { .. }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_map() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             parse_map( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 &fake_section( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     "maps/foo", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     bytes_of(&bpf_map_def { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         map_type: 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         key_size: 2, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         value_size: 3, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         max_entries: 4, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         map_flags: 5 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "foo" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(Map { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 section_index: 0, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 name, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 def: bpf_map_def { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_type: 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     key_size: 2, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     value_size: 3, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     max_entries: 4, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_flags: 5, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 data | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) if name == "foo" && data.is_empty() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_map_data() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let map_data = b"map data"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             parse_map( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 &fake_section( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     ".bss", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_data, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 ".bss" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(Map { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 section_index: 0, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 name, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 def: bpf_map_def { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_type: BPF_MAP_TYPE_ARRAY, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     key_size: 4, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     value_size, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     max_entries: 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_flags: 0, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 }, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 data | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) if name == ".bss" && data == map_data && value_size == map_data.len() as u32 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         )) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn fake_obj() -> Object { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Object::new( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Endianness::Little, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             CString::new("GPL").unwrap(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             KernelVersion::Any, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_program_error() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_program( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 &fake_section( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     "kprobe/foo", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     &42u32.to_ne_bytes(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "kprobe" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Err(ParseError::InvalidProgramCode { name }) if name == "kprobe/foo" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_program() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_program(&fake_section("kprobe/foo", bytes_of(&fake_ins())), "kprobe"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 license, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kernel_version, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kind: ProgramKind::KProbe, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 section_index: SectionIndex(0), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 instructions | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) if license.to_string_lossy() == "GPL" && kernel_version == KernelVersion::Any && instructions.len() == 1 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_map() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 "maps/foo", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 bytes_of(&bpf_map_def { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_type: 1, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     key_size: 2, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     value_size: 3, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     max_entries: 4, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     map_flags: 5 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ),), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(obj.maps.get("foo").is_some()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_data() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section(".bss", b"map data"),), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(obj.maps.get(".bss").is_some()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section(".rodata", b"map data"),), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(obj.maps.get(".rodata").is_some()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section(".rodata.boo", b"map data"),), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(obj.maps.get(".rodata.boo").is_some()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section(".data", b"map data"),), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(obj.maps.get(".data").is_some()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section(".data.boo", b"map data"),), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert!(obj.maps.get(".data.boo").is_some()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_kprobe() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section("kprobe/foo", bytes_of(&fake_ins()))), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.programs.get("foo"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Some(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kind: ProgramKind::KProbe, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_uprobe() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section("uprobe/foo", bytes_of(&fake_ins()))), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.programs.get("foo"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Some(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kind: ProgramKind::UProbe, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_trace_point() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section("trace_point/foo", bytes_of(&fake_ins()))), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.programs.get("foo"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Some(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kind: ProgramKind::TracePoint, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_socket_filter() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section("socket_filter/foo", bytes_of(&fake_ins()))), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.programs.get("foo"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Some(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kind: ProgramKind::SocketFilter, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #[test] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     fn test_parse_section_xdp() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         let mut obj = fake_obj(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.parse_section(fake_section("xdp/foo", bytes_of(&fake_ins()))), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         assert_matches!( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             obj.programs.get("foo"), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Some(Program { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 kind: ProgramKind::Xdp, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |