From fb0c8f0bc92a8e080348dd0db2bd3e6a42cda102 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Wed, 24 Feb 2021 02:59:20 +0000 Subject: [PATCH] xtask: add code generator for aya --- xtask/src/codegen/aya.rs | 164 ++++++++++++++++++++++++++ xtask/src/codegen/aya_bpf_bindings.rs | 2 +- xtask/src/codegen/mod.rs | 12 ++ 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 xtask/src/codegen/aya.rs diff --git a/xtask/src/codegen/aya.rs b/xtask/src/codegen/aya.rs new file mode 100644 index 00000000..16724b38 --- /dev/null +++ b/xtask/src/codegen/aya.rs @@ -0,0 +1,164 @@ +use anyhow::anyhow; +use std::path::PathBuf; +use structopt::StructOpt; + +use aya_gen::{bindgen, write_to_file}; + +use crate::codegen::Architecture; + +#[derive(StructOpt)] +pub struct CodegenOptions { + #[structopt(long)] + libbpf_dir: PathBuf, +} + +pub fn codegen(opts: CodegenOptions) -> Result<(), anyhow::Error> { + codegen_internal_btf_bindings(&opts)?; + codegen_bindings(&opts) +} + +fn codegen_internal_btf_bindings(opts: &CodegenOptions) -> Result<(), anyhow::Error> { + let dir = PathBuf::from("aya"); + let generated = dir.join("src/generated"); + let mut bindgen = bindgen::user_builder().header( + opts.libbpf_dir + .join("src/libbpf_internal.h") + .to_string_lossy(), + ); + + let types = ["bpf_core_relo", "btf_ext_header"]; + + for x in &types { + bindgen = bindgen.whitelist_type(x); + } + + let bindings = bindgen + .generate() + .map_err(|_| anyhow!("bindgen failed"))? + .to_string(); + + // write the bindings, with the original helpers removed + write_to_file( + &generated.join("btf_internal_bindings.rs"), + &bindings.to_string(), + )?; + + Ok(()) +} + +fn codegen_bindings(opts: &CodegenOptions) -> Result<(), anyhow::Error> { + let types = [ + // BPF + "BPF_TYPES", + "bpf_cmd", + "bpf_insn", + "bpf_attr", + "bpf_map_type", + "bpf_prog_type", + "bpf_attach_type", + // BTF + "btf_header", + "btf_ext_info", + "btf_ext_info_sec", + "btf_type", + "btf_enum", + "btf_array", + "btf_member", + "btf_param", + "btf_var", + "btf_var_secinfo", + // PERF + "perf_event_attr", + "perf_sw_ids", + "perf_event_sample_format", + "perf_event_mmap_page", + "perf_event_header", + "perf_type_id", + "perf_event_type", + // NETLINK + "ifinfomsg", + ]; + + let vars = [ + // BPF + "BPF_PSEUDO_.*", + "BPF_ALU", + "BPF_ALU64", + "BPF_LDX", + "BPF_ST", + "BPF_STX", + "BPF_LD", + "BPF_K", + "BPF_DW", + "BPF_W", + "BPF_H", + "BPF_B", + "SO_ATTACH_BPF", + "SO_DETACH_BPF", + // BTF + "BTF_KIND_.*", + "BTF_INT_.*", + // PERF + "PERF_FLAG_.*", + "PERF_EVENT_.*", + // NETLINK + "NLMSG_ALIGNTO", + "IFLA_XDP_FD", + "XDP_FLAGS_.*", + ]; + + let dir = PathBuf::from("aya"); + let generated = dir.join("src/generated"); + + let builder = || { + bindgen::user_builder() + .header(dir.join("include/linux_wrapper.h").to_string_lossy()) + .clang_args(&[ + "-I", + &*opts.libbpf_dir.join("include/uapi").to_string_lossy(), + ]) + .clang_args(&["-I", &*opts.libbpf_dir.join("include").to_string_lossy()]) + }; + + for arch in Architecture::supported() { + let mut bindgen = builder(); + + for x in &types { + bindgen = bindgen.whitelist_type(x); + } + for x in &vars { + bindgen = bindgen.whitelist_var(x); + } + + // FIXME: this stuff is probably debian/ubuntu specific + match arch { + Architecture::X86_64 => { + bindgen = bindgen.clang_args(&["-I", "/usr/include/x86_64-linux-gnu"]); + } + Architecture::AArch64 => { + bindgen = bindgen.clang_args(&["-I", "/usr/aarch64-linux-gnu/include"]); + } + }; + + for x in &types { + bindgen = bindgen.whitelist_type(x); + } + + for x in &vars { + bindgen = bindgen.whitelist_var(x); + } + + let bindings = bindgen + .generate() + .map_err(|_| anyhow!("bindgen failed"))? + .to_string(); + + // write the bindings, with the original helpers removed + write_to_file( + &generated.join(format!("linux_bindings_{}.rs", arch)), + &bindings.to_string(), + )?; + } + + Ok(()) +} diff --git a/xtask/src/codegen/aya_bpf_bindings.rs b/xtask/src/codegen/aya_bpf_bindings.rs index d78026bd..32c26da6 100644 --- a/xtask/src/codegen/aya_bpf_bindings.rs +++ b/xtask/src/codegen/aya_bpf_bindings.rs @@ -29,7 +29,7 @@ pub fn codegen(opts: CodegenOptions) -> Result<(), anyhow::Error> { let dir = PathBuf::from("bpf/aya-bpf-bindings"); let generated = dir.join("src").join(opts.arch.to_string()); - let mut bindgen = bindgen::builder() + let mut bindgen = bindgen::bpf_builder() .header(&*dir.join("include/bindings.h").to_string_lossy()) .clang_args(&["-I", &*opts.libbpf_dir.join("src").to_string_lossy()]); diff --git a/xtask/src/codegen/mod.rs b/xtask/src/codegen/mod.rs index 7d07f1cc..8e90e3a7 100644 --- a/xtask/src/codegen/mod.rs +++ b/xtask/src/codegen/mod.rs @@ -1,14 +1,23 @@ +mod aya; mod aya_bpf_bindings; mod helpers; use structopt::StructOpt; +const SUPPORTED_ARCHS: &'static [Architecture] = &[Architecture::X86_64, Architecture::AArch64]; + #[derive(Debug, Copy, Clone)] pub enum Architecture { X86_64, AArch64, } +impl Architecture { + pub fn supported() -> &'static [Architecture] { + SUPPORTED_ARCHS + } +} + impl std::str::FromStr for Architecture { type Err = String; @@ -38,6 +47,8 @@ pub struct Options { #[derive(StructOpt)] enum Command { + #[structopt(name = "aya")] + Aya(aya::CodegenOptions), #[structopt(name = "aya-bpf-bindings")] AyaBpfBindings(aya_bpf_bindings::CodegenOptions), } @@ -45,6 +56,7 @@ enum Command { pub fn codegen(opts: Options) -> Result<(), anyhow::Error> { use Command::*; match opts.command { + Aya(opts) => aya::codegen(opts), AyaBpfBindings(opts) => aya_bpf_bindings::codegen(opts), } }