From 7e6a7d9005618affe6a796d3681d1107abdea380 Mon Sep 17 00:00:00 2001 From: Matteo Nardi Date: Fri, 16 Dec 2022 12:10:35 +0100 Subject: [PATCH 1/5] btf: add integration tests for relocations Add new integrations tests for BTF relocations. --- test/integration-test/Cargo.toml | 1 + test/integration-test/src/tests/mod.rs | 1 + .../integration-test/src/tests/relocations.rs | 226 ++++++++++++++++++ xtask/src/build_ebpf.rs | 1 + 4 files changed, 229 insertions(+) create mode 100644 test/integration-test/src/tests/relocations.rs diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml index 1f1bdf13..5851e414 100644 --- a/test/integration-test/Cargo.toml +++ b/test/integration-test/Cargo.toml @@ -18,3 +18,4 @@ log = "0.4" object = { version = "0.30", default-features = false, features = ["std", "read_core", "elf"] } rbpf = "0.1.0" regex = "1" +tempfile = "3.3.0" diff --git a/test/integration-test/src/tests/mod.rs b/test/integration-test/src/tests/mod.rs index 0b3e9e95..ddb1b504 100644 --- a/test/integration-test/src/tests/mod.rs +++ b/test/integration-test/src/tests/mod.rs @@ -7,6 +7,7 @@ use std::{ffi::CStr, mem}; pub mod elf; pub mod load; pub mod rbpf; +pub mod relocations; pub mod smoke; pub use integration_test_macros::integration_test; diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs new file mode 100644 index 00000000..4778f14f --- /dev/null +++ b/test/integration-test/src/tests/relocations.rs @@ -0,0 +1,226 @@ +use anyhow::{Context, Result}; +use std::{process::Command, thread::sleep, time::Duration}; + +use aya::{maps::Array, programs::TracePoint, BpfLoader, Btf, Endianness}; + +use super::{integration_test, IntegrationTest}; + +#[integration_test] +fn relocate_field() { + let test = RelocationTest { + local_definition: r#" + struct foo { + __u8 a; + __u8 b; + __u8 c; + __u8 d; + } __attribute__((preserve_access_index)); + "#, + target_btf: r#" + struct foo { + __u8 a; + __u8 c; + __u8 b; + __u8 d; + } s1; + "#, + relocation_code: r#" + __u8 memory[] = {1, 2, 3, 4}; + __u32 value = BPF_CORE_READ((struct foo *)&memory, c); + "#, + } + .build() + .unwrap(); + assert_eq!(test.run().unwrap(), 2); + assert_eq!(test.run_no_btf().unwrap(), 3); +} + +#[integration_test] +fn relocate_enum() { + let test = RelocationTest { + local_definition: r#" + enum foo { D = 1 }; + "#, + target_btf: r#" + enum foo { D = 4 } e1; + "#, + relocation_code: r#" + __u32 value = bpf_core_enum_value(enum foo, D); + "#, + } + .build() + .unwrap(); + assert_eq!(test.run().unwrap(), 4); + assert_eq!(test.run_no_btf().unwrap(), 0); +} + +/// Utility code for running relocation tests: +/// - Generates the eBPF program using probided local definition and relocation code +/// - Generates the BTF from the target btf code +struct RelocationTest { + /// Data structure definition, local to the eBPF program and embedded in the eBPF bytecode + local_definition: &'static str, + /// Target data structure definition. What the vmlinux would actually contain. + target_btf: &'static str, + /// Code executed by the eBPF program to test the relocation. + /// The format should be: + // __u8 memory[] = { ... }; + // __u32 value = BPF_CORE_READ((struct foo *)&memory, ...); + // + // The generated code will be executed by attaching a tracepoint to sched_switch + // and emitting `__u32 value` an a map. See the code template below for more details. + relocation_code: &'static str, +} + +impl RelocationTest { + /// Build a RelocationTestRunner + fn build(&self) -> Result { + Ok(RelocationTestRunner { + ebpf: self.build_ebpf()?, + btf: self.build_btf()?, + }) + } + + /// - Generate the source eBPF filling a template + /// - Compile it with clang + fn build_ebpf(&self) -> Result> { + let local_definition = self.local_definition; + let relocation_code = self.relocation_code; + let tmp_dir = tempfile::tempdir().context("Error making temp dir")?; + let ebpf_file = tmp_dir.path().join("ebpf_program.c"); + std::fs::write( + &ebpf_file, + format!( + r#" + #include + + #include + #include + #include + + {local_definition} + + struct {{ + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, __u32); + __type(value, __u32); + __uint(max_entries, 1); + }} output_map SEC(".maps"); + + SEC("tracepoint/bpf_prog") int bpf_prog(void *ctx) {{ + __u32 key = 0; + {relocation_code} + bpf_map_update_elem(&output_map, &key, &value, BPF_ANY); + return 0; + }} + + char _license[] SEC("license") = "GPL"; + "# + ), + ) + .context("Writing bpf program failed")?; + Command::new("clang") + .current_dir(tmp_dir.path()) + .args(["-c", "-g", "-O2", "-target", "bpf"]) + .args([ + "-I", + &std::env::var("LIBBPF_INCLUDE").context("LIBBPF_INCLUDE not set")?, + ]) + .arg(&ebpf_file) + .status() + .context("Failed to run clang")? + .success() + .then_some(()) + .context("Failed to compile eBPF program")?; + let ebpf = std::fs::read(ebpf_file.with_extension("o")) + .context("Error reading compiled eBPF program")?; + Ok(ebpf) + } + + /// - Generate the target BTF source with a mock main() + /// - Compile it with clang + /// - Extract the BTF with pahole + fn build_btf(&self) -> Result { + let target_btf = self.target_btf; + let tmp_dir = tempfile::tempdir().context("Error making temp dir")?; + // BTF files can be generated and inspected with these commands: + // $ clang -c -g -O2 -target bpf target.c + // $ pahole --btf_encode_detached=target.btf -V target.o + // $ bpftool btf dump file ./target.btf format c + let btf_file = tmp_dir.path().join("target_btf.c"); + std::fs::write( + &btf_file, + format!( + r#" + #include + {target_btf} + int main() {{ return 0; }} + "# + ), + ) + .context("Writing bpf program failed")?; + Command::new("clang") + .current_dir(tmp_dir.path()) + .args(["-c", "-g", "-O2", "-target", "bpf"]) + .arg(&btf_file) + .status() + .context("Failed to run clang")? + .success() + .then_some(()) + .context("Failed to compile BTF")?; + Command::new("pahole") + .current_dir(tmp_dir.path()) + .arg("--btf_encode_detached=target.btf") + .arg(btf_file.with_extension("o")) + .status() + .context("Failed to run pahole")? + .success() + .then_some(()) + .context("Failed to extract BTF")?; + let btf = Btf::parse_file(tmp_dir.path().join("target.btf"), Endianness::default()) + .context("Error parsing generated BTF")?; + Ok(btf) + } +} + +struct RelocationTestRunner { + ebpf: Vec, + btf: Btf, +} + +impl RelocationTestRunner { + /// Run test and return the output value + fn run(&self) -> Result { + self.run_internal(true) + } + + /// Run without loading btf + fn run_no_btf(&self) -> Result { + self.run_internal(false) + } + + fn run_internal(&self, with_relocations: bool) -> Result { + let mut loader = BpfLoader::new(); + if with_relocations { + loader.btf(Some(&self.btf)); + } + let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?; + let program: &mut TracePoint = bpf + .program_mut("bpf_prog") + .context("bpf_prog not found")? + .try_into() + .context("program not a tracepoint")?; + program.load().context("Loading tracepoint failed")?; + // Attach to sched_switch and wait some time to make sure it executed at least once + program + .attach("sched", "sched_switch") + .context("attach failed")?; + sleep(Duration::from_millis(1000)); + // To inspect the loaded eBPF bytecode, increse the timeout and run: + // $ sudo bpftool prog dump xlated name bpf_prog + + let output_map: Array<_, u32> = bpf.take_map("output_map").unwrap().try_into().unwrap(); + let key = 0; + output_map.get(&key, 0).context("Getting key 0 failed") + } +} diff --git a/xtask/src/build_ebpf.rs b/xtask/src/build_ebpf.rs index 4f98feba..0d3540e6 100644 --- a/xtask/src/build_ebpf.rs +++ b/xtask/src/build_ebpf.rs @@ -103,6 +103,7 @@ fn build_c_ebpf(opts: &BuildEbpfOptions) -> anyhow::Result<()> { let include_path = out_path.join("include"); get_libbpf_headers(&opts.libbpf_dir, &include_path)?; + std::env::set_var("LIBBPF_INCLUDE", &include_path); let files = fs::read_dir(&src).unwrap(); for file in files { let p = file.unwrap().path(); From b72abcc7ded3ba83bae6da1f3895cf73c8fb0602 Mon Sep 17 00:00:00 2001 From: Matteo Nardi Date: Mon, 19 Dec 2022 14:21:18 +0100 Subject: [PATCH 2/5] tests: add pointer relocation test --- .../integration-test/src/tests/relocations.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 4778f14f..2654dff6 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -54,6 +54,25 @@ fn relocate_enum() { assert_eq!(test.run_no_btf().unwrap(), 0); } +#[integration_test] +fn relocate_pointer() { + let test = RelocationTest { + local_definition: r#" + struct foo {}; + struct bar { struct foo *f; }; + "#, + target_btf: r#""#, + relocation_code: r#" + __u8 memory[] = {0, 0, 0, 0, 0, 0, 0, 42}; + struct foo *f = BPF_CORE_READ((struct bar *)&memory, f); + __u32 value = (f == (struct foo *) 42); + "#, + } + .build() + .unwrap(); + assert_eq!(test.run().unwrap(), 1); +} + /// Utility code for running relocation tests: /// - Generates the eBPF program using probided local definition and relocation code /// - Generates the BTF from the target btf code From 702f77b56503477165ac6e3050df1ef7c348b717 Mon Sep 17 00:00:00 2001 From: Matteo Nardi Date: Mon, 26 Dec 2022 10:49:53 +0100 Subject: [PATCH 3/5] tests: explain libbpf env variable --- test/integration-test/src/tests/relocations.rs | 4 +++- xtask/src/build_ebpf.rs | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 2654dff6..04a14f7a 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -14,7 +14,7 @@ fn relocate_field() { __u8 b; __u8 c; __u8 d; - } __attribute__((preserve_access_index)); + }; "#, target_btf: r#" struct foo { @@ -141,6 +141,8 @@ impl RelocationTest { Command::new("clang") .current_dir(tmp_dir.path()) .args(["-c", "-g", "-O2", "-target", "bpf"]) + // NOTE: these tests depend on libbpf, LIBBPF_INCLUDE must point its headers. + // This is set automatically by the integration-test xtask. .args([ "-I", &std::env::var("LIBBPF_INCLUDE").context("LIBBPF_INCLUDE not set")?, diff --git a/xtask/src/build_ebpf.rs b/xtask/src/build_ebpf.rs index 0d3540e6..9e22da89 100644 --- a/xtask/src/build_ebpf.rs +++ b/xtask/src/build_ebpf.rs @@ -103,7 +103,12 @@ fn build_c_ebpf(opts: &BuildEbpfOptions) -> anyhow::Result<()> { let include_path = out_path.join("include"); get_libbpf_headers(&opts.libbpf_dir, &include_path)?; + // Export libbpf location as an env variable since it's needed for building + // the relocation tests at test/integration-test/src/tests/relocations.rs + // We decided to make an exception and build its eBPF programs at run-time + // because of the many different permutations. std::env::set_var("LIBBPF_INCLUDE", &include_path); + let files = fs::read_dir(&src).unwrap(); for file in files { let p = file.unwrap().path(); From 27f22f205d7f04e69372eda370bb7b436cb87445 Mon Sep 17 00:00:00 2001 From: Matteo Nardi Date: Tue, 3 Jan 2023 07:48:34 +0100 Subject: [PATCH 4/5] Make relocations tests actually pass --- .../integration-test/src/tests/relocations.rs | 171 +++++++++--------- 1 file changed, 90 insertions(+), 81 deletions(-) diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 04a14f7a..abeb51a3 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,5 +1,6 @@ use anyhow::{Context, Result}; -use std::{process::Command, thread::sleep, time::Duration}; +use std::{path::PathBuf, process::Command, thread::sleep, time::Duration}; +use tempfile::TempDir; use aya::{maps::Array, programs::TracePoint, BpfLoader, Btf, Endianness}; @@ -51,7 +52,7 @@ fn relocate_enum() { .build() .unwrap(); assert_eq!(test.run().unwrap(), 4); - assert_eq!(test.run_no_btf().unwrap(), 0); + assert_eq!(test.run_no_btf().unwrap(), 1); } #[integration_test] @@ -61,16 +62,20 @@ fn relocate_pointer() { struct foo {}; struct bar { struct foo *f; }; "#, - target_btf: r#""#, + target_btf: r#" + struct foo {}; + struct bar { struct foo *f; }; + "#, relocation_code: r#" - __u8 memory[] = {0, 0, 0, 0, 0, 0, 0, 42}; + __u8 memory[] = {42, 0, 0, 0, 0, 0, 0, 0}; struct foo *f = BPF_CORE_READ((struct bar *)&memory, f); - __u32 value = (f == (struct foo *) 42); + __u32 value = ((__u64) f); "#, } .build() .unwrap(); - assert_eq!(test.run().unwrap(), 1); + assert_eq!(test.run().unwrap(), 42); + assert_eq!(test.run_no_btf().unwrap(), 42); } /// Utility code for running relocation tests: @@ -105,57 +110,37 @@ impl RelocationTest { fn build_ebpf(&self) -> Result> { let local_definition = self.local_definition; let relocation_code = self.relocation_code; - let tmp_dir = tempfile::tempdir().context("Error making temp dir")?; - let ebpf_file = tmp_dir.path().join("ebpf_program.c"); - std::fs::write( - &ebpf_file, - format!( - r#" - #include - - #include - #include - #include - - {local_definition} - - struct {{ - __uint(type, BPF_MAP_TYPE_ARRAY); - __type(key, __u32); - __type(value, __u32); - __uint(max_entries, 1); - }} output_map SEC(".maps"); - - SEC("tracepoint/bpf_prog") int bpf_prog(void *ctx) {{ - __u32 key = 0; - {relocation_code} - bpf_map_update_elem(&output_map, &key, &value, BPF_ANY); - return 0; - }} - - char _license[] SEC("license") = "GPL"; - "# - ), - ) - .context("Writing bpf program failed")?; - Command::new("clang") - .current_dir(tmp_dir.path()) - .args(["-c", "-g", "-O2", "-target", "bpf"]) - // NOTE: these tests depend on libbpf, LIBBPF_INCLUDE must point its headers. - // This is set automatically by the integration-test xtask. - .args([ - "-I", - &std::env::var("LIBBPF_INCLUDE").context("LIBBPF_INCLUDE not set")?, - ]) - .arg(&ebpf_file) - .status() - .context("Failed to run clang")? - .success() - .then_some(()) - .context("Failed to compile eBPF program")?; - let ebpf = std::fs::read(ebpf_file.with_extension("o")) - .context("Error reading compiled eBPF program")?; - Ok(ebpf) + let (_tmp_dir, compiled_file) = compile(&format!( + r#" + #include + + #include + #include + #include + + {local_definition} + + struct {{ + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, __u32); + __type(value, __u32); + __uint(max_entries, 1); + }} output_map SEC(".maps"); + + SEC("tracepoint/bpf_prog") int bpf_prog(void *ctx) {{ + __u32 key = 0; + {relocation_code} + bpf_map_update_elem(&output_map, &key, &value, BPF_ANY); + return 0; + }} + + char _license[] SEC("license") = "GPL"; + "# + )) + .context("Failed to compile eBPF program")?; + let bytecode = + std::fs::read(compiled_file).context("Error reading compiled eBPF program")?; + Ok(bytecode) } /// - Generate the target BTF source with a mock main() @@ -163,36 +148,33 @@ impl RelocationTest { /// - Extract the BTF with pahole fn build_btf(&self) -> Result { let target_btf = self.target_btf; - let tmp_dir = tempfile::tempdir().context("Error making temp dir")?; + let relocation_code = self.relocation_code; // BTF files can be generated and inspected with these commands: // $ clang -c -g -O2 -target bpf target.c // $ pahole --btf_encode_detached=target.btf -V target.o // $ bpftool btf dump file ./target.btf format c - let btf_file = tmp_dir.path().join("target_btf.c"); - std::fs::write( - &btf_file, - format!( - r#" - #include - {target_btf} - int main() {{ return 0; }} - "# - ), - ) - .context("Writing bpf program failed")?; - Command::new("clang") - .current_dir(tmp_dir.path()) - .args(["-c", "-g", "-O2", "-target", "bpf"]) - .arg(&btf_file) - .status() - .context("Failed to run clang")? - .success() - .then_some(()) - .context("Failed to compile BTF")?; + let (tmp_dir, compiled_file) = compile(&format!( + r#" + #include + + #include + #include + #include + + {target_btf} + int main() {{ + // This is needed to make sure to emit BTF for the defined types, + // it could be dead code eliminated if we don't. + {relocation_code}; + return value; + }} + "# + )) + .context("Failed to compile BTF")?; Command::new("pahole") .current_dir(tmp_dir.path()) .arg("--btf_encode_detached=target.btf") - .arg(btf_file.with_extension("o")) + .arg(compiled_file) .status() .context("Failed to run pahole")? .success() @@ -204,6 +186,30 @@ impl RelocationTest { } } +/// Compile an eBPF program and return the path of the compiled object. +/// Also returns a TempDir handler, dropping it will clear the created dicretory. +fn compile(source_code: &str) -> Result<(TempDir, PathBuf)> { + let tmp_dir = tempfile::tempdir().context("Error making temp dir")?; + let source = tmp_dir.path().join("source.c"); + std::fs::write(&source, source_code).context("Writing bpf program failed")?; + Command::new("clang") + .current_dir(&tmp_dir) + .args(["-c", "-g", "-O2", "-target", "bpf"]) + // NOTE: these tests depend on libbpf, LIBBPF_INCLUDE must point its headers. + // This is set automatically by the integration-test xtask. + .args([ + "-I", + &std::env::var("LIBBPF_INCLUDE").context("LIBBPF_INCLUDE not set")?, + ]) + .arg(&source) + .status() + .context("Failed to run clang")? + .success() + .then_some(()) + .context("Failed to compile eBPF source")?; + Ok((tmp_dir, source.with_extension("o"))) +} + struct RelocationTestRunner { ebpf: Vec, btf: Btf, @@ -212,18 +218,21 @@ struct RelocationTestRunner { impl RelocationTestRunner { /// Run test and return the output value fn run(&self) -> Result { - self.run_internal(true) + self.run_internal(true).context("Error running with BTF") } /// Run without loading btf fn run_no_btf(&self) -> Result { self.run_internal(false) + .context("Error running without BTF") } fn run_internal(&self, with_relocations: bool) -> Result { let mut loader = BpfLoader::new(); if with_relocations { loader.btf(Some(&self.btf)); + } else { + loader.btf(None); } let mut bpf = loader.load(&self.ebpf).context("Loading eBPF failed")?; let program: &mut TracePoint = bpf From 34e040b8e9530f988e5334db486793e669933969 Mon Sep 17 00:00:00 2001 From: Matteo Nardi Date: Tue, 3 Jan 2023 12:05:54 +0100 Subject: [PATCH 5/5] tests: use libtest-mimic and fix CI --- .github/workflows/build-aya.yml | 6 +- test/integration-test/Cargo.toml | 1 + test/integration-test/src/main.rs | 83 ++++--------------- .../integration-test/src/tests/relocations.rs | 8 +- test/run.sh | 8 +- 5 files changed, 32 insertions(+), 74 deletions(-) diff --git a/.github/workflows/build-aya.yml b/.github/workflows/build-aya.yml index baf666de..991298fa 100644 --- a/.github/workflows/build-aya.yml +++ b/.github/workflows/build-aya.yml @@ -66,8 +66,12 @@ jobs: - name: Install Pre-requisites run: | + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" | sudo tee -a /etc/apt/sources.list sudo apt-get update - sudo apt-get -qy install linux-tools-common qemu-system-x86 cloud-image-utils openssh-client libelf-dev gcc-multilib + sudo apt-get -qy install linux-tools-common qemu-system-x86 cloud-image-utils openssh-client libelf-dev gcc-multilib llvm-15 clang-15 + sudo update-alternatives --install /usr/bin/llvm-objcopy llvm-objcopy /usr/bin/llvm-objcopy-15 200 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 200 cargo install bpf-linker - name: Lint integration tests diff --git a/test/integration-test/Cargo.toml b/test/integration-test/Cargo.toml index 5851e414..9282f8cc 100644 --- a/test/integration-test/Cargo.toml +++ b/test/integration-test/Cargo.toml @@ -19,3 +19,4 @@ object = { version = "0.30", default-features = false, features = ["std", "read_ rbpf = "0.1.0" regex = "1" tempfile = "3.3.0" +libtest-mimic = "0.6.0" diff --git a/test/integration-test/src/main.rs b/test/integration-test/src/main.rs index 1fd32ea4..b081e645 100644 --- a/test/integration-test/src/main.rs +++ b/test/integration-test/src/main.rs @@ -1,74 +1,21 @@ -use log::info; +use libtest_mimic::{Arguments, Trial}; mod tests; use tests::IntegrationTest; -use clap::Parser; - -#[derive(Debug, Parser)] -#[clap(author, version, about, long_about = None)] -#[clap(propagate_version = true)] -pub struct RunOptions { - #[clap(short, long, value_parser)] - tests: Option>, -} - -#[derive(Debug, Parser)] -struct Cli { - #[clap(subcommand)] - command: Option, -} - -#[derive(Debug, Parser)] -enum Command { - /// Run one or more tests: ... -- run -t test1 -t test2 - Run(RunOptions), - /// List all the tests: ... -- list - List, -} - -macro_rules! exec_test { - ($test:expr) => {{ - info!("Running {}", $test.name); - ($test.test_fn)(); - }}; -} - -macro_rules! exec_all_tests { - () => {{ - for t in inventory::iter:: { - exec_test!(t) - } - }}; -} - -fn main() -> anyhow::Result<()> { +fn main() { env_logger::init(); - - let cli = Cli::parse(); - - match &cli.command { - Some(Command::Run(opts)) => match &opts.tests { - Some(tests) => { - for t in inventory::iter:: { - if tests.contains(&t.name.into()) { - exec_test!(t) - } - } - } - None => { - exec_all_tests!() - } - }, - Some(Command::List) => { - for t in inventory::iter:: { - info!("{}", t.name); - } - } - None => { - exec_all_tests!() - } - } - - Ok(()) + let mut args = Arguments::from_args(); + // Force to run single-threaded + args.test_threads = Some(1); + let tests = inventory::iter:: + .into_iter() + .map(|test| { + Trial::test(test.name, move || { + (test.test_fn)(); + Ok(()) + }) + }) + .collect(); + libtest_mimic::run(&args, tests).exit(); } diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index abeb51a3..23bc7a18 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -145,7 +145,7 @@ impl RelocationTest { /// - Generate the target BTF source with a mock main() /// - Compile it with clang - /// - Extract the BTF with pahole + /// - Extract the BTF with llvm-objcopy fn build_btf(&self) -> Result { let target_btf = self.target_btf; let relocation_code = self.relocation_code; @@ -171,12 +171,12 @@ impl RelocationTest { "# )) .context("Failed to compile BTF")?; - Command::new("pahole") + Command::new("llvm-objcopy") .current_dir(tmp_dir.path()) - .arg("--btf_encode_detached=target.btf") + .args(["--dump-section", ".BTF=target.btf"]) .arg(compiled_file) .status() - .context("Failed to run pahole")? + .context("Failed to run llvm-objcopy")? .success() .then_some(()) .context("Failed to extract BTF")?; diff --git a/test/run.sh b/test/run.sh index b195d7a9..3be2b862 100755 --- a/test/run.sh +++ b/test/run.sh @@ -185,4 +185,10 @@ trap stop_vm EXIT cargo xtask build-integration-test --musl --libbpf-dir "$1" scp_vm ../target/x86_64-unknown-linux-musl/debug/integration-test -exec_vm sudo ./integration-test +exec_vm sudo ./integration-test --skip relocations + +# Relocation tests build the eBPF programs and require libbpf. We run them outside VM. +export LIBBPF_INCLUDE="${AYA_TMPDIR}/libbpf/" +mkdir -p "$LIBBPF_INCLUDE" +(cd "$1/src" && make INCLUDEDIR="$LIBBPF_INCLUDE" install_headers) +sudo -E ../target/x86_64-unknown-linux-musl/debug/integration-test relocations