aya: support relocations across multiple text sections + fixes

Fix R_BPF_64_64 text relocations in sections other than .text (for
instance .text.unlikely). Also fix misc bugs triggered by integration
tests.
pull/572/head
Alessandro Decina 1 year ago
parent b2b9bd2edf
commit 93ac3e94bc

@ -1045,9 +1045,7 @@ mod tests {
let name_offset = btf.add_string("&mut int".to_string()); let name_offset = btf.add_string("&mut int".to_string());
let ptr_type_id = btf.add_type(BtfType::Ptr(Ptr::new(name_offset, int_type_id))); let ptr_type_id = btf.add_type(BtfType::Ptr(Ptr::new(name_offset, int_type_id)));
let features = BtfFeatures { let features = Default::default();
..Default::default()
};
btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features) btf.fixup_and_sanitize(&HashMap::new(), &HashMap::new(), &features)
.unwrap(); .unwrap();

@ -37,8 +37,9 @@
//! let bytes = std::fs::read("program.o").unwrap(); //! let bytes = std::fs::read("program.o").unwrap();
//! let mut object = Object::parse(&bytes).unwrap(); //! let mut object = Object::parse(&bytes).unwrap();
//! // Relocate the programs //! // Relocate the programs
//! object.relocate_calls().unwrap(); //! let text_sections = std::collections::HashSet::new();
//! object.relocate_maps(std::iter::empty()).unwrap(); //! object.relocate_calls(&text_sections).unwrap();
//! object.relocate_maps(std::iter::empty(), &text_sections).unwrap();
//! //!
//! // Run with rbpf //! // Run with rbpf
//! let instructions = &object.programs["prog_name"].function.instructions; //! let instructions = &object.programs["prog_name"].function.instructions;

