Merge pull request #727 from tamird/build-everywhere

integration-test: avoid reliance on kernel headers
reviewable/pr638/r35
Tamir Duberstein 1 year ago committed by GitHub
commit cb42d028d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,7 +5,7 @@ edition = "2021"
publish = false publish = false
[dependencies] [dependencies]
anyhow = { workspace = true, default-features = true } anyhow = { workspace = true, features = ["std"] }
assert_matches = { workspace = true } assert_matches = { workspace = true }
aya = { workspace = true } aya = { workspace = true }
aya-log = { workspace = true } aya-log = { workspace = true }
@ -16,10 +16,7 @@ netns-rs = { workspace = true }
object = { workspace = true } object = { workspace = true }
rbpf = { workspace = true } rbpf = { workspace = true }
test-case = { workspace = true } test-case = { workspace = true }
tokio = { workspace = true, default-features = false, features = [ tokio = { workspace = true, features = ["macros", "time"] }
"macros",
"time",
] }
[build-dependencies] [build-dependencies]
cargo_metadata = { workspace = true } cargo_metadata = { workspace = true }

@ -1,10 +1,9 @@
#include <linux/bpf.h> // clang-format off
#include <vmlinux.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
// clang-format on
SEC("xdp") SEC("xdp")
int xdp_drop(struct xdp_md *ctx) int xdp_drop(struct xdp_md *ctx) { return XDP_DROP; }
{
return XDP_DROP;
}
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";

@ -1,10 +1,9 @@
#include <linux/bpf.h> // clang-format off
#include <vmlinux.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
// clang-format on
SEC("xdp") SEC("xdp")
int xdp_pass(struct xdp_md *ctx) int xdp_pass(struct xdp_md *ctx) { return XDP_PASS; }
{
return XDP_PASS;
}
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";

@ -1,30 +1,30 @@
#include <linux/bpf.h> // clang-format off
#include <vmlinux.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
// clang-format on
struct { struct {
__uint(type, BPF_MAP_TYPE_ARRAY); __uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32); __type(key, __u32);
__type(value, __u64); __type(value, __u64);
__uint(max_entries, 1); __uint(max_entries, 1);
} map_1 SEC(".maps"); } map_1 SEC(".maps");
struct { struct {
__uint(type, BPF_MAP_TYPE_ARRAY); __uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32); __type(key, __u32);
__type(value, __u64); __type(value, __u64);
__uint(max_entries, 1); __uint(max_entries, 1);
} map_2 SEC(".maps"); } map_2 SEC(".maps");
SEC("tracepoint") SEC("tracepoint")
int bpf_prog(void *ctx) int bpf_prog(void *ctx) {
{ __u32 key = 0;
__u32 key = 0; __u64 twenty_four = 24;
__u64 twenty_four = 24; __u64 forty_two = 42;
__u64 forty_two = 42; bpf_map_update_elem(&map_1, &key, &twenty_four, BPF_ANY);
bpf_map_update_elem(&map_1, &key, &twenty_four, BPF_ANY); bpf_map_update_elem(&map_2, &key, &forty_two, BPF_ANY);
bpf_map_update_elem(&map_2, &key, &forty_two, BPF_ANY); return 0;
return 0;
} }
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";

