Skip to content

Commit

Permalink
Add support for all syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
jamcleod committed Aug 2, 2021
1 parent bfc2291 commit e7993bb
Show file tree
Hide file tree
Showing 16 changed files with 4,395 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ members = [
"panda-rs",
"panda-sys",
"panda-macros",
"syscall-parser",
]
9 changes: 9 additions & 0 deletions panda-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ syn = { version = "1.0.37", features = ["full"] }
quote = "1.0.7"
doc-comment = "0.3.3"
darling = "0.10.2"

[features]
x86_64 = []
i386 = []
arm = []
aarch64 = []
ppc = []
mips = []
mipsel = []
34 changes: 28 additions & 6 deletions panda-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,11 @@ macro_rules! define_callback_attributes {
macro_rules! define_syscalls_callbacks {
($(
$($doc:literal)*
($attr_name:ident, $cb_name:ident, ($($arg_name:ident : $arg:ty),*))
),*) => {
($attr_name:ident, $cb_name:ident, ($($arg_name:ident : $arg:ty),* $(,)?))
),* $(,)?) => {
$(
doc_comment::doc_comment!{
concat!("(Callback) ", $($doc, "\n",)* "\n\nCallback arguments: (`&mut CPUState`, `target_ulong`", $(", `", stringify!($arg), "`",)* ")\n### Example\n```rust\nuse panda::prelude::*;\n\n#[panda::", stringify!($attr_name),"]\nfn callback(cpu: &mut CPUState, pc: target_ulong", $(", _: ", stringify!($arg), )* ") {\n // do stuff\n}\n```"),
concat!("(Callback) ", $($doc, "\n",)* "\n\nCallback arguments: (" /*"`&mut CPUState`, `target_ulong`"*/, $(", `", stringify!($arg), "`",)* ")\n### Example\n```rust\nuse panda::prelude::*;\n\n#[panda::", stringify!($attr_name),"]\nfn callback(cpu: &mut CPUState, pc: target_ulong", $(", _: ", stringify!($arg), )* ") {\n // do stuff\n}\n```"),
#[proc_macro_attribute]
pub fn $attr_name(_: TokenStream, function: TokenStream) -> TokenStream {
let mut function = syn::parse_macro_input!(function as syn::ItemFn);
Expand Down Expand Up @@ -294,15 +294,16 @@ macro_rules! define_syscalls_callbacks {

/// For internal use only
#[proc_macro]
#[doc(hidden)]
pub fn generate_syscalls_callbacks(_: TokenStream) -> TokenStream {
quote!(
plugin_import!{
static SYSCALLS: Syscalls2 = extern "syscalls2" {
callbacks {
$(
fn $attr_name(
cpu: &mut crate::sys::CPUState,
pc: crate::sys::target_ulong,
//cpu: &mut crate::sys::CPUState,
//pc: crate::sys::target_ulong,
$($arg_name : $arg),*
);
)*
Expand Down Expand Up @@ -351,6 +352,7 @@ macro_rules! define_hooks2_callbacks {
)*

/// For internal use only
#[doc(hidden)]
#[proc_macro]
pub fn generate_hooks2_callbacks(_: TokenStream) -> TokenStream {
quote!(
Expand All @@ -372,5 +374,25 @@ macro_rules! define_hooks2_callbacks {
}

include!("base_callbacks.rs");
include!("syscalls.rs");
include!("hooks2.rs");

#[cfg(feature = "x86_64")]
include!("syscalls/x86_64.rs");

#[cfg(feature = "i386")]
include!("syscalls/i386.rs");

#[cfg(feature = "arm")]
include!("syscalls/arm.rs");

#[cfg(feature = "aarch64")]
include!("syscalls/aarch64.rs");

#[cfg(feature = "ppc")]
include!("syscalls/ppc.rs");

#[cfg(feature = "mips")]
include!("syscalls/mips.rs");

#[cfg(feature = "mipsel")]
include!("syscalls/mipsel.rs");
4 changes: 0 additions & 4 deletions panda-macros/src/syscalls.rs

This file was deleted.

569 changes: 569 additions & 0 deletions panda-macros/src/syscalls/aarch64.rs

Large diffs are not rendered by default.

701 changes: 701 additions & 0 deletions panda-macros/src/syscalls/arm.rs

Large diffs are not rendered by default.

729 changes: 729 additions & 0 deletions panda-macros/src/syscalls/i386.rs

Large diffs are not rendered by default.

779 changes: 779 additions & 0 deletions panda-macros/src/syscalls/mips.rs

Large diffs are not rendered by default.

779 changes: 779 additions & 0 deletions panda-macros/src/syscalls/mipsel.rs

Large diffs are not rendered by default.

639 changes: 639 additions & 0 deletions panda-macros/src/syscalls/x86_64.rs

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions panda-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ thiserror = "1"

[features]
libpanda = ["panda-re-sys/libpanda"]
x86_64 = ["panda-re-sys/x86_64"]
i386 = ["panda-re-sys/i386"]
arm = ["panda-re-sys/arm"]
aarch64 = ["panda-re-sys/aarch64"]
ppc = ["panda-re-sys/ppc"]
mips = ["panda-re-sys/mips"]
mipsel = ["panda-re-sys/mipsel"]
x86_64 = ["panda-re-sys/x86_64", "panda-re-macros/x86_64"]
i386 = ["panda-re-sys/i386", "panda-re-macros/i386"]
arm = ["panda-re-sys/arm", "panda-re-macros/arm"]
aarch64 = ["panda-re-sys/aarch64", "panda-re-macros/aarch64"]
ppc = ["panda-re-sys/ppc", "panda-re-macros/ppc"]
mips = ["panda-re-sys/mips", "panda-re-macros/mips"]
mipsel = ["panda-re-sys/mipsel", "panda-re-macros/mipsel"]

default = ["x86_64"]
2 changes: 1 addition & 1 deletion panda-rs/examples/showcase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct Args {
}

#[panda::on_sys_write_enter]
fn sys_write_test(cpu: &mut CPUState, _pc: target_ulong, _fd: target_ulong, buf: target_ulong, count: target_ulong) {
fn sys_write_test(cpu: &mut CPUState, _pc: target_ulong, _fd: u32, buf: target_ulong, count: u32) {
println!(
"sys_write buf = \"{}\"",
String::from_utf8_lossy(&cpu.mem_read(buf, count as usize))
Expand Down
5 changes: 3 additions & 2 deletions panda-rs/src/plugins/syscalls2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
//! * [`on_sys_write_enter`](crate::on_sys_write_enter)
//! * [`on_sys_execve_enter`](crate::on_sys_execve_enter)
//!
//! Currently not many syscalls are implemented, open an issue if you'd like another added.
#[allow(unused_imports)]
use crate::sys::{target_ptr_t, target_ulong, CPUState};
use crate::{plugin_import, generate_syscalls_callbacks};
use crate::sys::{target_ptr_t, target_ulong};

generate_syscalls_callbacks!();
9 changes: 9 additions & 0 deletions syscall-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "syscall-parser"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
peg = "0.7.0"
7 changes: 7 additions & 0 deletions syscall-parser/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# syscall-parser

Parses `panda/plugins/syscalls2/generated/syscalls_ext_typedefs_*.h` in order to provide Rust bindings to syscalls2. To regenerate `../panda-macros/src/syscalls/*.rs`, run:

```
cargo run
```
134 changes: 134 additions & 0 deletions syscall-parser/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use std::io::Write;

#[derive(Debug)]
struct CallbackType {
name: String,
arguments: Vec<Argument>
}

#[derive(Debug)]
struct Argument {
name: String,
ty: Type,
}

#[derive(Debug)]
enum Type {
Ptr(Box<Type>),
Ident(String),
}

impl Type {
fn as_rust_type(&self) -> String {
match self {
Self::Ptr(ptr) => format!("&mut {}", ptr.as_rust_type()),
Self::Ident(ident) => match &**ident {
"uint8_t" => "u8",
"uint16_t" => "u16",
"uint32_t" => "u32",
"uint64_t" => "u64",
"int8_t" => "i8",
"int16_t" => "i16",
"int32_t" => "i32",
"int64_t" => "i64",
ident @ ("CPUState" | "target_ulong") => ident,
ident => panic!("type {} unrecognized", ident),
}.into(),
}
}
}

fn sanitize_name(name: &str) -> String {
match name {
"type" => "_type".into(),
_ => name.into(),
}
}

peg::parser! {
grammar c_parser() for str {
pub(crate) rule callback_types() -> Vec<CallbackType>
= (_? comment())* cb_types:callback_type() ** (_? ";" _?) ";" _ (comment() _?)* {
cb_types
}

rule comment()
= "//" [^ '\n']* "\n"

rule callback_type() -> CallbackType
= "typedef" _ "void" _ "(" _? "*" _? name:ident() _? ")" _?
"(" _? arguments:argument() ** ("," _?) _? ")"
{
CallbackType { name, arguments }
}

rule argument() -> Argument
= ty:c_type() _ name:ident() { Argument { name, ty } }

rule c_type() -> Type
= ptr()
/ type_ident()

rule ptr() -> Type
= ident:type_ident() _? "*" { Type::Ptr(Box::new(ident)) }

rule type_ident() -> Type
= ident:ident() { Type::Ident(ident.into()) }

rule ident() -> String
= ident:$(
['a'..='z' | 'A'..='Z' | '_'] ['a'..='z' | 'A'..='Z' | '_' | '0'..='9']*
) { ident.into() }

rule _() = quiet!{ [' ' | '\n' | '\t']+ }
}
}

const ARCHES: &[(&str, &str)] = &[
("x86_64", "x64"),
("i386", "x86"),
("arm", "arm"),
("aarch64", "arm64"),
// no ppc support
//("ppc", "ppc"),
("mips", "mips"),
("mipsel", "mips"),
];

fn main() {
for (arch, syscalls_arch) in ARCHES {
println!("Generating for {}...", arch);
let path = std::path::Path::new(
&std::env::var("PANDA_ROOT").expect("Please set 'PANDA_ROOT'")
)
.join(&format!("panda/plugins/syscalls2/generated/syscalls_ext_typedefs_{}.h", syscalls_arch));

let contents = std::fs::read_to_string(
path
).unwrap();
let mut f = std::fs::File::create(format!("../panda-macros/src/syscalls/{}.rs", arch)).unwrap();
let callback_types = c_parser::callback_types(&contents).unwrap();

writeln!(f, "// AUTOGENERATED BY panda-rs/syscall-parser DO NOT EDIT").unwrap();
writeln!(f, "define_syscalls_callbacks! {{").unwrap();
for callback_type in callback_types {
let name = callback_type.name.trim_end_matches("_t");

// omit BSD syscalls
if name.starts_with("on_sys_") {
let args = callback_type.arguments
.iter()
.map(|arg| format!("{}: {}", sanitize_name(&arg.name), arg.ty.as_rust_type()))
.collect::<Vec<String>>()
.join(", ");
writeln!(
f,
" ({name}, add_callback_{name}, ({args})),",
name=name,
args=args,
).unwrap();
}
}
writeln!(f, "}}").unwrap();
}
}

0 comments on commit e7993bb

Please sign in to comment.