Skip to content

modernize error handling #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ edition = '2018'
[dependencies]
bcc-sys = "0.13.0"
byteorder = "1.3.4"
failure = "0.1.7"
libc = "0.2.68"
regex = "1.3.5"
thiserror = "1.0.19"

[dev-dependencies]
clap = "2.33.0"
Expand Down
5 changes: 2 additions & 3 deletions examples/biosnoop.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bcc::core::BPF;
use bcc::perf::init_perf_map;
use bcc::BccError;
use clap::{App, Arg};
use failure::Error;

use core::sync::atomic::{AtomicBool, Ordering};
use std::ptr;
Expand All @@ -24,7 +24,7 @@ struct data_t {
name: [u8; 16],
}

fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
let matches = App::new("biosnoop")
.about("Trace block I/O")
.arg(
Expand Down Expand Up @@ -134,7 +134,6 @@ fn main() {

if let Err(x) = do_main(runnable) {
eprintln!("Error: {}", x);
eprintln!("{}", x.backtrace());
std::process::exit(1);
}
}
10 changes: 2 additions & 8 deletions examples/opensnoop.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
extern crate bcc;
extern crate byteorder;
extern crate failure;
extern crate libc;

use bcc::core::BPF;
use bcc::perf::init_perf_map;
use bcc::BccError;
use clap::{App, Arg};
use failure::Error;

use core::sync::atomic::{AtomicBool, Ordering};
use std::ptr;
Expand Down Expand Up @@ -34,7 +29,7 @@ struct data_t {
fname: [u8; 255], // NAME_MAX
}

fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
let matches = App::new("opensnoop")
.about("Prints out filename + PID every time a file is opened")
.arg(
Expand Down Expand Up @@ -112,7 +107,6 @@ fn main() {
match do_main(runnable) {
Err(x) => {
eprintln!("Error: {}", x);
eprintln!("{}", x.backtrace());
std::process::exit(1);
}
_ => {}
Expand Down
7 changes: 3 additions & 4 deletions examples/runqlat.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bcc::core::BPF;
use bcc::BccError;
use clap::{App, Arg};
use failure::Error;

use core::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
Expand All @@ -23,7 +23,7 @@ fn attach_events(bpf: &mut BPF) {
.unwrap();
}

#[cfg(any(not(feature = "v0_4_0"), not(feature = "v0_5_0"),))]
#[cfg(not(any(feature = "v0_4_0", feature = "v0_5_0")))]
fn attach_events(bpf: &mut BPF) {
if bpf.support_raw_tracepoint() {
let raw_tp_sched_wakeup = bpf.load_raw_tracepoint("raw_tp__sched_wakeup").unwrap();
Expand All @@ -50,7 +50,7 @@ fn attach_events(bpf: &mut BPF) {
}
}

fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
let matches = App::new("runqlat")
.about("Reports distribution of scheduler latency")
.arg(
Expand Down Expand Up @@ -131,7 +131,6 @@ fn main() {
match do_main(runnable) {
Err(x) => {
eprintln!("Error: {}", x);
eprintln!("{}", x.backtrace());
std::process::exit(1);
}
_ => {}
Expand Down
6 changes: 3 additions & 3 deletions examples/softirqs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use bcc::core::BPF;
use bcc::BccError;
use clap::{App, Arg};
use failure::Error;
use std::error::Error;

use core::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
Expand Down Expand Up @@ -73,7 +74,7 @@ impl fmt::Display for SoftIRQ {
}
}

fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
let matches = App::new("softirqs")
.about("Reports time spent in IRQ Handlers")
.arg(
Expand Down Expand Up @@ -169,7 +170,6 @@ fn main() {
match do_main(runnable) {
Err(x) => {
eprintln!("Error: {}", x);
eprintln!("{}", x.backtrace());
std::process::exit(1);
}
_ => {}
Expand Down
6 changes: 2 additions & 4 deletions examples/strlen.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
extern crate bcc;
extern crate byteorder;
extern crate failure;
extern crate libc;

use bcc::core::BPF;
use bcc::BccError;
use byteorder::{NativeEndian, ReadBytesExt};
use failure::Error;

use core::sync::atomic::{AtomicBool, Ordering};
use std::io::Cursor;
use std::sync::Arc;

fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
let code = "
#include <uapi/linux/ptrace.h>

Expand Down Expand Up @@ -75,7 +74,6 @@ fn main() {
match do_main(runnable) {
Err(x) => {
eprintln!("Error: {}", x);
eprintln!("{}", x.backtrace());
std::process::exit(1);
}
_ => {}
Expand Down
10 changes: 4 additions & 6 deletions examples/tcpretrans.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use bcc::core::BPF;
extern crate chrono;
use bcc::BccError;
use chrono::Utc;
use clap::{App, Arg};
use failure::Error;

use core::sync::atomic::{AtomicBool, Ordering};
use std::net::Ipv4Addr;
Expand Down Expand Up @@ -38,7 +37,7 @@ struct ipv6_data_t {
type_: u64,
}

fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
let matches = App::new("biosnoop")
.arg(
Arg::with_name("duration")
Expand Down Expand Up @@ -81,7 +80,7 @@ fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
Ok(())
}

fn print_ipv4_event() -> Box<FnMut(&[u8]) + Send> {
fn print_ipv4_event() -> Box<dyn FnMut(&[u8]) + Send> {
Box::new(|x| {
let event = parse_ipv4_struct(x);
println!(
Expand All @@ -97,7 +96,7 @@ fn print_ipv4_event() -> Box<FnMut(&[u8]) + Send> {
})
}

fn print_ipv6_event() -> Box<FnMut(&[u8]) + Send> {
fn print_ipv6_event() -> Box<dyn FnMut(&[u8]) + Send> {
Box::new(|x| {
let event = parse_ipv6_struct(x);
println!(
Expand Down Expand Up @@ -131,7 +130,6 @@ fn main() {

if let Err(x) = do_main(runnable) {
eprintln!("Error: {}", x);
eprintln!("{}", x.backtrace());
std::process::exit(1);
}
}
37 changes: 20 additions & 17 deletions src/core/kprobe/v0_4_0.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
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::*;

use crate::core::make_alphanumeric;
use crate::types::MutPointer;
use crate::BccError;

use regex::Regex;

Expand All @@ -23,11 +23,9 @@ 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))?;
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, BccError> {
let cname = CString::new(name)?;
let cfunction = CString::new(function)?;
let (pid, cpu, group_fd) = (-1, 0, -1);
let ptr = unsafe {
bpf_attach_kprobe(
Expand All @@ -43,7 +41,15 @@ impl Kprobe {
)
};
if ptr.is_null() {
Err(format_err!("Failed to attach Kprobe: {}", name))
match attach_type {
BPF_PROBE_ENTRY => Err(BccError::AttachKprobe {
name: name.to_string(),
}),
BPF_PROBE_RETURN => Err(BccError::AttachKretprobe {
name: name.to_string(),
}),
_ => unreachable!(),
}
} else {
Ok(Self {
p: ptr,
Expand All @@ -53,19 +59,17 @@ impl Kprobe {
}
}

pub fn attach_kprobe(function: &str, code: File) -> Result<Self, Error> {
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, BccError> {
let name = format!("p_{}", &make_alphanumeric(function));
Kprobe::new(&name, BPF_PROBE_ENTRY, function, code)
.map_err(|_| format_err!("Failed to attach Kprobe: {}", name))
}

pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, Error> {
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, BccError> {
let name = format!("r_{}", &make_alphanumeric(function));
Kprobe::new(&name, BPF_PROBE_RETURN, function, code)
.map_err(|_| format_err!("Failed to attach Kretprobe: {}", name))
}

pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, Error> {
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, BccError> {
let mut fns: Vec<String> = vec![];

enum Section {
Expand Down Expand Up @@ -117,19 +121,18 @@ impl Kprobe {
Section::End => (),
}
// All functions defined as NOKPROBE_SYMBOL() start with the
// prefix _kbl_addr_*, blacklisting them by looking at the name
// prefix _kbl_addr_*, excluding them by looking at the name
// allows to catch also those symbols that are defined in kernel
// modules.
if fname.starts_with("_kbl_addr_") {
continue;
}
// Explicitly blacklist perf-related functions, they are all
// non-attachable.
else if fname.starts_with("__perf") || fname.starts_with("perf_") {
// Exclude perf-related functions, they are all non-attachable.
if fname.starts_with("__perf") || fname.starts_with("perf_") {
continue;
}
// Exclude all gcc 8's extra .cold functions
else if re.is_match(fname) {
if re.is_match(fname) {
continue;
}
if (t == "t" || t == "w") && fname.contains(event_re) {
Expand Down
37 changes: 20 additions & 17 deletions src/core/kprobe/v0_6_0.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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::*;

use crate::core::make_alphanumeric;
use crate::BccError;

use regex::Regex;

Expand All @@ -21,11 +21,9 @@ 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))?;
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, BccError> {
let cname = CString::new(name)?;
let cfunction = CString::new(function)?;
let ptr = unsafe {
bpf_attach_kprobe(
code.as_raw_fd(),
Expand All @@ -36,7 +34,15 @@ impl Kprobe {
)
};
if ptr < 0 {
Err(format_err!("Failed to attach Kprobe: {}", name))
match attach_type {
BPF_PROBE_ENTRY => Err(BccError::AttachKprobe {
name: name.to_string(),
}),
BPF_PROBE_RETURN => Err(BccError::AttachKretprobe {
name: name.to_string(),
}),
_ => unreachable!(),
}
} else {
Ok(Self {
p: ptr,
Expand All @@ -46,19 +52,17 @@ impl Kprobe {
}
}

pub fn attach_kprobe(function: &str, code: File) -> Result<Self, Error> {
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, BccError> {
let name = format!("p_{}", &make_alphanumeric(function));
Kprobe::new(&name, BPF_PROBE_ENTRY, function, code)
.map_err(|_| format_err!("Failed to attach Kprobe: {}", name))
}

pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, Error> {
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, BccError> {
let name = format!("r_{}", &make_alphanumeric(function));
Kprobe::new(&name, BPF_PROBE_RETURN, function, code)
.map_err(|_| format_err!("Failed to attach Kretprobe: {}", name))
}

pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, Error> {
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, BccError> {
let mut fns: Vec<String> = vec![];

enum Section {
Expand Down Expand Up @@ -110,19 +114,18 @@ impl Kprobe {
Section::End => (),
}
// All functions defined as NOKPROBE_SYMBOL() start with the
// prefix _kbl_addr_*, blacklisting them by looking at the name
// prefix _kbl_addr_*, excluding them by looking at the name
// allows to catch also those symbols that are defined in kernel
// modules.
if fname.starts_with("_kbl_addr_") {
continue;
}
// Explicitly blacklist perf-related functions, they are all
// non-attachable.
else if fname.starts_with("__perf") || fname.starts_with("perf_") {
// Exclude perf-related functions, they are all non-attachable.
if fname.starts_with("__perf") || fname.starts_with("perf_") {
continue;
}
// Exclude all gcc 8's extra .cold functions
else if re.is_match(fname) {
if re.is_match(fname) {
continue;
}
if (t == "t" || t == "w") && fname.contains(event_re) {
Expand Down
Loading