aya_bpf_bindings.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. use anyhow::anyhow;
  2. use proc_macro2::TokenStream;
  3. use quote::ToTokens;
  4. use std::path::PathBuf;
  5. use aya_gen::{
  6. bindgen,
  7. getters::{generate_getters_for_items, read_getter},
  8. write_to_file_fmt,
  9. };
  10. use syn::{parse_str, Item};
  11. use crate::codegen::{
  12. helpers::{expand_helpers, extract_helpers},
  13. Architecture, Options,
  14. };
  15. pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> {
  16. let dir = PathBuf::from("bpf/aya-bpf-bindings");
  17. let builder = || {
  18. let mut bindgen = bindgen::bpf_builder()
  19. .header(&*dir.join("include/bindings.h").to_string_lossy())
  20. // aya-gen uses aya_bpf::cty. We can't use that here since aya-bpf
  21. // depends on aya-bpf-bindings so it would create a circular dep.
  22. .ctypes_prefix("::aya_bpf_cty")
  23. .clang_args(&[
  24. "-I",
  25. &*opts.libbpf_dir.join("include/uapi").to_string_lossy(),
  26. ])
  27. .clang_args(&["-I", &*opts.libbpf_dir.join("include").to_string_lossy()])
  28. .clang_args(&["-I", &*opts.libbpf_dir.join("src").to_string_lossy()])
  29. // open aya-bpf-bindings/.../bindings.rs and look for mod
  30. // _bindgen, those are anonymous enums
  31. .constified_enum("BPF_F_.*")
  32. .constified_enum("BPF_REG_.*")
  33. .constified_enum("BPF_CSUM_.*")
  34. .constified_enum("BPF_ADJ_.*")
  35. .constified_enum("BPF_SK_.*")
  36. .constified_enum("BPF_RB_.*")
  37. .constified_enum("BPF_RINGBUF_.*")
  38. .constified_enum("BPF_SOCK_.*")
  39. .constified_enum("BPF_TCP_.*")
  40. .constified_enum("BPF_DEVCG_.*")
  41. .constified_enum("BPF_FIB_.*")
  42. .constified_enum("BPF_FLOW_.*");
  43. let types = [
  44. "bpf_map_.*",
  45. "sk_action",
  46. "pt_regs",
  47. "xdp_action",
  48. "bpf_adj_room_mode",
  49. ];
  50. let vars = ["BPF_.*", "bpf_.*", "TC_ACT_.*", "SOL_SOCKET", "SO_.*"];
  51. for x in &types {
  52. bindgen = bindgen.allowlist_type(x);
  53. }
  54. // we define our own version which is compatible with both libbpf and
  55. // iproute2
  56. bindgen = bindgen.blocklist_type("bpf_map_def");
  57. for x in &vars {
  58. bindgen = bindgen.allowlist_var(x);
  59. }
  60. bindgen
  61. };
  62. for arch in Architecture::supported() {
  63. let mut bindgen = builder();
  64. // Set target triple. This will set the right flags (which you can see
  65. // running clang -target=X -E - -dM </dev/null)
  66. let target = match arch {
  67. Architecture::X86_64 => "x86_64-unknown-linux-gnu",
  68. Architecture::ARMv7 => "armv7-unknown-linux-gnu",
  69. Architecture::AArch64 => "aarch64-unknown-linux-gnu",
  70. };
  71. bindgen = bindgen.clang_args(&["-target", target]);
  72. // Set the sysroot. This is needed to ensure that the correct arch
  73. // specific headers are imported.
  74. let sysroot = match arch {
  75. Architecture::X86_64 => &opts.x86_64_sysroot,
  76. Architecture::ARMv7 => &opts.armv7_sysroot,
  77. Architecture::AArch64 => &opts.aarch64_sysroot,
  78. };
  79. bindgen = bindgen.clang_args(&["-I", &*sysroot.to_string_lossy()]);
  80. let bindings = bindgen
  81. .generate()
  82. .map_err(|_| anyhow!("bindgen failed"))?
  83. .to_string();
  84. let mut tree = parse_str::<syn::File>(&bindings).unwrap();
  85. let (indexes, helpers) = extract_helpers(&tree.items);
  86. let helpers = expand_helpers(&helpers);
  87. for index in indexes {
  88. tree.items[index] = Item::Verbatim(TokenStream::new())
  89. }
  90. let generated = dir.join("src").join(arch.to_string());
  91. // write the bindings, with the original helpers removed
  92. write_to_file_fmt(
  93. &generated.join("bindings.rs"),
  94. &tree.to_token_stream().to_string(),
  95. )?;
  96. // write the new helpers as expanded by expand_helpers()
  97. write_to_file_fmt(
  98. &generated.join("helpers.rs"),
  99. &format!("use super::bindings::*; {}", helpers),
  100. )?;
  101. // write the bpf_probe_read() getters
  102. let bpf_probe_read = syn::parse_str("crate::bpf_probe_read").unwrap();
  103. write_to_file_fmt(
  104. &generated.join("getters.rs"),
  105. &format!(
  106. "use super::bindings::*; {}",
  107. &generate_getters_for_items(&tree.items, |getter| {
  108. read_getter(getter, &bpf_probe_read)
  109. })
  110. .to_string()
  111. ),
  112. )?;
  113. }
  114. Ok(())
  115. }