|
|
@ -1,10 +1,13 @@
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
fs, io,
|
|
|
|
fs::{self, File},
|
|
|
|
|
|
|
|
io::{self, Write},
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
process::Command,
|
|
|
|
process::Command,
|
|
|
|
str::from_utf8,
|
|
|
|
str::from_utf8,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use tempfile::tempdir;
|
|
|
|
|
|
|
|
|
|
|
|
use thiserror::Error;
|
|
|
|
use thiserror::Error;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::bindgen;
|
|
|
|
use crate::bindgen;
|
|
|
@ -18,7 +21,10 @@ pub enum Error {
|
|
|
|
BpfToolExit { code: i32, stderr: String },
|
|
|
|
BpfToolExit { code: i32, stderr: String },
|
|
|
|
|
|
|
|
|
|
|
|
#[error("bindgen failed")]
|
|
|
|
#[error("bindgen failed")]
|
|
|
|
Bindgen,
|
|
|
|
Bindgen(#[source] io::Error),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[error("{stderr}\nbindgen failed with exit code {code}")]
|
|
|
|
|
|
|
|
BindgenExit { code: i32, stderr: String },
|
|
|
|
|
|
|
|
|
|
|
|
#[error("rustfmt failed")]
|
|
|
|
#[error("rustfmt failed")]
|
|
|
|
Rustfmt(#[source] io::Error),
|
|
|
|
Rustfmt(#[source] io::Error),
|
|
|
@ -35,25 +41,49 @@ pub enum InputFile {
|
|
|
|
pub fn generate<T: AsRef<str>>(input_file: InputFile, types: &[T]) -> Result<String, Error> {
|
|
|
|
pub fn generate<T: AsRef<str>>(input_file: InputFile, types: &[T]) -> Result<String, Error> {
|
|
|
|
let mut bindgen = bindgen::bpf_builder();
|
|
|
|
let mut bindgen = bindgen::bpf_builder();
|
|
|
|
|
|
|
|
|
|
|
|
match input_file {
|
|
|
|
let (c_header, name) = match input_file {
|
|
|
|
InputFile::Btf(path) => {
|
|
|
|
InputFile::Btf(path) => (c_header_from_btf(&path)?, "kernel_types.h".to_string()),
|
|
|
|
let c_header = c_header_from_btf(&path)?;
|
|
|
|
InputFile::Header(header) => (
|
|
|
|
bindgen = bindgen.header_contents("kernel_types.h", &c_header);
|
|
|
|
fs::read_to_string(&header).map_err(|_| Error::ReadHeaderFile)?,
|
|
|
|
}
|
|
|
|
header.file_name().unwrap().to_str().unwrap().to_owned(),
|
|
|
|
InputFile::Header(header) => {
|
|
|
|
),
|
|
|
|
let c_header = fs::read_to_string(&header).map_err(|_| Error::ReadHeaderFile)?;
|
|
|
|
};
|
|
|
|
let name = Path::new(&header).file_name().unwrap().to_str().unwrap();
|
|
|
|
|
|
|
|
bindgen = bindgen.header_contents(name, &c_header);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ty in types {
|
|
|
|
for ty in types {
|
|
|
|
bindgen = bindgen.allowlist_type(ty);
|
|
|
|
bindgen = bindgen.allowlist_type(ty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let bindings = bindgen.generate().or(Err(Error::Bindgen))?.to_string();
|
|
|
|
// TODO: check if this part should be moved to bindgen::generate()
|
|
|
|
|
|
|
|
let dir = tempdir().unwrap();
|
|
|
|
|
|
|
|
let file_path = dir.path().join(name);
|
|
|
|
|
|
|
|
let mut file = File::create(&file_path).unwrap();
|
|
|
|
|
|
|
|
let _ = file.write(c_header.as_bytes()).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let flags = bindgen.command_line_flags();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: check proper logging; it seems useful to see what command is
|
|
|
|
|
|
|
|
// launched but we can't disturb the normal output of the aya-gen tool
|
|
|
|
|
|
|
|
println!(
|
|
|
|
|
|
|
|
"Launching bindgen {} {}",
|
|
|
|
|
|
|
|
file_path.to_str().unwrap(),
|
|
|
|
|
|
|
|
flags.join(" ")
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let output = Command::new("bindgen")
|
|
|
|
|
|
|
|
.arg(file_path)
|
|
|
|
|
|
|
|
.args(flags)
|
|
|
|
|
|
|
|
// TODO: pass additional arguments after --
|
|
|
|
|
|
|
|
.output()
|
|
|
|
|
|
|
|
.map_err(Error::Bindgen)?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !output.status.success() {
|
|
|
|
|
|
|
|
return Err(Error::BindgenExit {
|
|
|
|
|
|
|
|
code: output.status.code().unwrap(),
|
|
|
|
|
|
|
|
stderr: from_utf8(&output.stderr).unwrap().to_owned(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(bindings)
|
|
|
|
Ok(from_utf8(&output.stdout).unwrap().to_owned())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn c_header_from_btf(path: &Path) -> Result<String, Error> {
|
|
|
|
fn c_header_from_btf(path: &Path) -> Result<String, Error> {
|
|
|
|