@ -123,6 +123,7 @@ pub struct Object {
pub functions : BTreeMap < ( usize , u64 ) , Function > ,
pub functions : BTreeMap < ( usize , u64 ) , Function > ,
pub ( crate ) relocations : HashMap < SectionIndex , HashMap < u64 , Relocation > > ,
pub ( crate ) relocations : HashMap < SectionIndex , HashMap < u64 , Relocation > > ,
pub ( crate ) symbol_table : HashMap < usize , Symbol > ,
pub ( crate ) symbol_table : HashMap < usize , Symbol > ,
pub ( crate ) symbols_by_section : HashMap < SectionIndex , Vec < usize > > ,
pub ( crate ) section_infos : HashMap < String , ( SectionIndex , u64 ) > ,
pub ( crate ) section_infos : HashMap < String , ( SectionIndex , u64 ) > ,
// symbol_offset_by_name caches symbols that could be referenced from a
// symbol_offset_by_name caches symbols that could be referenced from a
// BTF VAR type so the offsets can be fixed up
// BTF VAR type so the offsets can be fixed up
@ -600,7 +601,13 @@ impl Object {
kind : symbol . kind ( ) ,
kind : symbol . kind ( ) ,
} ;
} ;
bpf_obj . symbol_table . insert ( symbol . index ( ) . 0 , sym ) ;
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 {
if symbol . is_global ( ) | | symbol . kind ( ) = = SymbolKind ::Data {
bpf_obj . symbol_offset_by_name . insert ( name , symbol . address ( ) ) ;
bpf_obj . symbol_offset_by_name . insert ( name , symbol . address ( ) ) ;
}
}
@ -642,6 +649,7 @@ impl Object {
functions : BTreeMap ::new ( ) ,
functions : BTreeMap ::new ( ) ,
relocations : HashMap ::new ( ) ,
relocations : HashMap ::new ( ) ,
symbol_table : HashMap ::new ( ) ,
symbol_table : HashMap ::new ( ) ,
symbols_by_section : HashMap ::new ( ) ,
section_infos : HashMap ::new ( ) ,
section_infos : HashMap ::new ( ) ,
symbol_offset_by_name : HashMap ::new ( ) ,
symbol_offset_by_name : HashMap ::new ( ) ,
}
}
@ -711,10 +719,42 @@ impl Object {
Ok ( ( ) )
Ok ( ( ) )
}
}
fn parse_program ( & self , section : & Section ) -> Result < ( Program , Function ) , ParseError > {
fn parse_programs ( & mut self , section : & Section ) -> Result < ( ) , ParseError > {
let prog_sec = ProgramSection ::from_str ( section . name ) ? ;
let program_section = ProgramSection ::from_str ( section . name ) ? ;
let name = prog_sec . name ( ) . to_owned ( ) ;
let syms =
self . symbols_by_section
. get ( & section . 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 ) =
let ( func_info , line_info , func_info_rec_size , line_info_rec_size ) =
if let Some ( btf_ext ) = & self . btf_ext {
if let Some ( btf_ext ) = & self . btf_ext {
let func_info = btf_ext . func_info . get ( section . name ) ;
let func_info = btf_ext . func_info . get ( section . name ) ;
@ -729,12 +769,15 @@ impl Object {
( FuncSecInfo ::default ( ) , LineSecInfo ::default ( ) , 0 , 0 )
( FuncSecInfo ::default ( ) , LineSecInfo ::default ( ) , 0 , 0 )
} ;
} ;
let start = symbol . address as usize ;
let end = ( symbol . address + symbol . size ) as usize ;
let function = Function {
let function = Function {
name ,
name : name . to_owned ( ) ,
address : section . address ,
address : s ymbol . address ,
section_index : section . index ,
section_index : section . index ,
section_offset : 0 ,
section_offset : start ,
instructions : copy_instructions ( section . data ) ? ,
instructions : copy_instructions ( & section . data [ start .. end ] ) ? ,
func_info ,
func_info ,
line_info ,
line_info ,
func_info_rec_size ,
func_info_rec_size ,
@ -745,9 +788,9 @@ impl Object {
Program {
Program {
license : self . license . clone ( ) ,
license : self . license . clone ( ) ,
kernel_version : self . kernel_version ,
kernel_version : self . kernel_version ,
section : prog _sec,
section : prog ram _section. clone ( ) ,
section_index : function. section_ index. 0 ,
section_index : section. index. 0 ,
address : function . address ,
address : symbol . address ,
} ,
} ,
function ,
function ,
) )
) )
@ -845,15 +888,23 @@ impl Object {
Ok ( ( ) )
Ok ( ( ) )
}
}
fn parse_btf_maps (
fn parse_btf_maps ( & mut self , section : & Section ) -> Result < ( ) , ParseError > {
& mut self ,
section : & Section ,
symbols : HashMap < String , Symbol > ,
) -> Result < ( ) , ParseError > {
if self . btf . is_none ( ) {
if self . btf . is_none ( ) {
return Err ( ParseError ::NoBTF ) ;
return Err ( ParseError ::NoBTF ) ;
}
}
let btf = self . btf . as_ref ( ) . unwrap ( ) ;
let btf = self . btf . as_ref ( ) . unwrap ( ) ;
let maps : HashMap < & String , usize > = self
. symbols_by_section
. get ( & section . 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 ( ) {
for t in btf . types ( ) {
if let BtfType ::DataSec ( datasec ) = & t {
if let BtfType ::DataSec ( datasec ) = & t {
@ -865,18 +916,17 @@ impl Object {
// each btf_var_secinfo contains a map
// each btf_var_secinfo contains a map
for info in & datasec . entries {
for info in & datasec . entries {
let ( map_name , def ) = parse_btf_map_def ( btf , info ) ? ;
let ( map_name , def ) = parse_btf_map_def ( btf , info ) ? ;
let symbol_index = symbols
let symbol_index =
. get ( & map_name )
maps . get ( & map_name )
. ok_or_else ( | | ParseError ::SymbolNotFound {
. ok_or_else ( | | ParseError ::SymbolNotFound {
name : map_name . to_string ( ) ,
name : map_name . to_string ( ) ,
} ) ?
} ) ? ;
. index ;
self . maps . insert (
self . maps . insert (
map_name ,
map_name ,
Map ::Btf ( BtfMap {
Map ::Btf ( BtfMap {
def ,
def ,
section_index : section . index . 0 ,
section_index : section . index . 0 ,
symbol_index ,
symbol_index : * symbol_index ,
data : Vec ::new ( ) ,
data : Vec ::new ( ) ,
} ) ,
} ) ,
) ;
) ;
@ -887,6 +937,50 @@ impl Object {
Ok ( ( ) )
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 < Item = & ' a usize > > (
& self ,
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 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 = & section . 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 > {
fn parse_section ( & mut self , section : Section ) -> Result < ( ) , ParseError > {
self . section_infos
self . section_infos
. insert ( section . name . to_owned ( ) , ( section . index , section . size ) ) ;
. insert ( section . name . to_owned ( ) , ( section . index , section . size ) ) ;
@ -898,22 +992,7 @@ impl Object {
BpfSectionKind ::Text = > self . parse_text_section ( section ) ? ,
BpfSectionKind ::Text = > self . parse_text_section ( section ) ? ,
BpfSectionKind ::Btf = > self . parse_btf ( & section ) ? ,
BpfSectionKind ::Btf = > self . parse_btf ( & section ) ? ,
BpfSectionKind ::BtfExt = > self . parse_btf_ext ( & section ) ? ,
BpfSectionKind ::BtfExt = > self . parse_btf_ext ( & section ) ? ,
BpfSectionKind ::BtfMaps = > {
BpfSectionKind ::BtfMaps = > self . parse_btf_maps ( & section ) ? ,
let symbols : HashMap < String , Symbol > = 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 ( & section , symbols ) ?
}
BpfSectionKind ::Maps = > {
BpfSectionKind ::Maps = > {
// take out self.maps so we can borrow the iterator below
// take out self.maps so we can borrow the iterator below
// without cloning or collecting
// without cloning or collecting
@ -921,13 +1000,15 @@ impl Object {
// extract the symbols for the .maps section, we'll need them
// extract the symbols for the .maps section, we'll need them
// during parsing
// during parsing
let symbols = self . symbol_table . values ( ) . filter ( | s | {
let symbols = self
s . section_index
. symbols_by_section
. map ( | idx | idx = = section . index . 0 )
. get ( & section . index )
. unwrap_or ( false )
. ok_or ( ParseError ::NoSymbolsForSection {
} ) ;
section_name : section . name . to_owned ( ) ,
} ) ?
. iter ( ) ;
let res = parse_maps_section ( & mut maps , & section , symbols ) ;
let res = self . parse_maps_section ( & mut maps , & section , symbols ) ;
// put the maps back
// put the maps back
self . maps = maps ;
self . maps = maps ;
@ -935,10 +1016,7 @@ impl Object {
res ?
res ?
}
}
BpfSectionKind ::Program = > {
BpfSectionKind ::Program = > {
let ( program , function ) = self . parse_program ( & section ) ? ;
self . parse_programs ( & section ) ? ;
self . functions . insert ( program . function_key ( ) , function ) ;
self . programs
. insert ( program . section . name ( ) . to_owned ( ) , program ) ;
if ! section . relocations . is_empty ( ) {
if ! section . relocations . is_empty ( ) {
self . relocations . insert (
self . relocations . insert (
section . index ,
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 < 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 ,
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
/// Errors caught during parsing the object file
#[ derive(Debug, thiserror::Error) ]
#[ derive(Debug, thiserror::Error) ]
#[ allow(missing_docs) ]
#[ 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 " ) ]
#[ error( " the map number {i} in the `maps` section doesn't have a symbol name " ) ]
MapSymbolNameNotFound { i : usize } ,
MapSymbolNameNotFound { i : usize } ,
#[ error( " no symbols fo r `maps` section, can't parse maps " ) ]
#[ error( " no symbols fo und in the {section_name} section " ) ]
NoSymbolsFor MapsSection ,
NoSymbolsFor Section { section_name : String } ,
/// No BTF parsed for object
/// No BTF parsed for object
#[ error( " no BTF parsed for object " ) ]
#[ error( " no BTF parsed for object " ) ]
@ -1480,9 +1519,17 @@ mod tests {
use super ::* ;
use super ::* ;
use crate ::maps ::PinningType ;
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 < usize > ,
) -> Section < ' a > {
let idx = index . unwrap_or ( 0 ) ;
Section {
Section {
index : SectionIndex ( 0 ) ,
index : SectionIndex ( idx ) ,
kind ,
kind ,
address : 0 ,
address : 0 ,
name ,
name ,
@ -1513,9 +1560,13 @@ mod tests {
address ,
address ,
size ,
size ,
is_definition : false ,
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 < T > ( val : & T ) -> & [ u8 ] {
fn bytes_of < T > ( val : & T ) -> & [ u8 ] {
@ -1637,6 +1688,7 @@ mod tests {
BpfSectionKind ::Data ,
BpfSectionKind ::Data ,
".bss" ,
".bss" ,
map_data ,
map_data ,
None ,
) ,
) ,
) ,
) ,
Ok ( Map ::Legacy ( LegacyMap {
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 ,
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 ( ) ;
. unwrap ( ) ;
obj . parse_section ( fake_section (
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 ,
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 ,
0 , 0 , 16 , 0 , 0 , 0 ,
] ,
] ,
None ,
) )
) )
. unwrap ( ) ;
. unwrap ( ) ;
@ -1688,36 +1742,54 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_program_error ( ) {
fn test_parse_program_error ( ) {
let obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , 1 ) ;
assert_matches ! (
assert_matches ! (
obj . parse_program ( & fake_section (
obj . parse_program s ( & fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"kprobe/foo" ,
"kprobe/foo" ,
& 42 u32 . to_ne_bytes ( ) ,
& 42 u32 . to_ne_bytes ( ) ,
) ) ,
None ,
) , ) ,
Err ( ParseError ::InvalidProgramCode )
Err ( ParseError ::InvalidProgramCode )
) ;
) ;
}
}
#[ test ]
#[ test ]
fn test_parse_program ( ) {
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 ! (
assert_matches ! (
obj . parse_program ( & fake_section ( BpfSectionKind ::Program , "kprobe/foo" , bytes_of ( & fake_ins ( ) ) ) ) ,
prog_foo,
Ok ( ( Program {
Program {
license ,
license ,
kernel_version : None ,
kernel_version : None ,
section : ProgramSection ::KProbe { .. } ,
section : ProgramSection ::KProbe { .. } ,
.. } , Function {
..
name ,
} if license . to_str ( ) . unwrap ( ) = = "GPL"
address : 0 ,
section_index : SectionIndex ( 0 ) ,
section_offset : 0 ,
instructions ,
.. } ) ) if license . to_string_lossy ( ) = = "GPL" & & name = = "foo" & & instructions . len ( ) = = 1
) ;
) ;
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 ]
#[ test ]
@ -1735,13 +1807,72 @@ mod tests {
max_entries : 4 ,
max_entries : 4 ,
map_flags : 5 ,
map_flags : 5 ,
.. Default ::default ( )
.. Default ::default ( )
} )
} ) ,
None ,
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( "foo" ) . is_some ( ) ) ;
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 ]
#[ test ]
fn test_parse_section_multiple_maps ( ) {
fn test_parse_section_multiple_maps ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
@ -1764,7 +1895,12 @@ mod tests {
buf . extend ( [ 0 , 0 , 0 , 0 ] ) ;
buf . extend ( [ 0 , 0 , 0 , 0 ] ) ;
buf . extend ( & map_data ) ;
buf . extend ( & map_data ) ;
assert_matches ! (
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 ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( "foo" ) . is_some ( ) ) ;
assert! ( obj . maps . get ( "foo" ) . is_some ( ) ) ;
@ -1783,13 +1919,23 @@ mod tests {
fn test_parse_section_data ( ) {
fn test_parse_section_data ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
assert_matches ! (
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 ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( ".bss" ) . is_some ( ) ) ;
assert! ( obj . maps . get ( ".bss" ) . is_some ( ) ) ;
assert_matches ! (
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 ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( ".rodata" ) . is_some ( ) ) ;
assert! ( obj . maps . get ( ".rodata" ) . is_some ( ) ) ;
@ -1798,20 +1944,31 @@ mod tests {
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Data ,
BpfSectionKind ::Data ,
".rodata.boo" ,
".rodata.boo" ,
b" map data "
b" map data " ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( ".rodata.boo" ) . is_some ( ) ) ;
assert! ( obj . maps . get ( ".rodata.boo" ) . is_some ( ) ) ;
assert_matches ! (
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 ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( ".data" ) . is_some ( ) ) ;
assert! ( obj . maps . get ( ".data" ) . is_some ( ) ) ;
assert_matches ! (
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 ( ( ) )
Ok ( ( ) )
) ;
) ;
assert! ( obj . maps . get ( ".data.boo" ) . is_some ( ) ) ;
assert! ( obj . maps . get ( ".data.boo" ) . is_some ( ) ) ;
@ -1820,12 +1977,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_kprobe ( ) {
fn test_parse_section_kprobe ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"kprobe/foo" ,
"kprobe/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1841,12 +2000,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_uprobe ( ) {
fn test_parse_section_uprobe ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"uprobe/foo" ,
"uprobe/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1862,12 +2023,15 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_trace_point ( ) {
fn test_parse_section_trace_point ( ) {
let mut obj = fake_obj ( ) ;
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 ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"tracepoint/foo" ,
"tracepoint/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1883,12 +2047,13 @@ mod tests {
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"tp/foo/bar" ,
"tp/foo/bar" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
Some ( 1 ) ,
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
assert_matches ! (
assert_matches ! (
obj . programs . get ( " foo/ bar") ,
obj . programs . get ( " bar") ,
Some ( Program {
Some ( Program {
section : ProgramSection ::TracePoint { .. } ,
section : ProgramSection ::TracePoint { .. } ,
..
..
@ -1899,12 +2064,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_socket_filter ( ) {
fn test_parse_section_socket_filter ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"socket/foo" ,
"socket/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1920,12 +2087,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_xdp ( ) {
fn test_parse_section_xdp ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"xdp/foo" ,
"xdp/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1941,12 +2110,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_xdp_frags ( ) {
fn test_parse_section_xdp_frags ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"xdp.frags/foo" ,
"xdp.frags/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1962,12 +2133,15 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_raw_tp ( ) {
fn test_parse_section_raw_tp ( ) {
let mut obj = fake_obj ( ) ;
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 ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"raw_tp/foo" ,
"raw_tp/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1983,7 +2157,8 @@ mod tests {
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"raw_tracepoint/bar" ,
"raw_tracepoint/bar" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
Some ( 1 )
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -1999,12 +2174,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_lsm ( ) {
fn test_parse_section_lsm ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"lsm/foo" ,
"lsm/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2023,12 +2200,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_lsm_sleepable ( ) {
fn test_parse_section_lsm_sleepable ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"lsm.s/foo" ,
"lsm.s/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2047,12 +2226,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_btf_tracepoint ( ) {
fn test_parse_section_btf_tracepoint ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"tp_btf/foo" ,
"tp_btf/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2068,12 +2249,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_skskb_unnamed ( ) {
fn test_parse_section_skskb_unnamed ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "stream_parser" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"sk_skb/stream_parser" ,
"sk_skb/stream_parser" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2089,12 +2272,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_skskb_named ( ) {
fn test_parse_section_skskb_named ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "my_parser" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"sk_skb/stream_parser/my_parser" ,
"sk_skb/stream_parser/my_parser" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2110,12 +2295,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_fentry ( ) {
fn test_parse_section_fentry ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"fentry/foo" ,
"fentry/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2131,12 +2318,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_fexit ( ) {
fn test_parse_section_fexit ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"fexit/foo" ,
"fexit/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2152,12 +2341,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_cgroup_skb_ingress_unnamed ( ) {
fn test_parse_section_cgroup_skb_ingress_unnamed ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "ingress" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup_skb/ingress" ,
"cgroup_skb/ingress" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2173,12 +2364,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_cgroup_skb_ingress_named ( ) {
fn test_parse_section_cgroup_skb_ingress_named ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup_skb/ingress/foo" ,
"cgroup_skb/ingress/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2194,12 +2387,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_cgroup_skb_no_direction_unamed ( ) {
fn test_parse_section_cgroup_skb_no_direction_unamed ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "skb" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup/skb" ,
"cgroup/skb" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2215,12 +2410,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_cgroup_skb_no_direction_named ( ) {
fn test_parse_section_cgroup_skb_no_direction_named ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup/skb/foo" ,
"cgroup/skb/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2236,12 +2433,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_sock_addr_named ( ) {
fn test_parse_section_sock_addr_named ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup/connect4/foo" ,
"cgroup/connect4/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2260,12 +2459,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_sock_addr_unnamed ( ) {
fn test_parse_section_sock_addr_unnamed ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "connect4" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup/connect4" ,
"cgroup/connect4" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2284,12 +2485,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_sockopt_named ( ) {
fn test_parse_section_sockopt_named ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "foo" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup/getsockopt/foo" ,
"cgroup/getsockopt/foo" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2308,12 +2511,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_parse_section_sockopt_unnamed ( ) {
fn test_parse_section_sockopt_unnamed ( ) {
let mut obj = fake_obj ( ) ;
let mut obj = fake_obj ( ) ;
fake_sym ( & mut obj , 0 , 0 , "getsockopt" , FAKE_INS_LEN ) ;
assert_matches ! (
assert_matches ! (
obj . parse_section ( fake_section (
obj . parse_section ( fake_section (
BpfSectionKind ::Program ,
BpfSectionKind ::Program ,
"cgroup/getsockopt" ,
"cgroup/getsockopt" ,
bytes_of ( & fake_ins ( ) )
bytes_of ( & fake_ins ( ) ) ,
None
) ) ,
) ) ,
Ok ( ( ) )
Ok ( ( ) )
) ;
) ;
@ -2455,10 +2660,10 @@ mod tests {
0x2E , 0x6D , 0x61 , 0x70 , 0x73 , 0x00 , 0x6C , 0x69 , 0x63 , 0x65 , 0x6E , 0x73 , 0x65 , 0x00 ,
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 ( ) ;
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 ( ) ;
obj . parse_section ( map_section ) . unwrap ( ) ;
let map = obj . maps . get ( "map_1" ) . unwrap ( ) ;
let map = obj . maps . get ( "map_1" ) . unwrap ( ) ;