|
@@ -2,6 +2,7 @@
|
|
|
|
|
|
use alloc::{
|
|
|
borrow::ToOwned,
|
|
|
+ collections::BTreeMap,
|
|
|
ffi::CString,
|
|
|
string::{String, ToString},
|
|
|
vec::Vec,
|
|
@@ -67,10 +68,10 @@ pub struct Object {
|
|
|
/// in [ProgramSection]s as keys.
|
|
|
pub programs: HashMap<String, Program>,
|
|
|
/// Functions
|
|
|
- pub functions: HashMap<(usize, u64), Function>,
|
|
|
+ pub functions: BTreeMap<(usize, u64), Function>,
|
|
|
pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
|
|
|
pub(crate) symbol_table: HashMap<usize, Symbol>,
|
|
|
- pub(crate) section_sizes: HashMap<String, u64>,
|
|
|
+ pub(crate) section_infos: HashMap<String, (SectionIndex, u64)>,
|
|
|
// symbol_offset_by_name caches symbols that could be referenced from a
|
|
|
// BTF VAR type so the offsets can be fixed up
|
|
|
pub(crate) symbol_offset_by_name: HashMap<String, u64>,
|
|
@@ -85,8 +86,17 @@ pub struct Program {
|
|
|
pub kernel_version: KernelVersion,
|
|
|
/// The section containing the program
|
|
|
pub section: ProgramSection,
|
|
|
- /// The function
|
|
|
- pub function: Function,
|
|
|
+ /// The section index of the program
|
|
|
+ pub section_index: usize,
|
|
|
+ /// The address of the program
|
|
|
+ pub address: u64,
|
|
|
+}
|
|
|
+
|
|
|
+impl Program {
|
|
|
+ /// The key used by [Object::functions]
|
|
|
+ pub fn function_key(&self) -> (usize, u64) {
|
|
|
+ (self.section_index, self.address)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// An eBPF function
|
|
@@ -578,10 +588,10 @@ impl Object {
|
|
|
btf_ext: None,
|
|
|
maps: HashMap::new(),
|
|
|
programs: HashMap::new(),
|
|
|
- functions: HashMap::new(),
|
|
|
+ functions: BTreeMap::new(),
|
|
|
relocations: HashMap::new(),
|
|
|
symbol_table: HashMap::new(),
|
|
|
- section_sizes: HashMap::new(),
|
|
|
+ section_infos: HashMap::new(),
|
|
|
symbol_offset_by_name: HashMap::new(),
|
|
|
}
|
|
|
}
|
|
@@ -647,7 +657,7 @@ impl Object {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- fn parse_program(&self, section: &Section) -> Result<Program, ParseError> {
|
|
|
+ fn parse_program(&self, section: &Section) -> Result<(Program, Function), ParseError> {
|
|
|
let prog_sec = ProgramSection::from_str(section.name)?;
|
|
|
let name = prog_sec.name().to_owned();
|
|
|
|
|
@@ -665,22 +675,28 @@ impl Object {
|
|
|
(FuncSecInfo::default(), LineSecInfo::default(), 0, 0)
|
|
|
};
|
|
|
|
|
|
- Ok(Program {
|
|
|
- license: self.license.clone(),
|
|
|
- kernel_version: self.kernel_version,
|
|
|
- section: prog_sec,
|
|
|
- function: Function {
|
|
|
- name,
|
|
|
- address: section.address,
|
|
|
- section_index: section.index,
|
|
|
- section_offset: 0,
|
|
|
- instructions: copy_instructions(section.data)?,
|
|
|
- func_info,
|
|
|
- line_info,
|
|
|
- func_info_rec_size,
|
|
|
- line_info_rec_size,
|
|
|
+ let function = Function {
|
|
|
+ name,
|
|
|
+ address: section.address,
|
|
|
+ section_index: section.index,
|
|
|
+ section_offset: 0,
|
|
|
+ instructions: copy_instructions(section.data)?,
|
|
|
+ func_info,
|
|
|
+ line_info,
|
|
|
+ func_info_rec_size,
|
|
|
+ line_info_rec_size,
|
|
|
+ };
|
|
|
+
|
|
|
+ Ok((
|
|
|
+ Program {
|
|
|
+ license: self.license.clone(),
|
|
|
+ kernel_version: self.kernel_version,
|
|
|
+ section: prog_sec,
|
|
|
+ section_index: function.section_index.0,
|
|
|
+ address: function.address,
|
|
|
},
|
|
|
- })
|
|
|
+ function,
|
|
|
+ ))
|
|
|
}
|
|
|
|
|
|
fn parse_text_section(&mut self, section: Section) -> Result<(), ParseError> {
|
|
@@ -829,8 +845,8 @@ impl Object {
|
|
|
{
|
|
|
parts.push(parts[0]);
|
|
|
}
|
|
|
- self.section_sizes
|
|
|
- .insert(section.name.to_owned(), section.size);
|
|
|
+ self.section_infos
|
|
|
+ .insert(section.name.to_owned(), (section.index, section.size));
|
|
|
match section.kind {
|
|
|
BpfSectionKind::Data | BpfSectionKind::Rodata | BpfSectionKind::Bss => {
|
|
|
self.maps
|
|
@@ -876,7 +892,8 @@ impl Object {
|
|
|
res?
|
|
|
}
|
|
|
BpfSectionKind::Program => {
|
|
|
- let program = self.parse_program(§ion)?;
|
|
|
+ let (program, function) = self.parse_program(§ion)?;
|
|
|
+ self.functions.insert(program.function_key(), function);
|
|
|
self.programs
|
|
|
.insert(program.section.name().to_owned(), program);
|
|
|
if !section.relocations.is_empty() {
|
|
@@ -896,10 +913,10 @@ impl Object {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- /// Sanitize BPF programs.
|
|
|
- pub fn sanitize_programs(&mut self, features: &Features) {
|
|
|
- for program in self.programs.values_mut() {
|
|
|
- program.sanitize(features);
|
|
|
+ /// Sanitize BPF functions.
|
|
|
+ pub fn sanitize_functions(&mut self, features: &Features) {
|
|
|
+ for function in self.functions.values_mut() {
|
|
|
+ function.sanitize(features);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -919,9 +936,9 @@ const BPF_FUNC_PROBE_READ_KERNEL: i32 = 113;
|
|
|
const BPF_FUNC_PROBE_READ_USER_STR: i32 = 114;
|
|
|
const BPF_FUNC_PROBE_READ_KERNEL_STR: i32 = 115;
|
|
|
|
|
|
-impl Program {
|
|
|
+impl Function {
|
|
|
fn sanitize(&mut self, features: &Features) {
|
|
|
- for inst in &mut self.function.instructions {
|
|
|
+ for inst in &mut self.instructions {
|
|
|
if !insn_is_helper_call(inst) {
|
|
|
continue;
|
|
|
}
|
|
@@ -1679,17 +1696,17 @@ mod tests {
|
|
|
|
|
|
assert_matches!(
|
|
|
obj.parse_program(&fake_section(BpfSectionKind::Program,"kprobe/foo", bytes_of(&fake_ins()))),
|
|
|
- Ok(Program {
|
|
|
+ Ok((Program {
|
|
|
license,
|
|
|
kernel_version: KernelVersion::Any,
|
|
|
section: ProgramSection::KProbe { .. },
|
|
|
- function: Function {
|
|
|
+ .. }, Function {
|
|
|
name,
|
|
|
address: 0,
|
|
|
section_index: SectionIndex(0),
|
|
|
section_offset: 0,
|
|
|
instructions,
|
|
|
- ..} }) if license.to_string_lossy() == "GPL" && name == "foo" && instructions.len() == 1
|
|
|
+ ..})) if license.to_string_lossy() == "GPL" && name == "foo" && instructions.len() == 1
|
|
|
);
|
|
|
}
|
|
|
|