Browse Source

xtask: add code generator for aya

Alessandro Decina 4 years ago
parent
commit
fb0c8f0bc9
3 changed files with 177 additions and 1 deletions
  1. 164 0
      xtask/src/codegen/aya.rs
  2. 1 1
      xtask/src/codegen/aya_bpf_bindings.rs
  3. 12 0
      xtask/src/codegen/mod.rs

+ 164 - 0
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(())
+}

+ 1 - 1
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()]);
 

+ 12 - 0
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),
     }
 }