@ -1,10 +1,10 @@
// clang-format off // clang-format off
#include <linux/bpf.h> #include <vmlinux.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h> #include <bpf/bpf_core_read.h>
// clang-format on // clang-format on
char _license[] __attribute__((section("license"), used)) = "GPL"; char _license[] SEC("license") = "GPL";
struct { struct {
__uint(type, BPF_MAP_TYPE_ARRAY); __uint(type, BPF_MAP_TYPE_ARRAY);
@ -19,12 +19,17 @@ long set_output(__u64 value) {
} }
struct relocated_struct_with_scalars { struct relocated_struct_with_scalars {
#ifndef TARGET
__u8 a; __u8 a;
#endif
__u8 b; __u8 b;
__u8 c; __u8 c;
#ifdef TARGET
__u8 d;
#endif
}; };
__attribute__((noinline)) int field_global() { __noinline int field_global() {
struct relocated_struct_with_scalars s = {1, 2, 3}; struct relocated_struct_with_scalars s = {1, 2, 3};
return set_output(__builtin_preserve_access_index(s.b)); return set_output(__builtin_preserve_access_index(s.b));
} }
@ -32,11 +37,16 @@ __attribute__((noinline)) int field_global() {
SEC("uprobe") int field(void *ctx) { return field_global(); } SEC("uprobe") int field(void *ctx) { return field_global(); }
struct relocated_struct_with_pointer { struct relocated_struct_with_pointer {
#ifndef TARGET
struct relocated_struct_with_pointer *first; struct relocated_struct_with_pointer *first;
#endif
struct relocated_struct_with_pointer *second; struct relocated_struct_with_pointer *second;
#ifdef TARGET
struct relocated_struct_with_pointer *first;
#endif
}; };
__attribute__((noinline)) int pointer_global() { __noinline int pointer_global() {
struct relocated_struct_with_pointer s = { struct relocated_struct_with_pointer s = {
(struct relocated_struct_with_pointer *)42, (struct relocated_struct_with_pointer *)42,
(struct relocated_struct_with_pointer *)21, (struct relocated_struct_with_pointer *)21,
@ -46,49 +56,86 @@ __attribute__((noinline)) int pointer_global() {
SEC("uprobe") int pointer(void *ctx) { return pointer_global(); } SEC("uprobe") int pointer(void *ctx) { return pointer_global(); }
__attribute__((noinline)) int struct_flavors_global() { __noinline int struct_flavors_global() {
struct relocated_struct_with_scalars s = {1, 2, 3}; struct relocated_struct_with_scalars s = {1, 2, 3};
#ifndef TARGET
if (bpf_core_field_exists(s.a)) { if (bpf_core_field_exists(s.a)) {
return set_output(__builtin_preserve_access_index(s.a)); return set_output(__builtin_preserve_access_index(s.a));
#else
if (bpf_core_field_exists(s.d)) {
return set_output(__builtin_preserve_access_index(s.d));
#endif
} else { } else {
return set_output(__builtin_preserve_access_index(s.b)); return set_output(__builtin_preserve_access_index(s.c));
} }
} }
SEC("uprobe") int struct_flavors(void *ctx) { return struct_flavors_global(); } SEC("uprobe") int struct_flavors(void *ctx) { return struct_flavors_global(); }
enum relocated_enum_unsigned_32 { U32 = 0xAAAAAAAA }; enum relocated_enum_unsigned_32 {
U32_VAL =
#ifndef TARGET
0xAAAAAAAA
#else
0xBBBBBBBB
#endif
};
__attribute__((noinline)) int enum_unsigned_32_global() { __noinline int enum_unsigned_32_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_unsigned_32, U32)); return set_output(
bpf_core_enum_value(enum relocated_enum_unsigned_32, U32_VAL));
} }
SEC("uprobe") int enum_unsigned_32(void *ctx) { SEC("uprobe") int enum_unsigned_32(void *ctx) {
return enum_unsigned_32_global(); return enum_unsigned_32_global();
} }
enum relocated_enum_signed_32 { S32 = -0x7AAAAAAA }; enum relocated_enum_signed_32 {
S32_VAL =
#ifndef TARGET
-0x7AAAAAAA
#else
-0x7BBBBBBB
#endif
};
__attribute__((noinline)) int enum_signed_32_global() { __noinline int enum_signed_32_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_signed_32, S32)); return set_output(
bpf_core_enum_value(enum relocated_enum_signed_32, S32_VAL));
} }
SEC("uprobe") int enum_signed_32(void *ctx) { return enum_signed_32_global(); } SEC("uprobe") int enum_signed_32(void *ctx) { return enum_signed_32_global(); }
enum relocated_enum_unsigned_64 { U64 = 0xAAAAAAAABBBBBBBB }; enum relocated_enum_unsigned_64 {
U64_VAL =
#ifndef TARGET
0xAAAAAAAABBBBBBBB
#else
0xCCCCCCCCDDDDDDDD
#endif
};
__attribute__((noinline)) int enum_unsigned_64_global() { __noinline int enum_unsigned_64_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_unsigned_64, U64)); return set_output(
bpf_core_enum_value(enum relocated_enum_unsigned_64, U64_VAL));
} }
SEC("uprobe") int enum_unsigned_64(void *ctx) { SEC("uprobe") int enum_unsigned_64(void *ctx) {
return enum_unsigned_64_global(); return enum_unsigned_64_global();
} }
enum relocated_enum_signed_64 { u64 = -0xAAAAAAABBBBBBBB }; enum relocated_enum_signed_64 {
S64_VAL =
#ifndef TARGET
-0xAAAAAAABBBBBBBB
#else
-0xCCCCCCCDDDDDDDD
#endif
};
__attribute__((noinline)) int enum_signed_64_global() { __noinline int enum_signed_64_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_signed_64, u64)); return set_output(
bpf_core_enum_value(enum relocated_enum_signed_64, S64_VAL));
} }
SEC("uprobe") int enum_signed_64(void *ctx) { return enum_signed_64_global(); } SEC("uprobe") int enum_signed_64(void *ctx) { return enum_signed_64_global(); }

@ -1,77 +0,0 @@
// clang-format off
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
// clang-format on
#include <stdlib.h>
long set_output(__u64 value) { exit((int)value); }
struct relocated_struct_with_scalars {
__u8 b;
__u8 c;
__u8 d;
};
__attribute__((noinline)) int field_global() {
struct relocated_struct_with_scalars s = {1, 2, 3};
return set_output(__builtin_preserve_access_index(s.b));
}
struct relocated_struct_with_pointer {
struct relocated_struct_with_pointer *second;
struct relocated_struct_with_pointer *first;
};
__attribute__((noinline)) int pointer_global() {
struct relocated_struct_with_pointer s = {
(struct relocated_struct_with_pointer *)42,
(struct relocated_struct_with_pointer *)21,
};
return set_output((__u64)__builtin_preserve_access_index(s.first));
}
__attribute__((noinline)) int struct_flavors_global() {
struct relocated_struct_with_scalars s = {1, 2, 3};
if (bpf_core_field_exists(s.b)) {
return set_output(__builtin_preserve_access_index(s.b));
} else {
return set_output(__builtin_preserve_access_index(s.c));
}
}
enum relocated_enum_unsigned_32 { U32 = 0xBBBBBBBB };
__attribute__((noinline)) int enum_unsigned_32_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_unsigned_32, U32));
}
enum relocated_enum_signed_32 { S32 = -0x7BBBBBBB };
__attribute__((noinline)) int enum_signed_32_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_signed_32, S32));
}
enum relocated_enum_unsigned_64 { U64 = 0xCCCCCCCCDDDDDDDD };
__attribute__((noinline)) int enum_unsigned_64_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_unsigned_64, U64));
}
enum relocated_enum_signed_64 { u64 = -0xCCCCCCCDDDDDDDD };
__attribute__((noinline)) int enum_signed_64_global() {
return set_output(bpf_core_enum_value(enum relocated_enum_signed_64, u64));
}
// Avoids dead code elimination by the compiler.
int main() {
field_global();
pointer_global();
struct_flavors_global();
enum_unsigned_32_global();
enum_signed_32_global();
enum_unsigned_64_global();
enum_signed_64_global();
}

@ -1,28 +1,25 @@
#include <linux/bpf.h> // clang-format off
#include <vmlinux.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
// clang-format on
char _license[] SEC("license") = "GPL"; char _license[] SEC("license") = "GPL";
struct { struct {
__uint(type, BPF_MAP_TYPE_ARRAY); __uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32); __type(key, __u32);
__type(value, __u64); __type(value, __u64);
__uint(max_entries, 2); __uint(max_entries, 2);
} RESULTS SEC(".maps"); } RESULTS SEC(".maps");
static __u64 static __u64 inc_cb(void *map, __u32 *key, void *val, void *data) {
inc_cb(void *map, __u32 *key, void *val, __u64 *value = val;
void *data) *value += 1;
{ return 0;
__u64 *value = val;
*value += 1;
return 0;
} }
SEC("uprobe/test_text_64_64_reloc") SEC("uprobe/test_text_64_64_reloc")
int test_text_64_64_reloc(struct pt_regs *ctx) int test_text_64_64_reloc(struct pt_regs *ctx) {
{ bpf_for_each_map_elem(&RESULTS, inc_cb, NULL, 0);
bpf_for_each_map_elem(&RESULTS, inc_cb, NULL, 0); return 0;
return 0;
} }

@ -4,7 +4,7 @@ use std::{
fs, fs,
io::{BufRead as _, BufReader}, io::{BufRead as _, BufReader},
path::PathBuf, path::PathBuf,
process::{Child, Command, Stdio}, process::{Child, Command, Output, Stdio},
}; };
use cargo_metadata::{ use cargo_metadata::{
@ -64,20 +64,14 @@ fn main() {
panic!("unsupported endian={:?}", endian) panic!("unsupported endian={:?}", endian)
}; };
const C_BPF: &[(&str, &str)] = &[ const C_BPF: &[(&str, bool)] = &[
("ext.bpf.c", "ext.bpf.o"), ("ext.bpf.c", false),
("main.bpf.c", "main.bpf.o"), ("main.bpf.c", false),
("multimap-btf.bpf.c", "multimap-btf.bpf.o"), ("multimap-btf.bpf.c", false),
("reloc.bpf.c", "reloc.bpf.o"), ("reloc.bpf.c", true),
("text_64_64_reloc.c", "text_64_64_reloc.o"), ("text_64_64_reloc.c", false),
]; ];
let c_bpf = C_BPF.iter().map(|(src, dst)| (src, out_dir.join(dst)));
const C_BTF: &[(&str, &str)] = &[("reloc.btf.c", "reloc.btf.o")];
let c_btf = C_BTF.iter().map(|(src, dst)| (src, out_dir.join(dst)));
if build_integration_bpf { if build_integration_bpf {
let libbpf_dir = manifest_dir let libbpf_dir = manifest_dir
.parent() .parent()
@ -116,65 +110,67 @@ fn main() {
target_arch.push(arch); target_arch.push(arch);
}; };
for (src, dst) in c_bpf { // NB: libbpf's documentation suggests that vmlinux.h be generated by running `bpftool btf
let src = bpf_dir.join(src); // dump file /sys/kernel/btf/vmlinux format c`; this allows CO-RE to work.
println!("cargo:rerun-if-changed={}", src.to_str().unwrap()); //
// However in our tests we do not make use of kernel data structures, and so any vmlinux.h
// which defines the constants we need (e.g. `__u8`, `__u64`, `BPF_MAP_TYPE_ARRAY`,
// `BPF_ANY`, `XDP_PASS`, `XDP_DROP`, etc.) will suffice. Since we already have a libbpf
// submodule which happens to include such a file, we use it.
let libbpf_vmlinux_dir = libbpf_dir.join(".github/actions/build-selftests");
exec( let clang = || {
Command::new("clang") let mut cmd = Command::new("clang");
.arg("-I") cmd.arg("-nostdlibinc")
.arg(&libbpf_headers_dir) .arg("-I")
.args(["-g", "-O2", "-target", target, "-c"]) .arg(&libbpf_headers_dir)
.arg(&target_arch) .arg("-I")
.arg(src) .arg(&libbpf_vmlinux_dir)
.arg("-o") .args(["-g", "-O2", "-target", target, "-c"])
.arg(dst), .arg(&target_arch);
) cmd
.unwrap(); };
}
for (src, dst) in c_btf { for (src, build_btf) in C_BPF {
let dst = out_dir.join(src).with_extension("o");
let src = bpf_dir.join(src); let src = bpf_dir.join(src);
println!("cargo:rerun-if-changed={}", src.to_str().unwrap()); println!("cargo:rerun-if-changed={}", src.to_str().unwrap());
let mut cmd = Command::new("clang"); exec(clang().arg(&src).arg("-o").arg(&dst)).unwrap();
cmd.arg("-I")
.arg(&libbpf_headers_dir) if *build_btf {
.args(["-g", "-target", target, "-c"]) let mut cmd = clang();
.arg(&target_arch) let mut child = cmd
.arg(src) .arg("-DTARGET")
.args(["-o", "-"]); .arg(&src)
.args(["-o", "-"])
let mut child = cmd .stdout(Stdio::piped())
.stdout(Stdio::piped()) .spawn()
.spawn() .unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}"));
.unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}"));
let Child { stdout, .. } = &mut child;
let Child { stdout, .. } = &mut child; let stdout = stdout.take().unwrap();
let stdout = stdout.take().unwrap();
let dst = dst.with_extension("target.o");
let mut output = OsString::new();
output.push(".BTF="); let mut output = OsString::new();
output.push(dst); output.push(".BTF=");
exec( output.push(dst);
// NB: objcopy doesn't support reading from stdin, so we have to use llvm-objcopy. exec(
Command::new("llvm-objcopy") // NB: objcopy doesn't support reading from stdin, so we have to use llvm-objcopy.
.arg("--dump-section") Command::new("llvm-objcopy")
.arg(output) .arg("--dump-section")
.arg("-") .arg(output)
.stdin(stdout), .arg("-")
) .stdin(stdout),
.unwrap(); )
.unwrap();
let status = child
.wait() let output = child
.unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}")); .wait_with_output()
match status.code() { .unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}"));
Some(code) => match code { let Output { status, .. } = &output;
0 => {} assert_eq!(status.code(), Some(0), "{cmd:?} failed: {output:?}");
code => panic!("{cmd:?} exited with status code {code}"),
},
None => panic!("{cmd:?} terminated by signal"),
} }
} }
@ -257,13 +253,7 @@ fn main() {
let status = child let status = child
.wait() .wait()
.unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}")); .unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}"));
match status.code() { assert_eq!(status.code(), Some(0), "{cmd:?} failed: {status:?}");
Some(code) => match code {
0 => {}
code => panic!("{cmd:?} exited with status code {code}"),
},
None => panic!("{cmd:?} terminated by signal"),
}
stderr.join().map_err(std::panic::resume_unwind).unwrap(); stderr.join().map_err(std::panic::resume_unwind).unwrap();
@ -273,8 +263,13 @@ fn main() {
.unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}")); .unwrap_or_else(|err| panic!("failed to copy {binary:?} to {dst:?}: {err}"));
} }
} else { } else {
for (_src, dst) in c_bpf.chain(c_btf) { for (src, build_btf) in C_BPF {
let dst = out_dir.join(src).with_extension("o");
fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}")); fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}"));
if *build_btf {
let dst = dst.with_extension("target.o");
fs::write(&dst, []).unwrap_or_else(|err| panic!("failed to create {dst:?}: {err}"));
}
} }
let Package { targets, .. } = integration_ebpf_package; let Package { targets, .. } = integration_ebpf_package;

@ -5,7 +5,8 @@ pub const MAIN: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/main.b
pub const MULTIMAP_BTF: &[u8] = pub const MULTIMAP_BTF: &[u8] =
include_bytes_aligned!(concat!(env!("OUT_DIR"), "/multimap-btf.bpf.o")); include_bytes_aligned!(concat!(env!("OUT_DIR"), "/multimap-btf.bpf.o"));
pub const RELOC_BPF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.bpf.o")); pub const RELOC_BPF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.bpf.o"));
pub const RELOC_BTF: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.btf.o")); pub const RELOC_BTF: &[u8] =
include_bytes_aligned!(concat!(env!("OUT_DIR"), "/reloc.bpf.target.o"));
pub const TEXT_64_64_RELOC: &[u8] = pub const TEXT_64_64_RELOC: &[u8] =
include_bytes_aligned!(concat!(env!("OUT_DIR"), "/text_64_64_reloc.o")); include_bytes_aligned!(concat!(env!("OUT_DIR"), "/text_64_64_reloc.o"));

@ -2,20 +2,20 @@ use test_case::test_case;
use aya::{maps::Array, programs::UProbe, util::KernelVersion, BpfLoader, Btf, Endianness}; use aya::{maps::Array, programs::UProbe, util::KernelVersion, BpfLoader, Btf, Endianness};
#[test_case("field", false, None, 2)] #[test_case("enum_signed_32", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0x7AAAAAAAi32 as u64)]
#[test_case("field", true, None, 1)] #[test_case("enum_signed_32", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0x7BBBBBBBi32 as u64)]
#[test_case("enum_signed_64", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0xAAAAAAABBBBBBBBi64 as u64)]
#[test_case("enum_signed_64", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0xCCCCCCCDDDDDDDDi64 as u64)]
#[test_case("enum_unsigned_32", false, None, 0xAAAAAAAA)] #[test_case("enum_unsigned_32", false, None, 0xAAAAAAAA)]
#[test_case("enum_unsigned_32", true, None, 0xBBBBBBBB)] #[test_case("enum_unsigned_32", true, None, 0xBBBBBBBB)]
#[test_case("enum_unsigned_64", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), 0xAAAAAAAABBBBBBBB)]
#[test_case("enum_unsigned_64", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), 0xCCCCCCCCDDDDDDDD)]
#[test_case("field", false, None, 2)]
#[test_case("field", true, None, 1)]
#[test_case("pointer", false, None, 42)] #[test_case("pointer", false, None, 42)]
#[test_case("pointer", true, None, 21)] #[test_case("pointer", true, None, 21)]
#[test_case("struct_flavors", false, None, 1)] #[test_case("struct_flavors", false, None, 1)]
#[test_case("struct_flavors", true, None, 1)] #[test_case("struct_flavors", true, None, 2)]
#[test_case("enum_signed_32", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0x7AAAAAAAi32 as u64)]
#[test_case("enum_signed_32", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0x7BBBBBBBi32 as u64)]
#[test_case("enum_unsigned_64", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), 0xAAAAAAAABBBBBBBB)]
#[test_case("enum_unsigned_64", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), 0xCCCCCCCCDDDDDDDD)]
#[test_case("enum_signed_64", false, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0xAAAAAAABBBBBBBBi64 as u64)]
#[test_case("enum_signed_64", true, Some((KernelVersion::new(6, 0, 0), "https://github.com/torvalds/linux/commit/6089fb3")), -0xCCCCCCCDDDDDDDDi64 as u64)]
fn relocation_tests( fn relocation_tests(
program: &str, program: &str,
with_relocations: bool, with_relocations: bool,

@ -6,10 +6,10 @@ edition = "2021"
publish = false publish = false
[dependencies] [dependencies]
anyhow = { workspace = true, default-features = true } anyhow = { workspace = true, features = ["std"] }
aya-tool = { workspace = true } aya-tool = { workspace = true }
cargo_metadata = { workspace = true } cargo_metadata = { workspace = true }
clap = { workspace = true, default-features = true, features = ["derive"] } clap = { workspace = true, features = ["derive"] }
dialoguer = { workspace = true } dialoguer = { workspace = true }
diff = { workspace = true } diff = { workspace = true }
indoc = { workspace = true } indoc = { workspace = true }

@ -1,4 +1,4 @@
use anyhow::{anyhow, Context as _, Result}; use anyhow::{bail, Context as _, Result};
use std::{ use std::{
fs, fs,
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -13,13 +13,10 @@ pub fn exec(cmd: &mut Command) -> Result<()> {
let status = cmd let status = cmd
.status() .status()
.with_context(|| format!("failed to run {cmd:?}"))?; .with_context(|| format!("failed to run {cmd:?}"))?;
match status.code() { if status.code() != Some(0) {
Some(code) => match code { bail!("{cmd:?} failed: {status:?}")
0 => Ok(()),
code => Err(anyhow!("{cmd:?} exited with code {code}")),
},
None => Err(anyhow!("{cmd:?} terminated by signal")),
} }
Ok(())
} }
// Create a symlink in the out directory to work around the fact that cargo ignores anything // Create a symlink in the out directory to work around the fact that cargo ignores anything

@ -62,7 +62,7 @@ pub fn public_api(options: Options, metadata: Metadata) -> Result<()> {
}); });
if !errors.is_empty() { if !errors.is_empty() {
bail!("public API errors:\n{errors}"); bail!("public API errors:\n{errors}")
} }
Ok(()) Ok(())
} }

