From c258b51963516f58e2bbd67e5c16cd99473624d1 Mon Sep 17 00:00:00 2001 From: desbma-s1n Date: Thu, 30 May 2024 12:10:08 +0200 Subject: [PATCH] feat: named arguments --- src/strace/parser/mod.rs | 52 ++++++++++++++++++++++++++++++++++++++ src/strace/parser/peg.pest | 8 +++++- src/strace/parser/peg.rs | 47 ++++++++++++++++++++++++---------- 3 files changed, 92 insertions(+), 15 deletions(-) diff --git a/src/strace/parser/mod.rs b/src/strace/parser/mod.rs index 2f143ad..dc7a92b 100644 --- a/src/strace/parser/mod.rs +++ b/src/strace/parser/mod.rs @@ -1499,6 +1499,58 @@ mod tests { }) ); } + + #[cfg_attr( + feature = "parser-regex", + ignore = "named arguments not supported by regex-parser" + )] + #[test] + fn test_clone() { + let _ = simple_logger::SimpleLogger::new().init(); + + assert_eq!( + parse_line( + "714433 0.000035 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f3f3c2f5090) = 714434", + &[] + ) + .unwrap(), + ParseResult::Syscall(Syscall { + pid: 714433, + rel_ts: 0.000035, + name: "clone".to_owned(), + args: vec![ + Expression::Struct(HashMap::from([ + ( + "child_stack".to_owned(), + Expression::Integer(IntegerExpression { + value: IntegerExpressionValue::NamedConst("NULL".to_owned()), + metadata: None, + }), + ), + ( + "flags".to_owned(), + Expression::Integer(IntegerExpression { + value: IntegerExpressionValue::BinaryOr(vec![ + IntegerExpressionValue::NamedConst("CLONE_CHILD_CLEARTID".to_owned()), + IntegerExpressionValue::NamedConst("CLONE_CHILD_SETTID".to_owned()), + IntegerExpressionValue::NamedConst("SIGCHLD".to_owned()), + ]), + metadata: None + }), + ), + ( + "child_tidptr".to_owned(), + Expression::Integer(IntegerExpression { + value: IntegerExpressionValue::Literal(0x7f3f3c2f5090), + metadata: None, + }), + ), + ])), + ], + ret_val: 714434 + }) + ); + } } #[cfg(all(feature = "nightly", test))] diff --git a/src/strace/parser/peg.pest b/src/strace/parser/peg.pest index c11fbfc..d804d79 100644 --- a/src/strace/parser/peg.pest +++ b/src/strace/parser/peg.pest @@ -20,13 +20,19 @@ rel_ts = { ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } name = { symbol_name } -arguments = { (argument ~ (", " ~ argument)*)? } +arguments = { + #named = named_arguments | + #unnamed = unnamed_arguments +} ret_val = { int ~ (" " ~ ANY*)? } // Subrules +named_arguments = { struct_member ~ (", " ~ struct_member)* } +unnamed_arguments = { (argument ~ (", " ~ argument)*)? } + argument = { #in_out = in_out_argument | #in = in_argument diff --git a/src/strace/parser/peg.rs b/src/strace/parser/peg.rs index 6be1237..b206c8b 100644 --- a/src/strace/parser/peg.rs +++ b/src/strace/parser/peg.rs @@ -289,22 +289,41 @@ impl TryFrom> for Syscall { .to_owned(); let args = if pair_tag.as_str() != "end" { - subpairs + let args_pair = subpairs .next() - .ok_or_else(|| anyhow::anyhow!("Missing arguments node"))? - .into_inner() - .map(|p| { - let p = pair_descend(p, 1)?; - match p.as_node_tag() { - Some("in") => pair_descend(p, 2)?.try_into(), - Some("in_out") => { - // Only take the 'in' part, ignore the rest - pair_descend(p, 2)?.try_into() + .ok_or_else(|| anyhow::anyhow!("Missing arguments node"))?; + let args_pair = pair_descend(args_pair, 1)?; + match args_pair.as_node_tag() { + Some("unnamed") => args_pair + .into_inner() + .map(|p| { + let p = pair_descend(p, 1)?; + match p.as_node_tag() { + Some("in") => pair_descend(p, 2)?.try_into(), + Some("in_out") => { + // Only take the 'in' part, ignore the rest + pair_descend(p, 2)?.try_into() + } + _ => anyhow::bail!("Unhandled pair: {p:?}"), } - _ => anyhow::bail!("Unhandled pair: {p:?}"), - } - }) - .collect::>()? + }) + .collect::>()?, + Some("named") => { + // Handle name arguments as a single struct + vec![Expression::Struct( + args_pair + .into_inner() + .map(|p| -> anyhow::Result<_> { + let (name, val) = p.into_inner().next_tuple().ok_or_else(|| { + anyhow::anyhow!("Missing name arguments nodes") + })?; + Ok((name.as_str().to_owned(), pair_descend(val, 1)?.try_into()?)) + }) + .collect::>()?, + )] + } + _ => anyhow::bail!("Unhandled pair: {args_pair:?}"), + } } else { vec![] };