Skip to content

Commit

Permalink
improve: allow using bpftool for stripping
Browse files Browse the repository at this point in the history
Also skip stripping if failed.

Add env EINAT_BPF_STRIP_CMD to force stripping command used.
  • Loading branch information
EHfive committed Dec 9, 2024
1 parent 3c02106 commit 63a43b2
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 16 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ For implementation details, see documentations under [reference](./docs/referenc
- Linux kernel >= 5.15 (compiled with BPF and BTF support) on target machine
- Rust toolchain (`cargo` etc.)
- `clang` for compiling BPF C code
- `llvm-strip` for stripping compiled BPF object
- `bpftool` or `llvm-strip` for stripping compiled BPF object
- `libbpf` headers
- (optional) `pkg-config` to locate `libbpf` headers

Additional dependencies for `"libbpf"` loader:

- `rustfmt` for formatting generated code
- `clang` libs for bindgen
- `libelf` from elfutils and `zlib` on target platform
- `libelf` from elfutils and `zlib` on target platform

Currently we support `"aya"`, `"libbpf"` and `"libbpf-skel"` eBPF loaders, only the `"aya"` is enabled by default as it requires no native dependencies on target platform except libc.

Expand Down Expand Up @@ -65,10 +65,11 @@ See also [cross-compilation guide](./docs/guide/cross.md) for cross-compilation

### Build Environment Variables

| Name | Example Value | Note |
| ---------------------- | -------------------------- | ----------------------------------------------- |
| `EINAT_BPF_CFLAGS` | `-I/usr/include/<triplet>` | Specify extra CFLAGS for BPF object compilation |
| `LIBBPF_NO_PKG_CONFIG` | `1` | Disable [pkg_config lookup] of libbpf. |
| Name | Example Value | Note |
| ---------------------- | -------------------------- | --------------------------------------------------------------------------- |
| `EINAT_BPF_CFLAGS` | `-I/usr/include/<triplet>` | Specify extra CFLAGS for BPF object compilation |
| `EINAT_BPF_STRIP_CMD` | `llvm-strip -g -o` | BPF object stripping command, would followed by target path and source path |
| `LIBBPF_NO_PKG_CONFIG` | `1` | Disable [pkg_config lookup] of libbpf. |

[pkg_config lookup]: https://docs.rs/pkg-config/0.3.31/pkg_config/index.html#environment-variables

Expand Down
60 changes: 51 additions & 9 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ fn c_args() -> Vec<String> {

#[cfg(any(feature = "aya", feature = "libbpf"))]
fn einat_obj_build() {
use std::ffi::OsStr;
use std::process::Command;

let bpf_obj_tmp = &out_path("einat.bpf.tmp.o");
let bpf_obj = &out_path("einat.bpf.o");

// compile BPF C code
Expand Down Expand Up @@ -79,22 +81,60 @@ fn einat_obj_build() {
.arg("-c")
.arg(SRC)
.arg("-o")
.arg(bpf_obj)
.arg(bpf_obj_tmp)
.status()
.expect("compile BPF object failed");
if !res.success() {
panic!("{}", res);
}

// strip the DWARF debug information
let res = Command::new("llvm-strip")
.arg("--strip-debug")
.arg(bpf_obj)
.status()
.expect("llvm-strip BPF object file failed");
if !res.success() {
panic!("{}", res);
fn strip_obj<S: AsRef<OsStr>>(strip_cmd: &str, target: S, source: S) -> Result<(), String> {
let mut args = strip_cmd.split_ascii_whitespace();
let cmd = args.next().unwrap();
let res = Command::new(cmd)
.args(args)
.arg(target)
.arg(source)
.status();

match res {
Ok(res) => {
if res.success() {
return Ok(());
}
Err(format!("{}: {}", strip_cmd, res))
}
Err(err) => Err(format!("{}: {}", strip_cmd, err)),
}
}

// strip the DWARF debug information
let strip_bpf_obj = || -> Result<(), String> {
if let Some(strip_cmd) = option_env!("EINAT_BPF_STRIP_CMD") {
return strip_obj(strip_cmd, bpf_obj, bpf_obj_tmp);
}

let res = strip_obj("bpftool gen object", bpf_obj, bpf_obj_tmp);
if res.is_ok() {
return res;
}
eprintln!("strip with bpftool failed, fallback to llvm-strip");

let res = strip_obj("llvm-strip -g -o", bpf_obj, bpf_obj_tmp);
if res.is_ok() {
return res;
}
eprintln!("strip with llvm-strip failed, skip stripping");

std::fs::rename(bpf_obj_tmp, bpf_obj).unwrap();

Ok(())
};

strip_bpf_obj().expect("strip BPF object file failed");

println!("cargo:rerun-if-env-changed=EINAT_BPF_CFLAGS");
println!("cargo:rerun-if-env-changed=EINAT_BPF_STRIP_CMD");
}

#[cfg(feature = "libbpf-skel")]
Expand All @@ -120,4 +160,6 @@ fn main() {

println!("cargo:rerun-if-changed={}", SRC_DIR);
println!("cargo:rerun-if-changed=build.rs");

println!("cargo:rerun-if-changed=/null");
}
7 changes: 6 additions & 1 deletion docs/guide/cross.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ To enable only the "libbpf" loader, specify Cargo flags `--no-default-features -
Install `gcc-aarch64-linux-gnu` for cross linking. Install `clang` for bindgen and compile eBPF C code in this project.

```
apt install gcc-aarch64-linux-gnu clang llvm
apt install gcc-aarch64-linux-gnu clang
# bpftool for BPF object stripping
apt install linux-tools-common
# Or use llvm-strip
apt install llvm
```

Install `rustup` to get Rust>=1.74, see https://www.rust-lang.org/tools/install. Also make sure `rustfmt` is installed as it's used by `libbpf-cargo`.
Expand Down Expand Up @@ -47,6 +51,7 @@ export CFLAGS_aarch64_unknown_linux_gnu="-I /usr/include/aarch64-linux-gnu -L /u
```

Specify `EINAT_BPF_CFLAGS` if einat build script failed to locate libbpf headers.

```
export EINAT_BPF_CFLAGS="-I /usr/include/aarch64-linux-gnu"
```
Expand Down

0 comments on commit 63a43b2

Please sign in to comment.