@ -6,7 +6,7 @@ use std::{
process::{Child, Command, Stdio}, process::{Child, Command, Stdio},
}; };
use anyhow::{bail, Context as _, Result}; use anyhow::{anyhow, bail, Context as _, Result};
use cargo_metadata::{Artifact, CompilerMessage, Message, Target}; use cargo_metadata::{Artifact, CompilerMessage, Message, Target};
use clap::Parser; use clap::Parser;
use xtask::AYA_BUILD_INTEGRATION_BPF; use xtask::AYA_BUILD_INTEGRATION_BPF;
@ -77,14 +77,9 @@ pub fn build(opts: BuildOptions) -> Result<Vec<(String, PathBuf)>> {
let status = child let status = child
.wait() .wait()
.with_context(|| format!("failed to wait for {cmd:?}"))?; .with_context(|| format!("failed to wait for {cmd:?}"))?;
match status.code() { if status.code() != Some(0) {
Some(code) => match code { bail!("{cmd:?} failed: {status:?}")
0 => {}
code => bail!("{cmd:?} exited with status code {code}"),
},
None => bail!("{cmd:?} terminated by signal"),
} }
Ok(executables) Ok(executables)
} }
@ -98,7 +93,7 @@ pub fn run(opts: Options) -> Result<()> {
let binaries = build(build_options).context("error while building userspace application")?; let binaries = build(build_options).context("error while building userspace application")?;
let mut args = runner.trim().split_terminator(' '); let mut args = runner.trim().split_terminator(' ');
let runner = args.next().ok_or(anyhow::anyhow!("no first argument"))?; let runner = args.next().ok_or(anyhow!("no first argument"))?;
let args = args.collect::<Vec<_>>(); let args = args.collect::<Vec<_>>();
let mut failures = String::new(); let mut failures = String::new();
@ -110,24 +105,18 @@ pub fn run(opts: Options) -> Result<()> {
.args(run_args.iter()) .args(run_args.iter())
.arg("--test-threads=1"); .arg("--test-threads=1");
println!("{} running {cmd:?}", name); println!("{name} running {cmd:?}");
let status = cmd let status = cmd
.status() .status()
.with_context(|| format!("failed to run {cmd:?}"))?; .with_context(|| format!("failed to run {cmd:?}"))?;
match status.code() { if status.code() != Some(0) {
Some(code) => match code { writeln!(&mut failures, "{name} failed: {status:?}").context("String write failed")?
0 => {}
code => writeln!(&mut failures, "{} exited with status code {code}", name)
.context("String write failed")?,
},
None => writeln!(&mut failures, "{} terminated by signal", name)
.context("String write failed")?,
} }
} }
if failures.is_empty() { if failures.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(anyhow::anyhow!("failures:\n{}", failures)) Err(anyhow!("failures:\n{}", failures))
} }
} }

Loading…
Cancel
Save