|
|
|
@ -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,11 +675,7 @@ impl Object {
|
|
|
|
|
(FuncSecInfo::default(), LineSecInfo::default(), 0, 0)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(Program {
|
|
|
|
|
license: self.license.clone(),
|
|
|
|
|
kernel_version: self.kernel_version,
|
|
|
|
|
section: prog_sec,
|
|
|
|
|
function: Function {
|
|
|
|
|
let function = Function {
|
|
|
|
|
name,
|
|
|
|
|
address: section.address,
|
|
|
|
|
section_index: section.index,
|
|
|
|
@ -679,8 +685,18 @@ impl Object {
|
|
|
|
|
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
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|