@ -52,14 +52,13 @@ pub struct Object {
/// in [ProgramSection]s as keys. /// in [ProgramSection]s as keys.
pub programs: HashMap<String, Program>, pub programs: HashMap<String, Program>,
/// Functions /// Functions
pub functions: HashMap<u64, Function>, pub functions: HashMap<(usize, u64), Function>,
pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>, pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
pub(crate) symbols_by_index: HashMap<usize, Symbol>, pub(crate) symbol_table: HashMap<usize, Symbol>,
pub(crate) section_sizes: HashMap<String, u64>, pub(crate) section_sizes: HashMap<String, 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
pub(crate) symbol_offset_by_name: HashMap<String, u64>, pub(crate) symbol_offset_by_name: HashMap<String, u64>,
pub(crate) text_section_index: Option<usize>,
} }
/// An eBPF program /// An eBPF program
@ -522,7 +521,7 @@ impl Object {
is_definition: symbol.is_definition(), is_definition: symbol.is_definition(),
kind: symbol.kind(), kind: symbol.kind(),
}; };
bpf_obj.symbols_by_index.insert(symbol.index().0, sym); bpf_obj.symbol_table.insert(symbol.index().0, sym);
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());
@ -564,17 +563,16 @@ impl Object {
programs: HashMap::new(), programs: HashMap::new(),
functions: HashMap::new(), functions: HashMap::new(),
relocations: HashMap::new(), relocations: HashMap::new(),
symbols_by_index: HashMap::new(), symbol_table: HashMap::new(),
section_sizes: HashMap::new(), section_sizes: HashMap::new(),
symbol_offset_by_name: HashMap::new(), symbol_offset_by_name: HashMap::new(),
text_section_index: None,
} }
} }
/// Patches map data /// Patches map data
pub fn patch_map_data(&mut self, globals: HashMap<&str, &[u8]>) -> Result<(), ParseError> { pub fn patch_map_data(&mut self, globals: HashMap<&str, &[u8]>) -> Result<(), ParseError> {
let symbols: HashMap<String, &Symbol> = self let symbols: HashMap<String, &Symbol> = self
.symbols_by_index .symbol_table
.iter() .iter()
.filter(|(_, s)| s.name.is_some()) .filter(|(_, s)| s.name.is_some())
.map(|(_, s)| (s.name.as_ref().unwrap().clone(), s)) .map(|(_, s)| (s.name.as_ref().unwrap().clone(), s))
@ -668,12 +666,10 @@ impl Object {
}) })
} }
fn parse_text_section(&mut self, mut section: Section) -> Result<(), ParseError> { fn parse_text_section(&mut self, section: Section) -> Result<(), ParseError> {
self.text_section_index = Some(section.index.0);
let mut symbols_by_address = HashMap::new(); let mut symbols_by_address = HashMap::new();
for sym in self.symbols_by_index.values() { for sym in self.symbol_table.values() {
if sym.is_definition if sym.is_definition
&& sym.kind == SymbolKind::Text && sym.kind == SymbolKind::Text
&& sym.section_index == Some(section.index.0) && sym.section_index == Some(section.index.0)
@ -729,7 +725,7 @@ impl Object {
}; };
self.functions.insert( self.functions.insert(
sym.address, (section.index.0, sym.address),
Function { Function {
address, address,
name: sym.name.clone().unwrap(), name: sym.name.clone().unwrap(),
@ -804,7 +800,7 @@ impl Object {
Ok(()) Ok(())
} }
fn parse_section(&mut self, mut section: Section) -> Result<(), ParseError> { fn parse_section(&mut self, section: Section) -> Result<(), ParseError> {
let mut parts = section.name.rsplitn(2, '/').collect::<Vec<_>>(); let mut parts = section.name.rsplitn(2, '/').collect::<Vec<_>>();
parts.reverse(); parts.reverse();
@ -828,7 +824,7 @@ impl Object {
BpfSectionKind::BtfExt => self.parse_btf_ext(&section)?, BpfSectionKind::BtfExt => self.parse_btf_ext(&section)?,
BpfSectionKind::BtfMaps => { BpfSectionKind::BtfMaps => {
let symbols: HashMap<String, Symbol> = self let symbols: HashMap<String, Symbol> = self
.symbols_by_index .symbol_table
.values() .values()
.filter(|s| { .filter(|s| {
if let Some(idx) = s.section_index { if let Some(idx) = s.section_index {
@ -849,7 +845,7 @@ 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.symbols_by_index.values().filter(|s| { let symbols = self.symbol_table.values().filter(|s| {
s.section_index s.section_index
.map(|idx| idx == section.index.0) .map(|idx| idx == section.index.0)
.unwrap_or(false) .unwrap_or(false)
@ -1097,6 +1093,7 @@ impl<'data, 'file, 'a> TryFrom<&'a ObjSection<'data, 'file>> for Section<'a> {
_ => return Err(ParseError::UnsupportedRelocationTarget), _ => return Err(ParseError::UnsupportedRelocationTarget),
}, },
offset, offset,
size: r.size(),
}) })
}) })
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
@ -1399,8 +1396,8 @@ mod tests {
} }
fn fake_sym(obj: &mut Object, section_index: usize, address: u64, name: &str, size: u64) { fn fake_sym(obj: &mut Object, section_index: usize, address: u64, name: &str, size: u64) {
let idx = obj.symbols_by_index.len(); let idx = obj.symbol_table.len();
obj.symbols_by_index.insert( obj.symbol_table.insert(
idx + 1, idx + 1,
Symbol { Symbol {
index: idx + 1, index: idx + 1,
@ -2213,7 +2210,7 @@ mod tests {
data: vec![0, 0, 0], data: vec![0, 0, 0],
}), }),
); );
obj.symbols_by_index.insert( obj.symbol_table.insert(
1, 1,
Symbol { Symbol {
index: 1, index: 1,

@ -1,6 +1,7 @@
//! Program relocation handling. //! Program relocation handling.
use core::mem; use core::mem;
use std::collections::HashSet;
use alloc::{borrow::ToOwned, string::String}; use alloc::{borrow::ToOwned, string::String};
use log::debug; use log::debug;
@ -85,6 +86,7 @@ pub enum RelocationError {
pub(crate) struct Relocation { pub(crate) struct Relocation {
// byte offset of the instruction to be relocated // byte offset of the instruction to be relocated
pub(crate) offset: u64, pub(crate) offset: u64,
pub(crate) size: u8,
// index of the symbol to relocate to // index of the symbol to relocate to
pub(crate) symbol_index: usize, pub(crate) symbol_index: usize,
} }
@ -105,6 +107,7 @@ impl Object {
pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>( pub fn relocate_maps<'a, I: Iterator<Item = (&'a str, Option<i32>, &'a Map)>>(
&mut self, &mut self,
maps: I, maps: I,
text_sections: &HashSet<usize>,
) -> Result<(), BpfRelocationError> { ) -> Result<(), BpfRelocationError> {
let mut maps_by_section = HashMap::new(); let mut maps_by_section = HashMap::new();
let mut maps_by_symbol = HashMap::new(); let mut maps_by_symbol = HashMap::new();
@ -128,8 +131,8 @@ impl Object {
relocations.values(), relocations.values(),
&maps_by_section, &maps_by_section,
&maps_by_symbol, &maps_by_symbol,
&self.symbols_by_index, &self.symbol_table,
self.text_section_index, text_sections,
) )
.map_err(|error| BpfRelocationError { .map_err(|error| BpfRelocationError {
function: function.name.clone(), function: function.name.clone(),
@ -142,13 +145,16 @@ impl Object {
} }
/// Relocates function calls /// Relocates function calls
pub fn relocate_calls(&mut self) -> Result<(), BpfRelocationError> { pub fn relocate_calls(
&mut self,
text_sections: &HashSet<usize>,
) -> Result<(), BpfRelocationError> {
for (name, program) in self.programs.iter_mut() { for (name, program) in self.programs.iter_mut() {
let linker = FunctionLinker::new( let linker = FunctionLinker::new(
self.text_section_index,
&self.functions, &self.functions,
&self.relocations, &self.relocations,
&self.symbols_by_index, &self.symbol_table,
text_sections,
); );
linker.link(program).map_err(|error| BpfRelocationError { linker.link(program).map_err(|error| BpfRelocationError {
function: name.to_owned(), function: name.to_owned(),
@ -166,7 +172,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
maps_by_section: &HashMap<usize, (&str, Option<i32>, &Map)>, maps_by_section: &HashMap<usize, (&str, Option<i32>, &Map)>,
maps_by_symbol: &HashMap<usize, (&str, Option<i32>, &Map)>, maps_by_symbol: &HashMap<usize, (&str, Option<i32>, &Map)>,
symbol_table: &HashMap<usize, Symbol>, symbol_table: &HashMap<usize, Symbol>,
text_section_index: Option<usize>, text_sections: &HashSet<usize>,
) -> Result<(), RelocationError> { ) -> Result<(), RelocationError> {
let section_offset = fun.section_offset; let section_offset = fun.section_offset;
let instructions = &mut fun.instructions; let instructions = &mut fun.instructions;
@ -202,16 +208,17 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
}; };
// calls and relocation to .text symbols are handled in a separate step // calls and relocation to .text symbols are handled in a separate step
if insn_is_call(&instructions[ins_index]) || sym.section_index == text_section_index { if insn_is_call(&instructions[ins_index]) || text_sections.contains(&section_index) {
continue; continue;
} }
let (name, fd, map) = if let Some(m) = maps_by_symbol.get(&rel.symbol_index) { let (name, fd, map) = if let Some(m) = maps_by_symbol.get(&rel.symbol_index) {
let map = &m.2; let map = &m.2;
debug!( debug!(
"relocating map by symbol index {}, kind {:?}", "relocating map by symbol index {:?}, kind {:?} at insn {ins_index} in section {}",
map.section_index(), map.symbol_index(),
map.section_kind() map.section_kind(),
fun.section_index.0
); );
debug_assert_eq!(map.symbol_index().unwrap(), rel.symbol_index); debug_assert_eq!(map.symbol_index().unwrap(), rel.symbol_index);
m m
@ -229,9 +236,10 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
}; };
let map = &m.2; let map = &m.2;
debug!( debug!(
"relocating map by section index {}, kind {:?}", "relocating map by section index {}, kind {:?} at insn {ins_index} in section {}",
map.section_index(), map.section_index(),
map.section_kind() map.section_kind(),
fun.section_index.0,
); );
debug_assert_eq!(map.symbol_index(), None); debug_assert_eq!(map.symbol_index(), None);
@ -261,26 +269,26 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
} }
struct FunctionLinker<'a> { struct FunctionLinker<'a> {
text_section_index: Option<usize>, functions: &'a HashMap<(usize, u64), Function>,
functions: &'a HashMap<u64, Function>,
linked_functions: HashMap<u64, usize>, linked_functions: HashMap<u64, usize>,
relocations: &'a HashMap<SectionIndex, HashMap<u64, Relocation>>, relocations: &'a HashMap<SectionIndex, HashMap<u64, Relocation>>,
symbol_table: &'a HashMap<usize, Symbol>, symbol_table: &'a HashMap<usize, Symbol>,
text_sections: &'a HashSet<usize>,
} }
impl<'a> FunctionLinker<'a> { impl<'a> FunctionLinker<'a> {
fn new( fn new(
text_section_index: Option<usize>, functions: &'a HashMap<(usize, u64), Function>,
functions: &'a HashMap<u64, Function>,
relocations: &'a HashMap<SectionIndex, HashMap<u64, Relocation>>, relocations: &'a HashMap<SectionIndex, HashMap<u64, Relocation>>,
symbol_table: &'a HashMap<usize, Symbol>, symbol_table: &'a HashMap<usize, Symbol>,
text_sections: &'a HashSet<usize>,
) -> FunctionLinker<'a> { ) -> FunctionLinker<'a> {
FunctionLinker { FunctionLinker {
text_section_index,
functions, functions,
linked_functions: HashMap::new(), linked_functions: HashMap::new(),
relocations, relocations,
symbol_table, symbol_table,
text_sections,
} }
} }
@ -310,6 +318,10 @@ impl<'a> FunctionLinker<'a> {
// at `start_ins`. We'll use `start_ins` to do pc-relative calls. // at `start_ins`. We'll use `start_ins` to do pc-relative calls.
let start_ins = program.instructions.len(); let start_ins = program.instructions.len();
program.instructions.extend(&fun.instructions); program.instructions.extend(&fun.instructions);
debug!(
"linked function `{}` at instruction {}",
fun.name, start_ins
);
// link func and line info into the main program // link func and line info into the main program
// the offset needs to be adjusted // the offset needs to be adjusted
@ -326,101 +338,110 @@ impl<'a> FunctionLinker<'a> {
fn relocate(&mut self, program: &mut Function, fun: &Function) -> Result<(), RelocationError> { fn relocate(&mut self, program: &mut Function, fun: &Function) -> Result<(), RelocationError> {
let relocations = self.relocations.get(&fun.section_index); let relocations = self.relocations.get(&fun.section_index);
debug!("relocating program {} function {}", program.name, fun.name);
let n_instructions = fun.instructions.len(); let n_instructions = fun.instructions.len();
let start_ins = program.instructions.len() - n_instructions; let start_ins = program.instructions.len() - n_instructions;
debug!(
"relocating program `{}` function `{}` size {}",
program.name, fun.name, n_instructions
);
// process all the instructions. We can't only loop over relocations since we need to // process all the instructions. We can't only loop over relocations since we need to
// patch pc-relative calls too. // patch pc-relative calls too.
for ins_index in start_ins..start_ins + n_instructions { for ins_index in start_ins..start_ins + n_instructions {
let ins = program.instructions[ins_index]; let ins = program.instructions[ins_index];
let is_call = insn_is_call(&ins); let is_call = insn_is_call(&ins);
// only resolve relocations for calls or for instructions that let rel = relocations
// reference symbols in the .text section (eg let callback = .and_then(|relocations| {
// &some_fun) relocations
let rel = if let Some(relocations) = relocations { .get(&((fun.section_offset + (ins_index - start_ins) * INS_SIZE) as u64))
self.text_relocation_info(
relocations,
(fun.section_offset + (ins_index - start_ins) * INS_SIZE) as u64,
)?
// if not a call and not a .text reference, ignore the
// relocation (see relocate_maps())
.and_then(|(_, sym)| {
if is_call {
return Some(sym.address);
}
match sym.kind {
SymbolKind::Text => Some(sym.address),
SymbolKind::Section if sym.section_index == self.text_section_index => {
Some(sym.address + ins.imm as u64)
}
_ => None,
}
}) })
} else { .and_then(|rel| {
None // get the symbol for the relocation
}; self.symbol_table
.get(&rel.symbol_index)
.map(|sym| (rel, sym))
})
.filter(|(_rel, sym)| {
// only consider text relocations, data relocations are
// relocated in relocate_maps()
sym.kind == SymbolKind::Text
|| sym
.section_index
.map(|section_index| self.text_sections.contains(&section_index))
.unwrap_or(false)
});
// some_fun() or let x = &some_fun trigger linking, everything else // not a call and not a text relocation, we don't need to do anything
// can be ignored here
if !is_call && rel.is_none() { if !is_call && rel.is_none() {
continue; continue;
} }
let callee_address = if let Some(address) = rel { let (callee_section_index, callee_address) = if let Some((rel, sym)) = rel {
// We have a relocation entry for the instruction at `ins_index`, the address of let address = match sym.kind {
// the callee is the address of the relocation's target symbol. SymbolKind::Text => sym.address,
address // R_BPF_64_32 this is a call
SymbolKind::Section if rel.size == 32 => {
sym.address + (ins.imm + 1) as u64 * INS_SIZE as u64
}
// R_BPF_64_64 this is a ld_imm64 text relocation
SymbolKind::Section if rel.size == 64 => sym.address + ins.imm as u64,
_ => todo!(), // FIXME: return an error here,
};
(sym.section_index.unwrap(), address)
} else { } else {
// The caller and the callee are in the same ELF section and this is a pc-relative // The caller and the callee are in the same ELF section and this is a pc-relative
// call. Resolve the pc-relative imm to an absolute address. // call. Resolve the pc-relative imm to an absolute address.
let ins_size = INS_SIZE as i64; let ins_size = INS_SIZE as i64;
(
fun.section_index.0,
(fun.section_offset as i64 (fun.section_offset as i64
+ ((ins_index - start_ins) as i64) * ins_size + ((ins_index - start_ins) as i64) * ins_size
+ (ins.imm + 1) as i64 * ins_size) as u64 + (ins.imm + 1) as i64 * ins_size) as u64,
)
}; };
debug!( debug!(
"relocating {} to callee address {} ({})", "relocating {} to callee address {:#x} in section {} ({}) at instruction {ins_index}",
if is_call { "call" } else { "reference" }, if is_call { "call" } else { "reference" },
callee_address, callee_address,
callee_section_index,
if rel.is_some() { if rel.is_some() {
"relocation" "relocation"
} else { } else {
"relative" "pc-relative"
}, },
); );
// lookup and link the callee if it hasn't been linked already. `callee_ins_index` will // lookup and link the callee if it hasn't been linked already. `callee_ins_index` will
// contain the instruction index of the callee inside the program. // contain the instruction index of the callee inside the program.
let callee = let callee = self
self.functions .functions
.get(&callee_address) .get(&(callee_section_index, callee_address))
.ok_or(RelocationError::UnknownFunction { .ok_or(RelocationError::UnknownFunction {
address: callee_address, address: callee_address,
caller_name: fun.name.clone(), caller_name: fun.name.clone(),
})?; })?;
debug!("callee is {}", callee.name); debug!("callee is `{}`", callee.name);
let callee_ins_index = self.link_function(program, callee)?; let callee_ins_index = self.link_function(program, callee)? as i32;
let mut ins = &mut program.instructions[ins_index]; let mut ins = &mut program.instructions[ins_index];
ins.imm = if callee_ins_index < ins_index { let ins_index = ins_index as i32;
-((ins_index - callee_ins_index + 1) as i32) ins.imm = callee_ins_index - ins_index - 1;
} else { debug!(
(callee_ins_index - ins_index - 1) as i32 "callee `{}` is at ins {callee_ins_index}, {} from current instruction {ins_index}",
}; callee.name, ins.imm
);
if !is_call { if !is_call {
ins.set_src_reg(BPF_PSEUDO_FUNC as u8); ins.set_src_reg(BPF_PSEUDO_FUNC as u8);
} }
} }
debug!( debug!(
"finished relocating program {} function {}", "finished relocating program `{}` function `{}`",
program.name, fun.name program.name, fun.name
); );
@ -459,25 +480,6 @@ impl<'a> FunctionLinker<'a> {
} }
Ok(()) Ok(())
} }
fn text_relocation_info(
&self,
relocations: &HashMap<u64, Relocation>,
offset: u64,
) -> Result<Option<(Relocation, Symbol)>, RelocationError> {
if let Some(rel) = relocations.get(&offset) {
let sym =
self.symbol_table
.get(&rel.symbol_index)
.ok_or(RelocationError::UnknownSymbol {
index: rel.symbol_index,
})?;
Ok(Some((*rel, sym.clone())))
} else {
Ok(None)
}
}
} }
fn insn_is_call(ins: &bpf_insn) -> bool { fn insn_is_call(ins: &bpf_insn) -> bool {
@ -498,7 +500,7 @@ mod test {
use alloc::{string::ToString, vec, vec::Vec}; use alloc::{string::ToString, vec, vec::Vec};
use crate::{ use crate::{
maps::{bpf_map_def, BtfMap, BtfMapDef, LegacyMap, Map}, maps::{BtfMap, LegacyMap, Map},
BpfSectionKind, BpfSectionKind,
}; };
@ -568,6 +570,7 @@ mod test {
let relocations = vec![Relocation { let relocations = vec![Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
size: 64,
}]; }];
let maps_by_section = HashMap::new(); let maps_by_section = HashMap::new();
@ -580,7 +583,7 @@ mod test {
&maps_by_section, &maps_by_section,
&maps_by_symbol, &maps_by_symbol,
&symbol_table, &symbol_table,
None, &HashSet::new(),
) )
.unwrap(); .unwrap();
@ -615,10 +618,12 @@ mod test {
Relocation { Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
size: 64,
}, },
Relocation { Relocation {
offset: mem::size_of::<bpf_insn>() as u64, offset: mem::size_of::<bpf_insn>() as u64,
symbol_index: 2, symbol_index: 2,
size: 64,
}, },
]; ];
let maps_by_section = HashMap::new(); let maps_by_section = HashMap::new();
@ -636,7 +641,7 @@ mod test {
&maps_by_section, &maps_by_section,
&maps_by_symbol, &maps_by_symbol,
&symbol_table, &symbol_table,
None, &HashSet::new(),
) )
.unwrap(); .unwrap();
@ -665,6 +670,7 @@ mod test {
let relocations = vec![Relocation { let relocations = vec![Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
size: 64,
}]; }];
let maps_by_section = HashMap::new(); let maps_by_section = HashMap::new();
@ -677,7 +683,7 @@ mod test {
&maps_by_section, &maps_by_section,
&maps_by_symbol, &maps_by_symbol,
&symbol_table, &symbol_table,
None, &HashSet::new(),
) )
.unwrap(); .unwrap();
@ -712,10 +718,12 @@ mod test {
Relocation { Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
size: 64,
}, },
Relocation { Relocation {
offset: mem::size_of::<bpf_insn>() as u64, offset: mem::size_of::<bpf_insn>() as u64,
symbol_index: 2, symbol_index: 2,
size: 64,
}, },
]; ];
let maps_by_section = HashMap::new(); let maps_by_section = HashMap::new();
@ -733,7 +741,7 @@ mod test {
&maps_by_section, &maps_by_section,
&maps_by_symbol, &maps_by_symbol,
&symbol_table, &symbol_table,
None, &HashSet::new(),
) )
.unwrap(); .unwrap();

@ -431,11 +431,18 @@ impl<'a> BpfLoader<'a> {
maps.insert(name, map); maps.insert(name, map);
} }
let text_sections = obj
.functions
.keys()
.map(|(section_index, _)| *section_index)
.collect();
obj.relocate_maps( obj.relocate_maps(
maps.iter() maps.iter()
.map(|(s, data)| (s.as_str(), data.fd, &data.obj)), .map(|(s, data)| (s.as_str(), data.fd, &data.obj)),
&text_sections,
)?; )?;
obj.relocate_calls()?; obj.relocate_calls(&text_sections)?;
let programs = obj let programs = obj
.programs .programs

@ -69,14 +69,20 @@ fn use_map_with_rbpf() {
} }
} }
let text_sections = object
.functions
.iter()
.map(|((section_index, _), _)| *section_index)
.collect();
object object
.relocate_maps( .relocate_maps(
maps.iter() maps.iter()
.map(|(s, (fd, map))| (s.as_ref() as &str, Some(*fd), map)), .map(|(s, (fd, map))| (s.as_ref() as &str, Some(*fd), map)),
&text_sections,
) )
.expect("Relocation failed"); .expect("Relocation failed");
// Actually there is no local function call involved. // Actually there is no local function call involved.
object.relocate_calls().unwrap(); object.relocate_calls(&text_sections).unwrap();
// Executes the program // Executes the program
assert_eq!(object.programs.len(), 1); assert_eq!(object.programs.len(), 1);

Loading…
Cancel
Save