mirror of https://github.com/rust-bpf/rust-bcc
rustfmt: format the codebase with modern rustfmt (#31)
* update the rustfmt config to reflect current options * run modern rustfmt to enforce style on the current codebase
This commit is contained in:
parent
e39f499769
commit
60c5459cfd
|
@ -1,7 +1,7 @@
|
|||
extern crate bcc;
|
||||
extern crate byteorder;
|
||||
extern crate libc;
|
||||
extern crate failure;
|
||||
extern crate libc;
|
||||
|
||||
use std::ptr;
|
||||
|
||||
|
@ -16,7 +16,7 @@ use failure::Error;
|
|||
* Prints out the filename + PID every time a file is opened
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Define the struct the BPF code writes in Rust
|
||||
* This must match the struct in `opensnoop.c` exactly.
|
||||
* The important thing to understand about the code in `opensnoop.c` is that it creates structs of
|
||||
|
@ -27,7 +27,7 @@ struct data_t {
|
|||
id: u64,
|
||||
ts: u64,
|
||||
ret: libc::c_int,
|
||||
comm: [u8; 16], // TASK_COMM_LEN
|
||||
comm: [u8; 16], // TASK_COMM_LEN
|
||||
fname: [u8; 255], // NAME_MAX
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,12 @@ fn perf_data_callback() -> Box<FnMut(&[u8]) + Send> {
|
|||
Box::new(|x| {
|
||||
// This callback
|
||||
let data = parse_struct(x);
|
||||
println!("{:-7} {:-16} {}", data.id >> 32, get_string(&data.comm), get_string(&data.fname));
|
||||
println!(
|
||||
"{:-7} {:-16} {}",
|
||||
data.id >> 32,
|
||||
get_string(&data.comm),
|
||||
get_string(&data.fname)
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
extern crate bcc;
|
||||
extern crate byteorder;
|
||||
extern crate libc;
|
||||
extern crate failure;
|
||||
extern crate libc;
|
||||
|
||||
use bcc::core::BPF;
|
||||
use failure::Error;
|
||||
|
@ -12,7 +12,6 @@ use std::{fmt, mem, ptr, thread, time};
|
|||
//
|
||||
// Based on: https://github.com/iovisor/bcc/blob/master/tools/softirqs.py
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
struct irq_key_t {
|
||||
vec: u32,
|
||||
|
@ -107,7 +106,6 @@ fn do_main() -> Result<(), Error> {
|
|||
let softirq = SoftIRQ::from(id);
|
||||
println!("softirq: {} time (ns): {}", softirq, time);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
extern crate bcc;
|
||||
extern crate byteorder;
|
||||
extern crate libc;
|
||||
extern crate failure;
|
||||
extern crate libc;
|
||||
|
||||
use byteorder::{NativeEndian, ReadBytesExt};
|
||||
use bcc::core::BPF;
|
||||
use byteorder::{NativeEndian, ReadBytesExt};
|
||||
use failure::Error;
|
||||
use std::io::Cursor;
|
||||
|
||||
|
@ -32,12 +32,17 @@ int count(struct pt_regs *ctx) {
|
|||
";
|
||||
let mut module = BPF::new(code)?;
|
||||
let uprobe_code = module.load_uprobe("count")?;
|
||||
module.attach_uprobe("/lib/x86_64-linux-gnu/libc.so.6", "strlen", uprobe_code, -1 /* all PIDs */)?;
|
||||
module.attach_uprobe(
|
||||
"/lib/x86_64-linux-gnu/libc.so.6",
|
||||
"strlen",
|
||||
uprobe_code,
|
||||
-1, /* all PIDs */
|
||||
)?;
|
||||
let table = module.table("counts");
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
for e in &table {
|
||||
// key and value are each a Vec<u8> so we need to transform them into a string and
|
||||
// key and value are each a Vec<u8> so we need to transform them into a string and
|
||||
// a u64 respectively
|
||||
let key = get_string(&e.key);
|
||||
let value = Cursor::new(e.value).read_u64::<NativeEndian>().unwrap();
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
reorder_imports = true
|
||||
reorder_imported_names = true
|
||||
reorder_modules = true
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
|
@ -1,7 +1,7 @@
|
|||
use failure::Error;
|
||||
use bcc_sys::bccapi::*;
|
||||
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_ENTRY as BPF_PROBE_ENTRY;
|
||||
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_RETURN as BPF_PROBE_RETURN;
|
||||
use bcc_sys::bccapi::*;
|
||||
use failure::Error;
|
||||
|
||||
use core::make_alphanumeric;
|
||||
use types::MutPointer;
|
||||
|
@ -21,12 +21,10 @@ pub struct Kprobe {
|
|||
|
||||
impl Kprobe {
|
||||
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, Error> {
|
||||
let cname = CString::new(name).map_err(|_| {
|
||||
format_err!("Nul byte in Kprobe name: {}", name)
|
||||
})?;
|
||||
let cfunction = CString::new(function).map_err(|_| {
|
||||
format_err!("Nul byte in Kprobe function: {}", function)
|
||||
})?;
|
||||
let cname =
|
||||
CString::new(name).map_err(|_| format_err!("Nul byte in Kprobe name: {}", name))?;
|
||||
let cfunction = CString::new(function)
|
||||
.map_err(|_| format_err!("Nul byte in Kprobe function: {}", function))?;
|
||||
let (pid, cpu, group_fd) = (-1, 0, -1);
|
||||
let ptr = unsafe {
|
||||
bpf_attach_kprobe(
|
||||
|
|
|
@ -2,8 +2,8 @@ mod kprobe;
|
|||
mod tracepoint;
|
||||
mod uprobe;
|
||||
|
||||
use failure::Error;
|
||||
use bcc_sys::bccapi::*;
|
||||
use failure::Error;
|
||||
|
||||
use self::kprobe::Kprobe;
|
||||
use self::tracepoint::Tracepoint;
|
||||
|
@ -27,17 +27,17 @@ pub struct BPF {
|
|||
}
|
||||
|
||||
fn make_alphanumeric(s: &str) -> String {
|
||||
s.replace(|c| {
|
||||
!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
|
||||
}, "_")
|
||||
s.replace(
|
||||
|c| !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')),
|
||||
"_",
|
||||
)
|
||||
}
|
||||
|
||||
impl BPF {
|
||||
/// `code` is a string containing C code. See https://github.com/iovisor/bcc for examples
|
||||
pub fn new(code: &str) -> Result<BPF, Error> {
|
||||
let cs = CString::new(code)?;
|
||||
let ptr =
|
||||
unsafe { bpf_module_create_c_from_string(cs.as_ptr(), 2, ptr::null_mut(), 0) };
|
||||
let ptr = unsafe { bpf_module_create_c_from_string(cs.as_ptr(), 2, ptr::null_mut(), 0) };
|
||||
if ptr.is_null() {
|
||||
return Err(format_err!("couldn't create BPF program"));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use failure::Error;
|
||||
use bcc_sys::bccapi::*;
|
||||
use failure::Error;
|
||||
|
||||
use types::MutPointer;
|
||||
|
||||
|
@ -18,17 +18,11 @@ pub struct Tracepoint {
|
|||
}
|
||||
|
||||
impl Tracepoint {
|
||||
pub fn attach_tracepoint(
|
||||
subsys: &str,
|
||||
name: &str,
|
||||
file: File,
|
||||
) -> Result<Self, Error> {
|
||||
let cname = CString::new(name).map_err(|_| {
|
||||
format_err!("Nul byte in Tracepoint name: {}", name)
|
||||
})?;
|
||||
let csubsys = CString::new(subsys).map_err(|_| {
|
||||
format_err!("Nul byte in Tracepoint subsys: {}", subsys)
|
||||
})?;
|
||||
pub fn attach_tracepoint(subsys: &str, name: &str, file: File) -> Result<Self, Error> {
|
||||
let cname =
|
||||
CString::new(name).map_err(|_| format_err!("Nul byte in Tracepoint name: {}", name))?;
|
||||
let csubsys = CString::new(subsys)
|
||||
.map_err(|_| format_err!("Nul byte in Tracepoint subsys: {}", subsys))?;
|
||||
// NOTE: BPF events are system-wide and do not support CPU filter
|
||||
let (pid, cpu, group_fd) = (-1, 0, -1);
|
||||
let ptr = unsafe {
|
||||
|
@ -44,9 +38,13 @@ impl Tracepoint {
|
|||
)
|
||||
};
|
||||
if ptr.is_null() {
|
||||
return Err(format_err!("Failed to attach tracepoint: {}:{}", subsys, name));
|
||||
return Err(format_err!(
|
||||
"Failed to attach tracepoint: {}:{}",
|
||||
subsys,
|
||||
name
|
||||
));
|
||||
} else {
|
||||
Ok(Self{
|
||||
Ok(Self {
|
||||
subsys: csubsys,
|
||||
name: cname,
|
||||
code_fd: file,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use failure::Error;
|
||||
use bcc_sys::bccapi::*;
|
||||
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_ENTRY as BPF_PROBE_ENTRY;
|
||||
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_RETURN as BPF_PROBE_RETURN;
|
||||
use bcc_sys::bccapi::*;
|
||||
use failure::Error;
|
||||
|
||||
use core::make_alphanumeric;
|
||||
use symbol;
|
||||
|
@ -29,12 +29,10 @@ impl Uprobe {
|
|||
file: File,
|
||||
pid: pid_t,
|
||||
) -> Result<Self, Error> {
|
||||
let cname = CString::new(name).map_err(|_| {
|
||||
format_err!("Nul byte in Uprobe name: {}", name)
|
||||
})?;
|
||||
let cpath = CString::new(path).map_err(|_| {
|
||||
format_err!("Nul byte in Uprobe path: {}", name)
|
||||
})?;
|
||||
let cname =
|
||||
CString::new(name).map_err(|_| format_err!("Nul byte in Uprobe name: {}", name))?;
|
||||
let cpath =
|
||||
CString::new(path).map_err(|_| format_err!("Nul byte in Uprobe path: {}", name))?;
|
||||
// TODO: maybe pass in the CPU & PID instead of
|
||||
let (cpu, group_fd) = (0, -1);
|
||||
let uprobe_ptr = unsafe {
|
||||
|
@ -54,7 +52,7 @@ impl Uprobe {
|
|||
if uprobe_ptr.is_null() {
|
||||
return Err(format_err!("Failed to attach Uprobe: {}", name));
|
||||
} else {
|
||||
Ok(Self{
|
||||
Ok(Self {
|
||||
code_fd: file,
|
||||
name: cname,
|
||||
p: uprobe_ptr,
|
||||
|
@ -62,7 +60,12 @@ impl Uprobe {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn attach_uprobe(binary_path: &str, symbol: &str, code: File, pid: pid_t) -> Result<Self, Error> {
|
||||
pub fn attach_uprobe(
|
||||
binary_path: &str,
|
||||
symbol: &str,
|
||||
code: File,
|
||||
pid: pid_t,
|
||||
) -> Result<Self, Error> {
|
||||
let (path, addr) = symbol::resolve_symbol_path(binary_path, symbol, 0x0, pid)?;
|
||||
let alpha_path = make_alphanumeric(&path);
|
||||
let ev_name = format!("r_{}_0x{:x}", &alpha_path, addr);
|
||||
|
@ -70,7 +73,12 @@ impl Uprobe {
|
|||
.map_err(|_| format_err!("Failed to attach Uprobe to binary: {}", binary_path))
|
||||
}
|
||||
|
||||
pub fn attach_uretprobe(binary_path: &str, symbol: &str, code: File, pid: pid_t) -> Result<Self, Error> {
|
||||
pub fn attach_uretprobe(
|
||||
binary_path: &str,
|
||||
symbol: &str,
|
||||
code: File,
|
||||
pid: pid_t,
|
||||
) -> Result<Self, Error> {
|
||||
let (path, addr) = symbol::resolve_symbol_path(binary_path, symbol, 0x0, pid)?;
|
||||
let alpha_path = make_alphanumeric(&path);
|
||||
let ev_name = format!("r_{}_0x{:x}", &alpha_path, addr);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fs::File;
|
||||
use std::str::FromStr;
|
||||
use std::io::Read;
|
||||
use failure::Error;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::str::FromStr;
|
||||
|
||||
const CPUONLINE: &'static str = "/sys/devices/system/cpu/online";
|
||||
|
||||
|
@ -48,51 +48,51 @@ mod tests {
|
|||
|
||||
lazy_static! {
|
||||
static ref TEST: Vec<TestData<'static>> = vec![
|
||||
TestData {
|
||||
data: "",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "0-3\n",
|
||||
expected: vec!{0, 1, 2, 3},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: " 0-2,5",
|
||||
expected: vec!{0, 1, 2, 5},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "0,2,4-5,7-9",
|
||||
expected: vec!{0, 2, 4, 5, 7, 8, 9},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "0,2",
|
||||
expected: vec!{0, 2},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "0",
|
||||
expected: vec!{0},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "-2,5",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "2-@,5",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "-",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "0-3\n",
|
||||
expected: vec!{0, 1, 2, 3},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: " 0-2,5",
|
||||
expected: vec!{0, 1, 2, 5},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "0,2,4-5,7-9",
|
||||
expected: vec!{0, 2, 4, 5, 7, 8, 9},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "0,2",
|
||||
expected: vec!{0, 2},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "0",
|
||||
expected: vec!{0},
|
||||
valid: true,
|
||||
},
|
||||
TestData {
|
||||
data: "-2,5",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "2-@,5",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
TestData {
|
||||
data: "-",
|
||||
expected: Vec::new(),
|
||||
valid: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
#[test]
|
||||
|
|
|
@ -8,16 +8,17 @@
|
|||
//! * see <https://github.com/jvns/rust-bcc/examples>
|
||||
|
||||
pub mod core;
|
||||
pub mod symbol;
|
||||
mod cpuonline;
|
||||
pub mod perf;
|
||||
pub mod symbol;
|
||||
pub mod table;
|
||||
mod types;
|
||||
mod cpuonline;
|
||||
|
||||
#[macro_use]
|
||||
extern crate failure;
|
||||
extern crate libc;
|
||||
extern crate bcc_sys;
|
||||
extern crate byteorder;
|
||||
#[cfg(test)] #[macro_use]
|
||||
extern crate libc;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
|
27
src/perf.rs
27
src/perf.rs
|
@ -1,15 +1,15 @@
|
|||
extern crate libc;
|
||||
use bcc_sys::bccapi::*;
|
||||
use byteorder::{NativeEndian, WriteBytesExt};
|
||||
use cpuonline;
|
||||
use failure::Error;
|
||||
use failure::ResultExt;
|
||||
use byteorder::{NativeEndian, WriteBytesExt};
|
||||
use bcc_sys::bccapi::*;
|
||||
use cpuonline;
|
||||
|
||||
use std;
|
||||
use std::io::Cursor;
|
||||
|
||||
use types::*;
|
||||
use table::Table;
|
||||
use types::*;
|
||||
|
||||
struct PerfCallback {
|
||||
raw_cb: Box<FnMut(&[u8]) + Send>,
|
||||
|
@ -21,9 +21,7 @@ unsafe extern "C" fn raw_callback(pc: MutPointer, ptr: MutPointer, size: i32) {
|
|||
let slice = std::slice::from_raw_parts(ptr as *const u8, size as usize);
|
||||
// prevent unwinding into C code
|
||||
// no custom panic hook set, panic will be printed as is
|
||||
let _ = std::panic::catch_unwind(|| {
|
||||
(*(*(pc as *mut PerfCallback)).raw_cb)(slice)
|
||||
});
|
||||
let _ = std::panic::catch_unwind(|| (*(*(pc as *mut PerfCallback)).raw_cb)(slice));
|
||||
}
|
||||
|
||||
// need this to be represented in memory as just a pointer!!
|
||||
|
@ -81,9 +79,9 @@ where
|
|||
callbacks.push(callback);
|
||||
|
||||
cur.write_u32::<NativeEndian>(perf_fd)?;
|
||||
table.set(&mut key, &mut cur.get_mut()).context(
|
||||
"Unable to initialize perf map",
|
||||
)?;
|
||||
table
|
||||
.set(&mut key, &mut cur.get_mut())
|
||||
.context("Unable to initialize perf map")?;
|
||||
let r = bpf_get_next_key(
|
||||
fd,
|
||||
key.as_mut_ptr() as MutPointer,
|
||||
|
@ -118,7 +116,7 @@ fn open_perf_buffer(
|
|||
cpu: usize,
|
||||
raw_cb: Box<FnMut(&[u8]) + Send>,
|
||||
) -> Result<(PerfReader, Box<PerfCallback>), Error> {
|
||||
let mut callback = Box::new(PerfCallback { raw_cb: raw_cb });
|
||||
let mut callback = Box::new(PerfCallback { raw_cb });
|
||||
let reader = unsafe {
|
||||
bpf_open_perf_buffer(
|
||||
Some(raw_callback),
|
||||
|
@ -132,5 +130,10 @@ fn open_perf_buffer(
|
|||
if reader.is_null() {
|
||||
return Err(format_err!("failed to open perf buffer"));
|
||||
}
|
||||
Ok((PerfReader { ptr: reader as *mut perf_reader }, callback))
|
||||
Ok((
|
||||
PerfReader {
|
||||
ptr: reader as *mut perf_reader,
|
||||
},
|
||||
callback,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use failure::Error;
|
||||
use bcc_sys::bccapi::*;
|
||||
use failure::Error;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::ffi::CString;
|
||||
use std::ffi::CStr;
|
||||
|
||||
use libc::{c_void, free};
|
||||
|
||||
|
@ -51,11 +51,13 @@ pub fn resolve_symname(
|
|||
))
|
||||
} else {
|
||||
let module = unsafe {
|
||||
CStr::from_ptr(symbol.module as *mut i8).to_str()?.to_string()
|
||||
CStr::from_ptr(symbol.module as *mut i8)
|
||||
.to_str()?
|
||||
.to_string()
|
||||
};
|
||||
// symbol.module was allocated somewhere inside `bcc_resolve_symname`
|
||||
// so we need to free it manually
|
||||
unsafe {free(symbol.module as *mut c_void)};
|
||||
unsafe { free(symbol.module as *mut c_void) };
|
||||
Ok((module, symbol.offset))
|
||||
}
|
||||
}
|
||||
|
|
22
src/table.rs
22
src/table.rs
|
@ -1,12 +1,11 @@
|
|||
use libc::{size_t, c_int};
|
||||
use failure::Error;
|
||||
use bcc_sys::bccapi::*;
|
||||
use failure::Error;
|
||||
use libc::{c_int, size_t};
|
||||
|
||||
use types::MutPointer;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std;
|
||||
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Table {
|
||||
|
@ -102,10 +101,10 @@ impl IntoIterator for Table {
|
|||
type Item = Entry;
|
||||
type IntoIter = EntryIter;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
EntryIter{
|
||||
EntryIter {
|
||||
current: None,
|
||||
table: self,
|
||||
fd: None
|
||||
fd: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +123,6 @@ pub struct Entry {
|
|||
pub value: Vec<u8>,
|
||||
}
|
||||
|
||||
|
||||
pub struct EntryIter {
|
||||
current: Option<Entry>,
|
||||
fd: Option<c_int>,
|
||||
|
@ -134,7 +132,10 @@ pub struct EntryIter {
|
|||
impl EntryIter {
|
||||
pub fn entry_ptrs(&mut self) -> Option<(*mut std::os::raw::c_void, *mut std::os::raw::c_void)> {
|
||||
match self.current.as_mut() {
|
||||
Some(&mut Entry{ref mut key, ref mut value}) => Some((
|
||||
Some(&mut Entry {
|
||||
ref mut key,
|
||||
ref mut value,
|
||||
}) => Some((
|
||||
key.as_mut_ptr() as *mut u8 as *mut std::os::raw::c_void,
|
||||
value.as_mut_ptr() as *mut u8 as *mut std::os::raw::c_void,
|
||||
)),
|
||||
|
@ -146,7 +147,10 @@ impl EntryIter {
|
|||
self.fd = Some(self.table.fd());
|
||||
let key_size = self.table.key_size();
|
||||
let leaf_size = self.table.leaf_size();
|
||||
let entry = Entry{key: vec![0; key_size], value: vec![0; leaf_size]};
|
||||
let entry = Entry {
|
||||
key: vec![0; key_size],
|
||||
value: vec![0; leaf_size],
|
||||
};
|
||||
self.current = Some(entry);
|
||||
unsafe {
|
||||
let (k, _) = self.entry_ptrs().unwrap();
|
||||
|
|
Loading…
Reference in New Issue