@ -27,17 +27,16 @@ pub enum RelocationError {
#[ error(transparent) ]
#[ error(transparent) ]
IOError ( #[ from ] io ::Error ) ,
IOError ( #[ from ] io ::Error ) ,
#[ error( " section `{name}` not found" ) ]
#[ error( " program not found" ) ]
SectionNotFound { name : String } ,
ProgramNotFound ,
#[ error( " invalid relocation access string {access_str} " ) ]
#[ error( " invalid relocation access string {access_str} " ) ]
InvalidAccessString { access_str : String } ,
InvalidAccessString { access_str : String } ,
#[ error( " invalid instruction index #{index} referenced by relocation #{relocation_number} in section `{section_name}` " ) ]
#[ error( " invalid instruction index #{index} referenced by relocation #{relocation_number} , the program contains {num_instructions} instructions " ) ]
InvalidInstructionIndex {
InvalidInstructionIndex {
index : usize ,
index : usize ,
num_instructions : usize ,
num_instructions : usize ,
section_name : String ,
relocation_number : usize ,
relocation_number : usize ,
} ,
} ,
@ -170,7 +169,6 @@ impl Object {
} ) ? ;
} ) ? ;
let mut candidates_cache = HashMap ::< u32 , Vec < Candidate > > ::new ( ) ;
let mut candidates_cache = HashMap ::< u32 , Vec < Candidate > > ::new ( ) ;
for ( sec_name_off , relos ) in btf_ext . relocations ( ) {
for ( sec_name_off , relos ) in btf_ext . relocations ( ) {
let section_name = local_btf . string_at ( * sec_name_off ) ? ;
let section_name = local_btf . string_at ( * sec_name_off ) ? ;
@ -180,12 +178,42 @@ impl Object {
continue ;
continue ;
}
}
let section_name = parts [ 1 ] ;
let section_name = parts [ 1 ] ;
let program = self . programs . get_mut ( section_name ) . ok_or_else ( | | {
let program = self
RelocationError ::SectionNotFound {
. programs
name : section_name . to_string ( ) ,
. get_mut ( section_name )
}
. ok_or ( BpfError ::RelocationError {
program_name : section_name . to_owned ( ) ,
error : Box ::new ( RelocationError ::ProgramNotFound ) ,
} ) ? ;
} ) ? ;
match relocate_btf_program (
program ,
relos ,
local_btf ,
& target_btf ,
& mut candidates_cache ,
) {
Ok ( _ ) = > { }
Err ( ErrorWrapper ::BtfError ( e ) ) = > return Err ( e ) ? ,
Err ( ErrorWrapper ::RelocationError ( error ) ) = > {
return Err ( BpfError ::RelocationError {
program_name : section_name . to_owned ( ) ,
error : Box ::new ( error ) ,
} )
}
}
}
Ok ( ( ) )
}
}
fn relocate_btf_program < ' target > (
program : & mut Program ,
relos : & [ Relocation ] ,
local_btf : & Btf ,
target_btf : & ' target Btf ,
candidates_cache : & mut HashMap < u32 , Vec < Candidate < ' target > > > ,
) -> Result < ( ) , ErrorWrapper > {
for rel in relos {
for rel in relos {
let instructions = & mut program . instructions ;
let instructions = & mut program . instructions ;
let ins_index = rel . ins_offset as usize / std ::mem ::size_of ::< bpf_insn > ( ) ;
let ins_index = rel . ins_offset as usize / std ::mem ::size_of ::< bpf_insn > ( ) ;
@ -193,7 +221,6 @@ impl Object {
return Err ( RelocationError ::InvalidInstructionIndex {
return Err ( RelocationError ::InvalidInstructionIndex {
index : ins_index ,
index : ins_index ,
num_instructions : instructions . len ( ) ,
num_instructions : instructions . len ( ) ,
section_name : section_name . to_string ( ) ,
relocation_number : rel . number ,
relocation_number : rel . number ,
} ) ? ;
} ) ? ;
}
}
@ -211,7 +238,7 @@ impl Object {
None = > {
None = > {
candidates_cache . insert (
candidates_cache . insert (
rel . type_id ,
rel . type_id ,
find_candidates ( local_ty , local_name , & target_btf ) ? ,
find_candidates ( local_ty , local_name , target_btf ) ? ,
) ;
) ;
candidates_cache . get ( & rel . type_id ) . unwrap ( )
candidates_cache . get ( & rel . type_id ) . unwrap ( )
}
}
@ -220,11 +247,8 @@ impl Object {
let mut matches = Vec ::new ( ) ;
let mut matches = Vec ::new ( ) ;
for candidate in candidates {
for candidate in candidates {
if let Some ( candidate_spec ) = match_candidate ( & local_spec , candidate ) ? {
if let Some ( candidate_spec ) = match_candidate ( & local_spec , candidate ) ? {
let comp_rel = ComputedRelocation ::new (
let comp_rel =
rel ,
ComputedRelocation ::new ( rel , & local_spec , Some ( & candidate_spec ) ) ? ;
& local_spec ,
Some ( & candidate_spec ) ,
) ? ;
matches . push ( ( candidate . name . clone ( ) , candidate_spec , comp_rel ) ) ;
matches . push ( ( candidate . name . clone ( ) , candidate_spec , comp_rel ) ) ;
}
}
}
}
@ -264,13 +288,11 @@ impl Object {
ComputedRelocation ::new ( rel , & local_spec , None ) ?
ComputedRelocation ::new ( rel , & local_spec , None ) ?
} ;
} ;
comp_rel . apply ( program , rel , section_name , local_btf , & target_btf ) ? ;
comp_rel . apply ( program , rel , local_btf , & target_btf ) ? ;
}
}
}
Ok ( ( ) )
Ok ( ( ) )
}
}
}
fn flavorless_name ( name : & str ) -> & str {
fn flavorless_name ( name : & str ) -> & str {
name . splitn ( 2 , "___" ) . next ( ) . unwrap ( )
name . splitn ( 2 , "___" ) . next ( ) . unwrap ( )
@ -306,7 +328,7 @@ fn find_candidates<'target>(
fn match_candidate < ' target > (
fn match_candidate < ' target > (
local_spec : & AccessSpec ,
local_spec : & AccessSpec ,
candidate : & ' target Candidate ,
candidate : & ' target Candidate ,
) -> Result < Option < AccessSpec < ' target > > , Bpf Error> {
) -> Result < Option < AccessSpec < ' target > > , ErrorWrappe r> {
let mut target_spec = AccessSpec {
let mut target_spec = AccessSpec {
btf : candidate . btf ,
btf : candidate . btf ,
root_type_id : candidate . type_id ,
root_type_id : candidate . type_id ,
@ -434,7 +456,7 @@ fn match_member<'local, 'target>(
target_btf : & ' target Btf ,
target_btf : & ' target Btf ,
target_id : u32 ,
target_id : u32 ,
target_spec : & mut AccessSpec < ' target > ,
target_spec : & mut AccessSpec < ' target > ,
) -> Result < Option < u32 > , Bpf Error> {
) -> Result < Option < u32 > , ErrorWrappe r> {
let local_ty = local_btf . type_by_id ( local_accessor . type_id ) ? ;
let local_ty = local_btf . type_by_id ( local_accessor . type_id ) ? ;
let local_member = match local_ty {
let local_member = match local_ty {
BtfType ::Struct ( _ , members ) | BtfType ::Union ( _ , members ) = > {
BtfType ::Struct ( _ , members ) | BtfType ::Union ( _ , members ) = > {
@ -519,7 +541,7 @@ impl<'a> AccessSpec<'a> {
root_type_id : u32 ,
root_type_id : u32 ,
spec : & str ,
spec : & str ,
relocation : Relocation ,
relocation : Relocation ,
) -> Result < AccessSpec < ' a > , Bpf Error> {
) -> Result < AccessSpec < ' a > , ErrorWrappe r> {
let parts = spec
let parts = spec
. split ( ":" )
. split ( ":" )
. map ( | s | s . parse ::< usize > ( ) )
. map ( | s | s . parse ::< usize > ( ) )
@ -724,7 +746,7 @@ impl ComputedRelocation {
rel : & Relocation ,
rel : & Relocation ,
local_spec : & AccessSpec ,
local_spec : & AccessSpec ,
target_spec : Option < & AccessSpec > ,
target_spec : Option < & AccessSpec > ,
) -> Result < ComputedRelocation , Bpf Error> {
) -> Result < ComputedRelocation , ErrorWrappe r> {
use RelocationKind ::* ;
use RelocationKind ::* ;
let ret = match rel . kind {
let ret = match rel . kind {
FieldByteOffset | FieldByteSize | FieldExists | FieldSigned | FieldLShift64
FieldByteOffset | FieldByteSize | FieldExists | FieldSigned | FieldLShift64
@ -749,10 +771,9 @@ impl ComputedRelocation {
& self ,
& self ,
program : & mut Program ,
program : & mut Program ,
rel : & Relocation ,
rel : & Relocation ,
section_name : & str ,
local_btf : & Btf ,
local_btf : & Btf ,
target_btf : & Btf ,
target_btf : & Btf ,
) -> Result < ( ) , Bpf Error> {
) -> Result < ( ) , ErrorWrappe r> {
let instructions = & mut program . instructions ;
let instructions = & mut program . instructions ;
let num_instructions = instructions . len ( ) ;
let num_instructions = instructions . len ( ) ;
let ins_index = rel . ins_offset as usize / std ::mem ::size_of ::< bpf_insn > ( ) ;
let ins_index = rel . ins_offset as usize / std ::mem ::size_of ::< bpf_insn > ( ) ;
@ -762,7 +783,6 @@ impl ComputedRelocation {
. ok_or ( RelocationError ::InvalidInstructionIndex {
. ok_or ( RelocationError ::InvalidInstructionIndex {
index : rel . ins_offset as usize ,
index : rel . ins_offset as usize ,
num_instructions ,
num_instructions ,
section_name : section_name . to_string ( ) ,
relocation_number : rel . number ,
relocation_number : rel . number ,
} ) ? ;
} ) ? ;
@ -840,7 +860,6 @@ impl ComputedRelocation {
RelocationError ::InvalidInstructionIndex {
RelocationError ::InvalidInstructionIndex {
index : ins_index + 1 ,
index : ins_index + 1 ,
num_instructions ,
num_instructions ,
section_name : section_name . to_string ( ) ,
relocation_number : rel . number ,
relocation_number : rel . number ,
} ,
} ,
) ? ;
) ? ;
@ -862,7 +881,7 @@ impl ComputedRelocation {
fn compute_enum_relocation (
fn compute_enum_relocation (
rel : & Relocation ,
rel : & Relocation ,
spec : Option < & AccessSpec > ,
spec : Option < & AccessSpec > ,
) -> Result < ComputedRelocationValue , Bpf Error> {
) -> Result < ComputedRelocationValue , ErrorWrappe r> {
use RelocationKind ::* ;
use RelocationKind ::* ;
let value = match rel . kind {
let value = match rel . kind {
EnumVariantExists = > spec . is_some ( ) as u32 ,
EnumVariantExists = > spec . is_some ( ) as u32 ,
@ -888,7 +907,7 @@ impl ComputedRelocation {
fn compute_field_relocation (
fn compute_field_relocation (
rel : & Relocation ,
rel : & Relocation ,
spec : Option < & AccessSpec > ,
spec : Option < & AccessSpec > ,
) -> Result < ComputedRelocationValue , Bpf Error> {
) -> Result < ComputedRelocationValue , ErrorWrappe r> {
use RelocationKind ::* ;
use RelocationKind ::* ;
if let FieldExists = rel . kind {
if let FieldExists = rel . kind {
@ -1013,7 +1032,7 @@ impl ComputedRelocation {
rel : & Relocation ,
rel : & Relocation ,
local_spec : & AccessSpec ,
local_spec : & AccessSpec ,
target_spec : Option < & AccessSpec > ,
target_spec : Option < & AccessSpec > ,
) -> Result < ComputedRelocationValue , Bpf Error> {
) -> Result < ComputedRelocationValue , ErrorWrappe r> {
use RelocationKind ::* ;
use RelocationKind ::* ;
let value = match rel . kind {
let value = match rel . kind {
TypeIdLocal = > local_spec . root_type_id ,
TypeIdLocal = > local_spec . root_type_id ,
@ -1037,3 +1056,14 @@ impl ComputedRelocation {
} )
} )
}
}
}
}
// this exists only to simplify propagating errors from relocate_btf() and to associate
// RelocationError(s) with their respective program name
#[ derive(Error, Debug) ]
enum ErrorWrapper {
#[ error(transparent) ]
BtfError ( #[ from ] BtfError ) ,
#[ error(transparent) ]
RelocationError ( #[ from ] RelocationError ) ,
}