mirror of https://github.com/aya-rs/aya
aya-common: Add a new package
This commit adds aya-common, which is for code that is shared between aya-bpf and aya. The initial use case is for USDT probes, which require a lot of co-operation between aya and aya-bpf to provide a good UX. Signed-off-by: Dave Tucker <dave@dtucker.co.uk>pull/329/merge^2
parent
7d90413c09
commit
eb05c18140
@ -0,0 +1,24 @@
|
|||||||
|
[package]
|
||||||
|
name = "aya-common"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Code shared between aya and aya-bpf crates."
|
||||||
|
keywords = ["ebpf", "bpf", "linux", "kernel"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
authors = ["The Aya Contributors"]
|
||||||
|
repository = "https://github.com/aya-rs/aya"
|
||||||
|
readme = "README.md"
|
||||||
|
documentation = "https://docs.rs/aya"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
regex = {version = "1", optional = true}
|
||||||
|
thiserror = {version = "1", optional = true}
|
||||||
|
memoffset = {version = "0.6", optional = true}
|
||||||
|
lazy_static = {version = "1", optional = true}
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
user = [ "regex", "thiserror", "memoffset", "lazy_static" ]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/lib.rs"
|
@ -0,0 +1 @@
|
|||||||
|
#include <linux/ptrace.h>
|
@ -0,0 +1,11 @@
|
|||||||
|
/* automatically generated by rust-bindgen 0.60.1 */
|
||||||
|
|
||||||
|
pub type __u64 = ::std::os::raw::c_ulonglong;
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct user_pt_regs {
|
||||||
|
pub regs: [__u64; 31usize],
|
||||||
|
pub sp: __u64,
|
||||||
|
pub pc: __u64,
|
||||||
|
pub pstate: __u64,
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/* automatically generated by rust-bindgen 0.60.1 */
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct pt_regs {
|
||||||
|
pub uregs: [::std::os::raw::c_long; 18usize],
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
/* automatically generated by rust-bindgen 0.60.1 */
|
@ -0,0 +1,27 @@
|
|||||||
|
/* automatically generated by rust-bindgen 0.60.1 */
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct pt_regs {
|
||||||
|
pub r15: ::std::os::raw::c_ulong,
|
||||||
|
pub r14: ::std::os::raw::c_ulong,
|
||||||
|
pub r13: ::std::os::raw::c_ulong,
|
||||||
|
pub r12: ::std::os::raw::c_ulong,
|
||||||
|
pub rbp: ::std::os::raw::c_ulong,
|
||||||
|
pub rbx: ::std::os::raw::c_ulong,
|
||||||
|
pub r11: ::std::os::raw::c_ulong,
|
||||||
|
pub r10: ::std::os::raw::c_ulong,
|
||||||
|
pub r9: ::std::os::raw::c_ulong,
|
||||||
|
pub r8: ::std::os::raw::c_ulong,
|
||||||
|
pub rax: ::std::os::raw::c_ulong,
|
||||||
|
pub rcx: ::std::os::raw::c_ulong,
|
||||||
|
pub rdx: ::std::os::raw::c_ulong,
|
||||||
|
pub rsi: ::std::os::raw::c_ulong,
|
||||||
|
pub rdi: ::std::os::raw::c_ulong,
|
||||||
|
pub orig_rax: ::std::os::raw::c_ulong,
|
||||||
|
pub rip: ::std::os::raw::c_ulong,
|
||||||
|
pub cs: ::std::os::raw::c_ulong,
|
||||||
|
pub eflags: ::std::os::raw::c_ulong,
|
||||||
|
pub rsp: ::std::os::raw::c_ulong,
|
||||||
|
pub ss: ::std::os::raw::c_ulong,
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
#![allow(
|
||||||
|
dead_code,
|
||||||
|
non_camel_case_types,
|
||||||
|
non_snake_case,
|
||||||
|
clippy::all,
|
||||||
|
missing_docs
|
||||||
|
)]
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
mod linux_bindings_aarch64;
|
||||||
|
#[cfg(target_arch = "arm")]
|
||||||
|
mod linux_bindings_armv7;
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
mod linux_bindings_riscv64;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
mod linux_bindings_x86_64;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub use linux_bindings_x86_64::*;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "arm")]
|
||||||
|
pub use linux_bindings_armv7::*;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub use linux_bindings_aarch64::*;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
pub use linux_bindings_riscv64::*;
|
@ -0,0 +1,297 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub const USDT_MAX_SPEC_COUNT: u32 = 256;
|
||||||
|
pub const USDT_MAX_IP_COUNT: u32 = 4 * USDT_MAX_SPEC_COUNT;
|
||||||
|
pub const USDT_MAX_ARG_COUNT: usize = 12;
|
||||||
|
|
||||||
|
/// The type of argument in a USDT program
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "user", derive(Debug))]
|
||||||
|
pub enum UsdtArgType {
|
||||||
|
Const,
|
||||||
|
Reg,
|
||||||
|
RegDeref,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for UsdtArgType {
|
||||||
|
fn default() -> Self {
|
||||||
|
UsdtArgType::Const
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The specifcation of an argument in a USDT program
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Default, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "user", derive(Debug))]
|
||||||
|
pub struct UsdtArgSpec {
|
||||||
|
/// scalar interpreted depending on arg_type
|
||||||
|
pub val_off: u64,
|
||||||
|
/// arg location case
|
||||||
|
pub arg_type: UsdtArgType,
|
||||||
|
/// offset of referenced register within struct pt_regs
|
||||||
|
pub reg_off: i16,
|
||||||
|
/// whether arg should be interpreted as signed value
|
||||||
|
pub arg_signed: bool,
|
||||||
|
/// number of bits that need to be cleared and, optionally,
|
||||||
|
/// sign-extended to cast arguments that are 1, 2, or 4 bytes
|
||||||
|
/// long into final 8-byte u64/s64 value returned to user
|
||||||
|
pub arg_bitshift: i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "user", derive(Debug))]
|
||||||
|
pub struct UsdtSpec {
|
||||||
|
pub args: [UsdtArgSpec; USDT_MAX_ARG_COUNT],
|
||||||
|
pub cookie: u64,
|
||||||
|
pub arg_count: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "user")]
|
||||||
|
mod generated;
|
||||||
|
|
||||||
|
#[cfg(feature = "user")]
|
||||||
|
extern crate std;
|
||||||
|
#[cfg(feature = "user")]
|
||||||
|
pub mod with_std {
|
||||||
|
use crate::{UsdtArgSpec, UsdtArgType, UsdtSpec, USDT_MAX_ARG_COUNT};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use regex::Regex;
|
||||||
|
use std::{format, string::String};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum ParseError {
|
||||||
|
#[error("error parsing usdt arg spec: {0}")]
|
||||||
|
UsdtArgSpecError(String),
|
||||||
|
#[error("error parsing usdt spec: {0}")]
|
||||||
|
UsdtSpecError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref USDT_REGEX: Regex =
|
||||||
|
Regex::new(r"^(-?[0-9]+)@((-?[0-9]+)\(%(.*)\)|%(.*)|\$([0-9]+))$").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for UsdtArgSpec {
|
||||||
|
type Err = ParseError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let mut spec = UsdtArgSpec::default();
|
||||||
|
let caps = USDT_REGEX.captures(s).unwrap();
|
||||||
|
|
||||||
|
if caps.len() != 7 {
|
||||||
|
return Err(ParseError::UsdtArgSpecError(format!(
|
||||||
|
"could not parse {}",
|
||||||
|
s
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
let mut arg_size: isize = caps.get(1).unwrap().as_str().parse().unwrap();
|
||||||
|
if caps.get(3).is_some() && caps.get(4).is_some() {
|
||||||
|
spec.arg_type = UsdtArgType::RegDeref;
|
||||||
|
spec.val_off = caps.get(3).unwrap().as_str().parse::<i64>().map_err(|e| {
|
||||||
|
ParseError::UsdtArgSpecError(format!("could not parse {}: {}", s, e))
|
||||||
|
})? as u64;
|
||||||
|
spec.reg_off = calc_pt_regs_offset(caps.get(4).unwrap().as_str())?;
|
||||||
|
} else if caps.get(5).is_some() {
|
||||||
|
spec.arg_type = UsdtArgType::Reg;
|
||||||
|
spec.reg_off = calc_pt_regs_offset(caps.get(5).unwrap().as_str())?;
|
||||||
|
} else if caps.get(6).is_some() {
|
||||||
|
spec.arg_type = UsdtArgType::Const;
|
||||||
|
spec.val_off = caps.get(6).unwrap().as_str().parse::<i64>().map_err(|e| {
|
||||||
|
ParseError::UsdtArgSpecError(format!("could not parse {}: {}", s, e))
|
||||||
|
})? as u64;
|
||||||
|
}
|
||||||
|
if arg_size < 0 {
|
||||||
|
spec.arg_signed = true;
|
||||||
|
arg_size = -arg_size;
|
||||||
|
}
|
||||||
|
match arg_size {
|
||||||
|
1 | 2 | 4 | 8 => spec.arg_bitshift = (arg_size * 8) as i8,
|
||||||
|
_ => {
|
||||||
|
return Err(ParseError::UsdtArgSpecError(format!(
|
||||||
|
"arg size was not 1,2,4,8: {}",
|
||||||
|
s
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
fn calc_pt_regs_offset(reg: &str) -> Result<i16, ParseError> {
|
||||||
|
use crate::generated::pt_regs;
|
||||||
|
use memoffset::offset_of;
|
||||||
|
match reg {
|
||||||
|
"rip" | "eip" => Ok(offset_of!(pt_regs, rip) as i16),
|
||||||
|
"rax" | "eax" | "ax" | "al" => Ok(offset_of!(pt_regs, rax) as i16),
|
||||||
|
"rbx" | "ebx" | "bx" | "bl" => Ok(offset_of!(pt_regs, rbx) as i16),
|
||||||
|
"rcx" | "ecx" | "cx" | "cl" => Ok(offset_of!(pt_regs, rcx) as i16),
|
||||||
|
"rdx" | "edx" | "dx" | "dl" => Ok(offset_of!(pt_regs, rdx) as i16),
|
||||||
|
"rsi" | "esi" | "si" | "sil" => Ok(offset_of!(pt_regs, rsi) as i16),
|
||||||
|
"rdi" | "edi" | "di" | "dil" => Ok(offset_of!(pt_regs, rdi) as i16),
|
||||||
|
"rbp" | "ebp" | "bp" | "bpl" => Ok(offset_of!(pt_regs, rbp) as i16),
|
||||||
|
"rsp" | "esp" | "sp" | "bsl" => Ok(offset_of!(pt_regs, rsp) as i16),
|
||||||
|
"r8" | "r8d" | "r8w" | "r8b" => Ok(offset_of!(pt_regs, r8) as i16),
|
||||||
|
"r9" | "r9d" | "r9w" | "r9b" => Ok(offset_of!(pt_regs, r9) as i16),
|
||||||
|
"r10" | "r10d" | "r10w" | "r10b" => Ok(offset_of!(pt_regs, r10) as i16),
|
||||||
|
"r11" | "r11d" | "r11w" | "r11b" => Ok(offset_of!(pt_regs, r11) as i16),
|
||||||
|
"r12" | "r12d" | "r12w" | "r12b" => Ok(offset_of!(pt_regs, r12) as i16),
|
||||||
|
"r13" | "r13d" | "r13w" | "r13b" => Ok(offset_of!(pt_regs, r13) as i16),
|
||||||
|
"r14" | "r14d" | "r14w" | "r14b" => Ok(offset_of!(pt_regs, r14) as i16),
|
||||||
|
"r15" | "r15d" | "r15w" | "r15b" => Ok(offset_of!(pt_regs, r15) as i16),
|
||||||
|
_ => Err(ParseError::UsdtArgSpecError(format!(
|
||||||
|
"unknown register: {}",
|
||||||
|
reg
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
fn calc_pt_regs_offset(reg: &str) -> Result<i16, ParseError> {
|
||||||
|
use crate::generated::user_pt_regs;
|
||||||
|
use memoffset::offset_of;
|
||||||
|
use std::mem;
|
||||||
|
match reg {
|
||||||
|
r if r.starts_with('x') => {
|
||||||
|
let n: usize = r.strip_prefix('x').unwrap().parse().map_err(|_| {
|
||||||
|
ParseError::UsdtArgSpecError(format!(
|
||||||
|
"invalid register format. expected: xN. got: {}",
|
||||||
|
reg
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
Ok((offset_of!(user_pt_regs, regs) + (n * mem::size_of::<u64>())) as i16)
|
||||||
|
}
|
||||||
|
"sp" => Ok(offset_of!(user_pt_regs, sp) as i16),
|
||||||
|
_ => Err(ParseError::UsdtArgSpecError(format!(
|
||||||
|
"unknown register: {}",
|
||||||
|
reg
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "arm")]
|
||||||
|
fn calc_pt_regs_offset(reg: &str) -> Result<i16, ParseError> {
|
||||||
|
use crate::generated::pt_regs;
|
||||||
|
use memoffset::offset_of;
|
||||||
|
use std::mem;
|
||||||
|
match reg {
|
||||||
|
r if r.starts_with('r') => {
|
||||||
|
let n: usize = r.strip_prefix('r').unwrap().parse().map_err(|_| {
|
||||||
|
ParseError::UsdtArgSpecError(format!(
|
||||||
|
"invalid register format. expected: rN. got: {}",
|
||||||
|
reg
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
Ok((offset_of!(pt_regs, uregs) + (n * mem::size_of::<u32>())) as i16)
|
||||||
|
}
|
||||||
|
_ => Err(ParseError::UsdtArgSpecError(format!(
|
||||||
|
"unknown register: {}",
|
||||||
|
reg
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
fn calc_pt_regs_offset(reg: &str) -> Result<i16, ParseError> {
|
||||||
|
unimplemented!("riscv support for usdt probes not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for UsdtSpec {
|
||||||
|
type Err = ParseError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
use std::vec::Vec;
|
||||||
|
let parts: Vec<&str> = s.split_whitespace().collect();
|
||||||
|
if parts.len() > USDT_MAX_ARG_COUNT {
|
||||||
|
return Err(ParseError::UsdtSpecError(format!("too many args: {}", s)));
|
||||||
|
}
|
||||||
|
let mut args = parts
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.parse::<UsdtArgSpec>().unwrap())
|
||||||
|
.collect::<Vec<UsdtArgSpec>>();
|
||||||
|
let arg_count = args.len() as i16;
|
||||||
|
args.resize(USDT_MAX_ARG_COUNT, UsdtArgSpec::default());
|
||||||
|
Ok(UsdtSpec {
|
||||||
|
args: args.try_into().unwrap(),
|
||||||
|
cookie: 0,
|
||||||
|
arg_count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use memoffset::offset_of;
|
||||||
|
|
||||||
|
#[cfg_attr(target_arch = "x86_64", test)]
|
||||||
|
fn test_parse_specs() {
|
||||||
|
use crate::generated::pt_regs;
|
||||||
|
|
||||||
|
let s = "-8@%rax -8@%rcx";
|
||||||
|
let res: UsdtSpec = s.parse().unwrap();
|
||||||
|
assert_eq!(res.arg_count, 2);
|
||||||
|
assert_eq!(
|
||||||
|
res.args[0],
|
||||||
|
UsdtArgSpec {
|
||||||
|
val_off: 0,
|
||||||
|
arg_type: UsdtArgType::Reg,
|
||||||
|
reg_off: offset_of!(pt_regs, rax) as i16,
|
||||||
|
arg_signed: true,
|
||||||
|
arg_bitshift: 64
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
res.args[1],
|
||||||
|
UsdtArgSpec {
|
||||||
|
val_off: 0,
|
||||||
|
arg_type: UsdtArgType::Reg,
|
||||||
|
reg_off: offset_of!(pt_regs, rcx) as i16,
|
||||||
|
arg_signed: true,
|
||||||
|
arg_bitshift: 64
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(target_arch = "x86_64", test)]
|
||||||
|
fn test_parse_args() {
|
||||||
|
use crate::generated::pt_regs;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"-4@-1204(%rbp)".parse::<UsdtArgSpec>().unwrap(),
|
||||||
|
UsdtArgSpec {
|
||||||
|
val_off: -1204i64 as u64,
|
||||||
|
arg_type: UsdtArgType::RegDeref,
|
||||||
|
reg_off: offset_of!(pt_regs, rbp) as i16,
|
||||||
|
arg_signed: true,
|
||||||
|
arg_bitshift: 32
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"-4@%edi".parse::<UsdtArgSpec>().unwrap(),
|
||||||
|
UsdtArgSpec {
|
||||||
|
val_off: 0,
|
||||||
|
arg_type: UsdtArgType::Reg,
|
||||||
|
reg_off: offset_of!(pt_regs, rdi) as i16,
|
||||||
|
arg_signed: true,
|
||||||
|
arg_bitshift: 32
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"-4@$5".parse::<UsdtArgSpec>().unwrap(),
|
||||||
|
UsdtArgSpec {
|
||||||
|
val_off: 5,
|
||||||
|
arg_type: UsdtArgType::Const,
|
||||||
|
reg_off: 0,
|
||||||
|
arg_signed: true,
|
||||||
|
arg_bitshift: 32
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use aya_gen::{bindgen, write_to_file};
|
||||||
|
|
||||||
|
use crate::codegen::{Architecture, Options};
|
||||||
|
|
||||||
|
pub fn codegen(opts: &Options) -> Result<(), anyhow::Error> {
|
||||||
|
codegen_bindings(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> {
|
||||||
|
let types = [
|
||||||
|
// Registers
|
||||||
|
"pt_regs",
|
||||||
|
"user_pt_regs",
|
||||||
|
];
|
||||||
|
|
||||||
|
let dir = PathBuf::from("aya-common");
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Set target triple. This will set the right flags (which you can see
|
||||||
|
// running clang -target=X -E - -dM </dev/null)
|
||||||
|
let target = match arch {
|
||||||
|
Architecture::X86_64 => "x86_64-unknown-linux-gnu",
|
||||||
|
Architecture::ARMv7 => "armv7-unknown-linux-gnu",
|
||||||
|
Architecture::AArch64 => "aarch64-unknown-linux-gnu",
|
||||||
|
Architecture::RISCV64 => "riscv64-unknown-linux-gnu",
|
||||||
|
};
|
||||||
|
bindgen = bindgen.clang_args(&["-target", target]);
|
||||||
|
|
||||||
|
// Set the sysroot. This is needed to ensure that the correct arch
|
||||||
|
// specific headers are imported.
|
||||||
|
let sysroot = match arch {
|
||||||
|
Architecture::X86_64 => &opts.x86_64_sysroot,
|
||||||
|
Architecture::ARMv7 => &opts.armv7_sysroot,
|
||||||
|
Architecture::AArch64 => &opts.aarch64_sysroot,
|
||||||
|
Architecture::RISCV64 => &opts.riscv64_sysroot,
|
||||||
|
};
|
||||||
|
bindgen = bindgen.clang_args(&["-I", &*sysroot.to_string_lossy()]);
|
||||||
|
|
||||||
|
for x in &types {
|
||||||
|
bindgen = bindgen.allowlist_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(format!("linux_bindings_{}.rs", arch)),
|
||||||
|
&bindings.to_string(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue