From patchwork Mon May 27 08:14:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13674766 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C1D2CC25B78 for ; Mon, 27 May 2024 08:00:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sBVHE-0004tG-Mz; Mon, 27 May 2024 04:00:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGN-0004fH-QZ for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:25 -0400 Received: from mgamail.intel.com ([192.198.163.17]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVG7-0004Vy-Ao for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716796747; x=1748332747; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WIiMy5ieHYZlDBKxx9ayAEu7brMWY9XnH0Rv5GgqqoE=; b=d4QfYj5IoW279a2StXKcrN+H9wiU84twZ8/X2u/jHefsXy7+RtpNNiG7 V6Fxwi1yPCwmUS5AW1kIepK+XpU2UyvCNXpKA/Y89VKiJjeTyk3bn1vzg gdQ9hhJ2eJMxI8OnFdF1da5KC1DwFLS/HY6qcP5VzSBL5495Z9RC93j0o rCHs0lAMe6tHyE4QdNwDfGOj0DRA4jw31rAwg6fsUbTyR5OsDuVWAwBI+ Dq3bLrIL0488xvSBbyfciXTtClMb/o664nFIrtOt0WMClIpM2bCqct/fw 5G9BaDriNy2As735FKkJipaOVqoGsXzB1ClS3MSyP3O5iJqhYqBERS7mP g==; X-CSE-ConnectionGUID: N/+X4kOuRLW6bUK7H05qyg== X-CSE-MsgGUID: U+t4B99OS3S6d62bFe6hvA== X-IronPort-AV: E=McAfee;i="6600,9927,11084"; a="12967714" X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="12967714" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2024 00:59:06 -0700 X-CSE-ConnectionGUID: n8MBLThMSv+hxAKfJWiQyQ== X-CSE-MsgGUID: Qo0fSpeLQPeDJeWka7rRSQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="39084953" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by fmviesa005.fm.intel.com with ESMTP; 27 May 2024 00:59:02 -0700 From: Zhao Liu To: Stefan Hajnoczi , Mads Ynddal , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Daniel_P_?= =?utf-8?q?=2E_Berrang=C3=A9?= , Thomas Huth , Markus Armbruster Cc: qemu-devel@nongnu.org, Zhao Liu Subject: [RFC 1/6] scripts/simpletrace-rust: Add the basic cargo framework Date: Mon, 27 May 2024 16:14:16 +0800 Message-Id: <20240527081421.2258624-2-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240527081421.2258624-1-zhao1.liu@intel.com> References: <20240527081421.2258624-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.198.163.17; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.145, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, T_SPF_HELO_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Define the basic cargo framework to support compiling simpletrace-rust via cargo, and add the Rust code style (with some nightly features) check items to make Rust style as close to the QEMU C code as possible. With the base cargo package, define the basic code framework for simpletrace-rust, approximating the Python version, and also abstract Analyzer operations for simpletrace-rust. Event and other future trace-related structures are placed in the trace module. Additionally, support basic command line parsing for simpletrace-rust as a start. Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu --- scripts/simpletrace-rust/.gitignore | 1 + scripts/simpletrace-rust/.rustfmt.toml | 9 + scripts/simpletrace-rust/Cargo.lock | 239 +++++++++++++++++++++++++ scripts/simpletrace-rust/Cargo.toml | 11 ++ scripts/simpletrace-rust/src/main.rs | 173 ++++++++++++++++++ scripts/simpletrace-rust/src/trace.rs | 11 ++ 6 files changed, 444 insertions(+) create mode 100644 scripts/simpletrace-rust/.gitignore create mode 100644 scripts/simpletrace-rust/.rustfmt.toml create mode 100644 scripts/simpletrace-rust/Cargo.lock create mode 100644 scripts/simpletrace-rust/Cargo.toml create mode 100644 scripts/simpletrace-rust/src/main.rs create mode 100644 scripts/simpletrace-rust/src/trace.rs diff --git a/scripts/simpletrace-rust/.gitignore b/scripts/simpletrace-rust/.gitignore new file mode 100644 index 000000000000..2f7896d1d136 --- /dev/null +++ b/scripts/simpletrace-rust/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/scripts/simpletrace-rust/.rustfmt.toml b/scripts/simpletrace-rust/.rustfmt.toml new file mode 100644 index 000000000000..97a97c24ebfb --- /dev/null +++ b/scripts/simpletrace-rust/.rustfmt.toml @@ -0,0 +1,9 @@ +brace_style = "AlwaysNextLine" +comment_width = 80 +edition = "2021" +group_imports = "StdExternalCrate" +imports_granularity = "item" +max_width = 80 +use_field_init_shorthand = true +use_try_shorthand = true +wrap_comments = true diff --git a/scripts/simpletrace-rust/Cargo.lock b/scripts/simpletrace-rust/Cargo.lock new file mode 100644 index 000000000000..4a0ff8092dcb --- /dev/null +++ b/scripts/simpletrace-rust/Cargo.lock @@ -0,0 +1,239 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "proc-macro2" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "simpletrace-rust" +version = "0.1.0" +dependencies = [ + "clap", + "thiserror", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/scripts/simpletrace-rust/Cargo.toml b/scripts/simpletrace-rust/Cargo.toml new file mode 100644 index 000000000000..b44ba1569dad --- /dev/null +++ b/scripts/simpletrace-rust/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "simpletrace-rust" +description = "Pretty-printer for simple trace backend binary trace files (Rust version)" +version = "0.1.0" +edition = "2021" +authors = ["Zhao Liu "] +license = "GPL-2.0-or-later" + +[dependencies] +clap = "4.5.4" +thiserror = "1.0.20" diff --git a/scripts/simpletrace-rust/src/main.rs b/scripts/simpletrace-rust/src/main.rs new file mode 100644 index 000000000000..2d2926b7658d --- /dev/null +++ b/scripts/simpletrace-rust/src/main.rs @@ -0,0 +1,173 @@ +/* + * Pretty-printer for simple trace backend binary trace files (Rust version) + * + * Copyright (C) 2024 Intel Corporation. + * + * Authors: Zhao Liu + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#![allow(dead_code)] +#![allow(unused_variables)] + +mod trace; + +use std::env; + +use clap::Arg; +use clap::Command; +use thiserror::Error; +use trace::Event; + +#[derive(Error, Debug)] +pub enum Error +{ + #[error("usage: {0} [--no-header] ")] + CliOptionUnmatch(String), +} + +pub type Result = std::result::Result; + +pub struct EventArgPayload {} + +trait Analyzer +{ + /* Called at the start of the trace. */ + fn begin(&self) {} + + /* Called if no specific method for processing a trace event. */ + fn catchall( + &mut self, + rec_args: &[EventArgPayload], + event: &Event, + timestamp_ns: u64, + pid: u32, + event_id: u64, + ) -> Result; + + /* Called at the end of the trace. */ + fn end(&self) {} + + /* + * TODO: Support "variable" parameters (i.e. variants of process_event() + * with different parameters, like **kwargs in python), when we need a + * simpletrace rust module. + */ + fn process_event( + &mut self, + rec_args: &[EventArgPayload], + event: &Event, + event_id: u64, + timestamp_ns: u64, + pid: u32, + ) -> Result + { + self.catchall(rec_args, event, timestamp_ns, pid, event_id) + + /* + * TODO: Support custom function hooks (like getattr() in python), + * when we need a simpletrace rust module. + */ + } +} + +struct Formatter +{ + last_timestamp_ns: Option, +} + +impl Formatter +{ + fn new() -> Self + { + Formatter { + last_timestamp_ns: None, + } + } +} + +impl Analyzer for Formatter +{ + fn catchall( + &mut self, + rec_args: &[EventArgPayload], + event: &Event, + timestamp_ns: u64, + pid: u32, + event_id: u64, + ) -> Result + { + let fmt_str = String::new(); + + Ok(fmt_str) + } +} + +fn process( + event_path: &str, + trace_path: &str, + analyzer: &mut Formatter, + read_header: bool, +) -> Result<()> +{ + analyzer.begin(); + analyzer.end(); + + Ok(()) +} + +/* + * Execute an analyzer on a trace file given on the command-line. + * This function is useful as a driver for simple analysis scripts. More + * advanced scripts will want to call process() instead. + */ +fn run(analyzer: &mut Formatter) -> Result<()> +{ + let matches = Command::new("simple trace") + .arg( + Arg::new("no-header") + .required(false) + .long("no-header") + .action(clap::ArgAction::SetTrue) + .help("Disable header parsing"), + ) + .arg( + Arg::new("trace-events") + .required(true) + .action(clap::ArgAction::Set) + .help("Path to trace events file"), + ) + .arg( + Arg::new("trace-file") + .required(true) + .action(clap::ArgAction::Set) + .help("Path to trace file"), + ) + .try_get_matches() + .map_err(|_| { + Error::CliOptionUnmatch( + env::current_exe() + .unwrap_or_else(|_| "simpletrace".into()) + .to_string_lossy() + .to_string(), + ) + })?; + + let no_header = matches.get_flag("no-header"); + let event_path = matches.get_one::("trace-events").unwrap(); + let trace_path = matches.get_one::("trace-file").unwrap(); + + process(event_path, trace_path, analyzer, !no_header)?; + + Ok(()) +} + +fn main() +{ + let mut fmt = Formatter::new(); + + if let Err(e) = run(&mut fmt) { + println!("{:?}", e.to_string()); + } +} diff --git a/scripts/simpletrace-rust/src/trace.rs b/scripts/simpletrace-rust/src/trace.rs new file mode 100644 index 000000000000..3a4b06435b8b --- /dev/null +++ b/scripts/simpletrace-rust/src/trace.rs @@ -0,0 +1,11 @@ +/* + * Machinery for generating tracing-related intermediate files (Rust version) + * + * Copyright (C) 2024 Intel Corporation. + * + * Authors: Zhao Liu + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +pub struct Event {} From patchwork Mon May 27 08:14:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13674764 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4E5E2C25B74 for ; Mon, 27 May 2024 08:00:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sBVGx-0004ob-Uw; Mon, 27 May 2024 03:59:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGE-0004ZR-2C for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:15 -0400 Received: from mgamail.intel.com ([192.198.163.17]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGA-0004WD-SG for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716796751; x=1748332751; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=C/uavNm9TPbuPaD5VN1/gZbyddHCNXdVHsl2V4ClR0Q=; b=WQ7keHJ3fDzxiQ4t1+YIzuhqY39jLJnSq+oe+WEwl/TKvO66rBz8tbRm 2iEdLld30Fd4QrW4rYQltU0j6q2jti1xbKn6bXLPCSwYfUbZUhbAYyrs7 nKREo6phIAMXXZj+L3F7nk0PVnKpC37ree0ymRDBvOW/5aRdTK3C6QkjE B3o8O/LNCykKFwb814TlPUhRnHuzb5n5jo1kkx9gcstvnQ1SrzMqg+rAt 8mN4S4mfZBypUEMHsqpMtDXP6JXEnCFNRxT/2XR+RKKFAQEytjsk8qssy +foObHVVWRmXpFgfYRHGMpTR+l8BpdjBbvVgrZ5xxJR9NkaZFORRyVbgz w==; X-CSE-ConnectionGUID: y4PTYw7sQ8uIdzUNZ7OVTg== X-CSE-MsgGUID: veOVoYhNRR2GNrMU6NXYkg== X-IronPort-AV: E=McAfee;i="6600,9927,11084"; a="12967721" X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="12967721" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2024 00:59:09 -0700 X-CSE-ConnectionGUID: ZsNg3/yMS06F/eWhHl4JBw== X-CSE-MsgGUID: Ca4lDMgESfyYZ8tNP5x3cw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="39084961" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by fmviesa005.fm.intel.com with ESMTP; 27 May 2024 00:59:05 -0700 From: Zhao Liu To: Stefan Hajnoczi , Mads Ynddal , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Daniel_P_?= =?utf-8?q?=2E_Berrang=C3=A9?= , Thomas Huth , Markus Armbruster Cc: qemu-devel@nongnu.org, Zhao Liu Subject: [RFC 2/6] scripts/simpletrace-rust: Support Event & Arguments in trace module Date: Mon, 27 May 2024 16:14:17 +0800 Message-Id: <20240527081421.2258624-3-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240527081421.2258624-1-zhao1.liu@intel.com> References: <20240527081421.2258624-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.198.163.17; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.145, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Refer to scripts/tracetool/__init__.py, add Event & Arguments abstractions in trace module. Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu --- scripts/simpletrace-rust/Cargo.lock | 52 ++++ scripts/simpletrace-rust/Cargo.toml | 2 + scripts/simpletrace-rust/src/trace.rs | 330 +++++++++++++++++++++++++- 3 files changed, 383 insertions(+), 1 deletion(-) diff --git a/scripts/simpletrace-rust/Cargo.lock b/scripts/simpletrace-rust/Cargo.lock index 4a0ff8092dcb..3d815014eb44 100644 --- a/scripts/simpletrace-rust/Cargo.lock +++ b/scripts/simpletrace-rust/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.6.14" @@ -90,6 +99,18 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "proc-macro2" version = "1.0.83" @@ -108,11 +129,42 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + [[package]] name = "simpletrace-rust" version = "0.1.0" dependencies = [ "clap", + "once_cell", + "regex", "thiserror", ] diff --git a/scripts/simpletrace-rust/Cargo.toml b/scripts/simpletrace-rust/Cargo.toml index b44ba1569dad..24a79d04e566 100644 --- a/scripts/simpletrace-rust/Cargo.toml +++ b/scripts/simpletrace-rust/Cargo.toml @@ -8,4 +8,6 @@ license = "GPL-2.0-or-later" [dependencies] clap = "4.5.4" +once_cell = "1.19.0" +regex = "1.10.4" thiserror = "1.0.20" diff --git a/scripts/simpletrace-rust/src/trace.rs b/scripts/simpletrace-rust/src/trace.rs index 3a4b06435b8b..f41d6e0b5bc3 100644 --- a/scripts/simpletrace-rust/src/trace.rs +++ b/scripts/simpletrace-rust/src/trace.rs @@ -8,4 +8,332 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -pub struct Event {} +#![allow(dead_code)] + +use std::fs::read_to_string; + +use once_cell::sync::Lazy; +use regex::Regex; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error +{ + #[error("Empty argument (did you forget to use 'void'?)")] + EmptyArg, + #[error("Event '{0}' has more than maximum permitted argument count")] + InvalidArgCnt(String), + #[error("{0} does not end with a new line")] + InvalidEventFile(String), + #[error("Invalid format: {0}")] + InvalidFormat(String), + #[error( + "Argument type '{0}' is not allowed. \ + Only standard C types and fixed size integer \ + types should be used. struct, union, and \ + other complex pointer types should be \ + declared as 'void *'" + )] + InvalidType(String), + #[error("Error at {0}:{1}: {2}")] + ReadEventFail(String, usize, String), + #[error("Unknown event: {0}")] + UnknownEvent(String), + #[error("Unknown properties: {0}")] + UnknownProp(String), +} + +pub type Result = std::result::Result; + +/* + * Refer to the description of ALLOWED_TYPES in + * scripts/tracetool/__init__.py. + */ +const ALLOWED_TYPES: [&str; 20] = [ + "int", + "long", + "short", + "char", + "bool", + "unsigned", + "signed", + "int8_t", + "uint8_t", + "int16_t", + "uint16_t", + "int32_t", + "uint32_t", + "int64_t", + "uint64_t", + "void", + "size_t", + "ssize_t", + "uintptr_t", + "ptrdiff_t", +]; + +const STRING_TYPES: [&str; 4] = + ["const char*", "char*", "const char *", "char *"]; + +/* TODO: Support 'vcpu' property. */ +const VALID_PROPS: [&str; 1] = ["disable"]; + +fn validate_c_type(arg_type: &str) -> Result<()> +{ + static RE_TYPE: Lazy = Lazy::new(|| Regex::new(r"\*").unwrap()); + let bits: Vec = + arg_type.split_whitespace().map(|s| s.to_string()).collect(); + for bit in bits { + let res = RE_TYPE.replace_all(&bit, ""); + if res.is_empty() { + continue; + } + if res == "const" { + continue; + } + if !ALLOWED_TYPES.contains(&res.as_ref()) { + return Err(Error::InvalidType(res.to_string())); + } + } + Ok(()) +} + +pub fn read_events(fname: &str) -> Result> +{ + let fstr = read_to_string(fname).unwrap(); + let lines = fstr.lines().map(|s| s.trim()).collect::>(); + let mut events = Vec::new(); + + /* + * lines() in Rust: Line terminators are not included in the lines + * returned by the iterator, so check whether line_str is empty. + */ + for (lineno, line_str) in lines.iter().enumerate() { + if line_str.is_empty() || line_str.starts_with('#') { + continue; + } + + let event = Event::build(line_str, lineno as u32 + 1, fname); + if let Err(e) = event { + return Err(Error::ReadEventFail( + fname.to_owned(), + lineno, + e.to_string(), + )); + } else { + events.push(event.unwrap()); + } + } + + Ok(events) +} + +#[derive(Clone)] +pub struct ArgProperty +{ + pub c_type: String, + pub name: String, +} + +impl ArgProperty +{ + fn new(c_type: &str, name: &str) -> Self + { + ArgProperty { + c_type: c_type.to_string(), + name: name.to_string(), + } + } + + pub fn is_string(&self) -> bool + { + let arg_strip = self.c_type.trim_start(); + STRING_TYPES.iter().any(|&s| arg_strip.starts_with(s)) + && arg_strip.matches('*').count() == 1 + } +} + +#[derive(Default, Clone)] +pub struct Arguments +{ + /* List of (type, name) tuples or arguments properties. */ + pub props: Vec, +} + +impl Arguments +{ + pub fn new() -> Self + { + Arguments { props: Vec::new() } + } + + pub fn len(&self) -> usize + { + self.props.len() + } + + pub fn build(arg_str: &str) -> Result + { + let mut args = Arguments::new(); + for arg in arg_str.split(',').map(|s| s.trim()) { + if arg.is_empty() { + return Err(Error::EmptyArg); + } + + if arg == "void" { + continue; + } + + let (arg_type, identifier) = if arg.contains('*') { + /* FIXME: Implement rsplit_inclusive(). */ + let p = arg.rfind('*').unwrap(); + ( + /* Safe because arg contains "*" and p exists. */ + unsafe { arg.get_unchecked(..p + 1) }, + /* Safe because arg contains "*" and p exists. */ + unsafe { arg.get_unchecked(p + 1..) }, + ) + } else { + arg.rsplit_once(' ').unwrap() + }; + + validate_c_type(arg_type)?; + args.props.push(ArgProperty::new(arg_type, identifier)); + } + Ok(args) + } +} + +/* TODO: Support original, event_trans, event_exec if needed. */ +#[derive(Default, Clone)] +pub struct Event +{ + /* The event name. */ + pub name: String, + /* Properties of the event. */ + pub properties: Vec, + /* The event format string. */ + pub fmt: Vec, + /* The event arguments. */ + pub args: Arguments, + /* The line number in the input file. */ + pub lineno: u32, + /* The path to the input file. */ + pub filename: String, +} + +impl Event +{ + #[allow(clippy::too_many_arguments)] + pub fn new( + name: &str, + mut props: Vec, + fmt: Vec, + args: Arguments, + lineno: u32, + filename: &str, + ) -> Result + { + let mut event = Event { + name: name.to_string(), + fmt: fmt.clone(), + args, + lineno, + filename: filename.to_string(), + ..Default::default() + }; + + event.properties.append(&mut props); + + if event.args.len() > 10 { + return Err(Error::InvalidArgCnt(event.name)); + } + + let unknown_props: Vec = event + .properties + .iter() + .filter_map(|p| { + if !VALID_PROPS.contains(&p.as_str()) { + Some(p.to_string()) + } else { + None + } + }) + .collect(); + if !unknown_props.is_empty() { + return Err(Error::UnknownProp(format!("{:?}", unknown_props))); + } + + if event.fmt.len() > 2 { + return Err(Error::InvalidFormat( + format!("too many arguments ({})", event.fmt.len()).to_string(), + )); + } + + Ok(event) + } + + pub fn build(line_str: &str, lineno: u32, filename: &str) -> Result + { + static RE: Lazy = Lazy::new(|| { + Regex::new( + r#"(?x) + ((?P[\w\s]+)\s+)? + (?P\w+) + \((?P[^)]*)\) + \s* + (?:(?:(?P".+),)?\s*(?P".+))? + \s*"#, + ) + .unwrap() + }); + + let caps_res = RE.captures(line_str); + if caps_res.is_none() { + return Err(Error::UnknownEvent(line_str.to_owned())); + } + let caps = caps_res.unwrap(); + let name = caps.name("name").map_or("", |m| m.as_str()); + let props: Vec = if caps.name("props").is_some() { + caps.name("props") + .unwrap() + .as_str() + .split_whitespace() + .map(|s| s.to_string()) + .collect() + } else { + Vec::new() + }; + let fmt: String = + caps.name("fmt").map_or("", |m| m.as_str()).to_string(); + let fmt_trans: String = caps + .name("fmt_trans") + .map_or("", |m| m.as_str()) + .to_string(); + + if fmt.contains("%m") || fmt_trans.contains("%m") { + return Err(Error::InvalidFormat( + "Event format '%m' is forbidden, pass the error + as an explicit trace argument" + .to_string(), + )); + } + if fmt.ends_with(r"\n") { + return Err(Error::InvalidFormat( + "Event format must not end with a newline + character" + .to_string(), + )); + } + let mut fmt_vec = vec![fmt]; + if !fmt_trans.is_empty() { + fmt_vec.push(fmt_trans); + } + + let args = + Arguments::build(caps.name("args").map_or("", |m| m.as_str()))?; + let event = Event::new(name, props, fmt_vec, args, lineno, filename)?; + + Ok(event) + } +} From patchwork Mon May 27 08:14:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13674777 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0D374C25B7C for ; Mon, 27 May 2024 08:02:10 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sBVHn-0005I0-Ai; Mon, 27 May 2024 04:00:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGF-0004bf-Jh for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:15 -0400 Received: from mgamail.intel.com ([192.198.163.17]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGC-0004Vj-Bh for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716796752; x=1748332752; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=n5LwkxBtgvJ3BNcCx2oxBYNjJJlOnu7VIcbHmrqwRto=; b=eq9b3PgKxC8k/qw7kUXAqxke/LOP5vOSNpIDmH0+bZ0cTrWpgw/QRd/o BX24ouQItwukfqlt2Dbg7qpZqFHejoxSxWym7kKzg957mDrNrVbxh2c3r AzjxrjmEM9+Be+2cUUVsWcxragE50ruABq/pXpSJ0W6Mg8Jr6o/SIF9Th VpBW/8zb0wjUnBtd2JTYHwA/4PLelqB/H1tiIZjQbrA9z7577NC9ItG7A eVMQWqYcjsU9bxWzgOGzVVUo7Ebcr94isd90aiZnmS3hjsG/IKeYc8lbC OAtWEYxoNK0TB+SagK+rCwoScOjAObN2Qx+k2pHBJ+3mYjhVa82ojeah6 w==; X-CSE-ConnectionGUID: XMMTgtu+RXqtfmMUWe2yFA== X-CSE-MsgGUID: IKOiw6V9SDKMOzwyepnFFA== X-IronPort-AV: E=McAfee;i="6600,9927,11084"; a="12967727" X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="12967727" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2024 00:59:12 -0700 X-CSE-ConnectionGUID: 5aVS/fsZRwCU+YxWJ0yL3A== X-CSE-MsgGUID: rJq9qp6qS3qUKbuVsXIIQw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="39084975" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by fmviesa005.fm.intel.com with ESMTP; 27 May 2024 00:59:09 -0700 From: Zhao Liu To: Stefan Hajnoczi , Mads Ynddal , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Daniel_P_?= =?utf-8?q?=2E_Berrang=C3=A9?= , Thomas Huth , Markus Armbruster Cc: qemu-devel@nongnu.org, Zhao Liu Subject: [RFC 3/6] scripts/simpletrace-rust: Add helpers to parse trace file Date: Mon, 27 May 2024 16:14:18 +0800 Message-Id: <20240527081421.2258624-4-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240527081421.2258624-1-zhao1.liu@intel.com> References: <20240527081421.2258624-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.198.163.17; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -45 X-Spam_score: -4.6 X-Spam_bar: ---- X-Spam_report: (-4.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.145, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Refer to scripts/simpletrace.py, add the helpers to read the trace file and parse the record type field, record header and log header. Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu --- scripts/simpletrace-rust/src/main.rs | 151 +++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/scripts/simpletrace-rust/src/main.rs b/scripts/simpletrace-rust/src/main.rs index 2d2926b7658d..b3b8baee7c66 100644 --- a/scripts/simpletrace-rust/src/main.rs +++ b/scripts/simpletrace-rust/src/main.rs @@ -14,21 +14,172 @@ mod trace; use std::env; +use std::fs::File; +use std::io::Error as IOError; +use std::io::ErrorKind; +use std::io::Read; use clap::Arg; use clap::Command; use thiserror::Error; use trace::Event; +const RECORD_TYPE_MAPPING: u64 = 0; +const RECORD_TYPE_EVENT: u64 = 1; + #[derive(Error, Debug)] pub enum Error { #[error("usage: {0} [--no-header] ")] CliOptionUnmatch(String), + #[error("Failed to read file: {0}")] + ReadFile(IOError), + #[error("Unknown record type ({0})")] + UnknownRecType(u64), } pub type Result = std::result::Result; +enum RecordType +{ + Empty, + Mapping, + Event, +} + +#[repr(C)] +#[derive(Clone, Copy, Default)] +struct RecordRawType +{ + rtype: u64, +} + +impl RecordType +{ + fn read_type(mut fobj: &File) -> Result + { + let mut tbuf = [0u8; 8]; + if let Err(e) = fobj.read_exact(&mut tbuf) { + if e.kind() == ErrorKind::UnexpectedEof { + return Ok(RecordType::Empty); + } else { + return Err(Error::ReadFile(e)); + } + } + + /* + * Safe because the layout of the trace record requires us to parse + * the type first, and then there is a check on the validity of the + * record type. + */ + let raw_t = + unsafe { std::mem::transmute::<[u8; 8], RecordRawType>(tbuf) }; + match raw_t.rtype { + RECORD_TYPE_MAPPING => Ok(RecordType::Mapping), + RECORD_TYPE_EVENT => Ok(RecordType::Event), + _ => Err(Error::UnknownRecType(raw_t.rtype)), + } + } +} + +trait ReadHeader +{ + fn read_header(fobj: &File) -> Result + where + Self: Sized; +} + +#[repr(C)] +#[derive(Clone, Copy)] +struct LogHeader +{ + event_id: u64, + magic: u64, + version: u64, +} + +impl ReadHeader for LogHeader +{ + fn read_header(mut fobj: &File) -> Result + { + let mut raw_hdr = [0u8; 24]; + fobj.read_exact(&mut raw_hdr).map_err(Error::ReadFile)?; + + /* + * Safe because the size of log header (struct LogHeader) + * is 24 bytes, which is ensured by simple trace backend. + */ + let hdr = + unsafe { std::mem::transmute::<[u8; 24], LogHeader>(raw_hdr) }; + Ok(hdr) + } +} + +#[derive(Default)] +struct RecordInfo +{ + event_id: u64, + timestamp_ns: u64, + record_pid: u32, + args_payload: Vec, +} + +impl RecordInfo +{ + fn new() -> Self + { + Default::default() + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +struct RecordHeader +{ + event_id: u64, + timestamp_ns: u64, + record_length: u32, + record_pid: u32, +} + +impl RecordHeader +{ + fn extract_record(&self, mut fobj: &File) -> Result + { + let mut info = RecordInfo::new(); + + info.event_id = self.event_id; + info.timestamp_ns = self.timestamp_ns; + info.record_pid = self.record_pid; + info.args_payload = vec![ + 0u8; + self.record_length as usize + - std::mem::size_of::() + ]; + fobj.read_exact(&mut info.args_payload) + .map_err(Error::ReadFile)?; + + Ok(info) + } +} + +impl ReadHeader for RecordHeader +{ + fn read_header(mut fobj: &File) -> Result + { + let mut raw_hdr = [0u8; 24]; + fobj.read_exact(&mut raw_hdr).map_err(Error::ReadFile)?; + + /* + * Safe because the size of record header (struct RecordHeader) + * is 24 bytes, which is ensured by simple trace backend. + */ + let hdr: RecordHeader = + unsafe { std::mem::transmute::<[u8; 24], RecordHeader>(raw_hdr) }; + Ok(hdr) + } +} + pub struct EventArgPayload {} trait Analyzer From patchwork Mon May 27 08:14:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13674765 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BC19DC25B7C for ; Mon, 27 May 2024 08:00:43 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sBVGj-0004lU-O8; Mon, 27 May 2024 03:59:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGI-0004e6-V9 for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:19 -0400 Received: from mgamail.intel.com ([192.198.163.17]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGF-0004WD-Ln for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716796756; x=1748332756; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yDPEzWhxxW02VCtTc002sd0aS9LHwc20MSP+Cf+0a50=; b=BhJrSc14LR1iWmd7y6l23e4euJiKVdxbZCXIo1BmDxQZqQ5Lds44W8tj q/KWmOnMcXOKS+lPSF93grgcN5iDWrEEs4bLQdzL1KF3QJU4cbxDGMpm7 lZoETuxwXDEJZk7PgruFXWIsVE4osDXczs9he9rIR522bKVru/HqxqfG9 5t2Oim3rDHH9C8m5Bs626iR9mQ5w9fSzv8s3LCyAtUq5Vdzb9hiUT/iMe 7FvoZZLYD+Na16kQTnUiAOeVlvkoNcL1YTqgCdAPOMi35UBVtbW+t1mkr nIF2mk2UoaNrh3z5pPPGjmb+5lVa0Veh/cHMMbOO67cLic2QYbZdGT9o9 Q==; X-CSE-ConnectionGUID: sK6v5+q0Timi6Q/WkKvreg== X-CSE-MsgGUID: HbXGj1cqTleeCHvLEZh/lA== X-IronPort-AV: E=McAfee;i="6600,9927,11084"; a="12967735" X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="12967735" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2024 00:59:15 -0700 X-CSE-ConnectionGUID: sDKw6Tu4SwiBxSLROdAUCg== X-CSE-MsgGUID: btAnab6dQImBbzT0Pzq7TA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="39084995" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by fmviesa005.fm.intel.com with ESMTP; 27 May 2024 00:59:11 -0700 From: Zhao Liu To: Stefan Hajnoczi , Mads Ynddal , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Daniel_P_?= =?utf-8?q?=2E_Berrang=C3=A9?= , Thomas Huth , Markus Armbruster Cc: qemu-devel@nongnu.org, Zhao Liu Subject: [RFC 4/6] scripts/simpletrace-rust: Parse and check trace recode file Date: Mon, 27 May 2024 16:14:19 +0800 Message-Id: <20240527081421.2258624-5-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240527081421.2258624-1-zhao1.liu@intel.com> References: <20240527081421.2258624-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.198.163.17; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -45 X-Spam_score: -4.6 X-Spam_bar: ---- X-Spam_report: (-4.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.145, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Refer to scripts/simpletrace.py, parse and check the simple trace backend binary trace file. Note, in order to keep certain backtrace information to get frame, adjust the cargo debug level for release version to "line-tables-only", which slows down the program, but is necessary. Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu --- scripts/simpletrace-rust/Cargo.lock | 79 +++++++++ scripts/simpletrace-rust/Cargo.toml | 4 + scripts/simpletrace-rust/src/main.rs | 253 ++++++++++++++++++++++++++- 3 files changed, 329 insertions(+), 7 deletions(-) diff --git a/scripts/simpletrace-rust/Cargo.lock b/scripts/simpletrace-rust/Cargo.lock index 3d815014eb44..37d80974ffe7 100644 --- a/scripts/simpletrace-rust/Cargo.lock +++ b/scripts/simpletrace-rust/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -60,6 +75,33 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "4.5.4" @@ -93,18 +135,48 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "is_terminal_polyfill" version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -158,10 +230,17 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + [[package]] name = "simpletrace-rust" version = "0.1.0" dependencies = [ + "backtrace", "clap", "once_cell", "regex", diff --git a/scripts/simpletrace-rust/Cargo.toml b/scripts/simpletrace-rust/Cargo.toml index 24a79d04e566..23a3179de01c 100644 --- a/scripts/simpletrace-rust/Cargo.toml +++ b/scripts/simpletrace-rust/Cargo.toml @@ -7,7 +7,11 @@ authors = ["Zhao Liu "] license = "GPL-2.0-or-later" [dependencies] +backtrace = "0.3" clap = "4.5.4" once_cell = "1.19.0" regex = "1.10.4" thiserror = "1.0.20" + +[profile.release] +debug = "line-tables-only" diff --git a/scripts/simpletrace-rust/src/main.rs b/scripts/simpletrace-rust/src/main.rs index b3b8baee7c66..f9a71d8dc243 100644 --- a/scripts/simpletrace-rust/src/main.rs +++ b/scripts/simpletrace-rust/src/main.rs @@ -13,17 +13,24 @@ mod trace; +use std::collections::HashMap; use std::env; use std::fs::File; use std::io::Error as IOError; use std::io::ErrorKind; use std::io::Read; +use std::mem::size_of; +use backtrace::Backtrace; use clap::Arg; use clap::Command; use thiserror::Error; use trace::Event; +const DROPPED_EVENT_ID: u64 = 0xfffffffffffffffe; +const HEADER_MAGIC: u64 = 0xf2b177cb0aa429b4; +const HEADER_EVENT_ID: u64 = 0xffffffffffffffff; + const RECORD_TYPE_MAPPING: u64 = 0; const RECORD_TYPE_EVENT: u64 = 1; @@ -32,10 +39,25 @@ pub enum Error { #[error("usage: {0} [--no-header] ")] CliOptionUnmatch(String), + #[error("Invalid event name ({0})")] + InvalidEventName(String), + #[error("Not a valid trace file, header id {0} != {1}")] + InvalidHeaderId(u64, u64), + #[error("Not a valid trace file, header magic {0} != {1}")] + InvalidHeaderMagic(u64, u64), #[error("Failed to read file: {0}")] ReadFile(IOError), + #[error( + "event {0} is logged but is not declared in the trace events \ + file, try using trace-events-all instead." + )] + UnknownEvent(String), #[error("Unknown record type ({0})")] UnknownRecType(u64), + #[error("Unknown version {0} of tracelog format!")] + UnknownVersion(u64), + #[error("Log format {0} not supported with this QEMU release!")] + UnsupportedVersion(u64), } pub type Result = std::result::Result; @@ -98,19 +120,22 @@ struct LogHeader version: u64, } +const LOG_HDR_LEN: usize = size_of::(); + impl ReadHeader for LogHeader { fn read_header(mut fobj: &File) -> Result { - let mut raw_hdr = [0u8; 24]; + let mut raw_hdr = [0u8; LOG_HDR_LEN]; fobj.read_exact(&mut raw_hdr).map_err(Error::ReadFile)?; /* * Safe because the size of log header (struct LogHeader) * is 24 bytes, which is ensured by simple trace backend. */ - let hdr = - unsafe { std::mem::transmute::<[u8; 24], LogHeader>(raw_hdr) }; + let hdr = unsafe { + std::mem::transmute::<[u8; LOG_HDR_LEN], LogHeader>(raw_hdr) + }; Ok(hdr) } } @@ -142,6 +167,8 @@ struct RecordHeader record_pid: u32, } +const REC_HDR_LEN: usize = size_of::(); + impl RecordHeader { fn extract_record(&self, mut fobj: &File) -> Result @@ -167,20 +194,232 @@ impl ReadHeader for RecordHeader { fn read_header(mut fobj: &File) -> Result { - let mut raw_hdr = [0u8; 24]; + let mut raw_hdr = [0u8; REC_HDR_LEN]; fobj.read_exact(&mut raw_hdr).map_err(Error::ReadFile)?; /* * Safe because the size of record header (struct RecordHeader) * is 24 bytes, which is ensured by simple trace backend. */ - let hdr: RecordHeader = - unsafe { std::mem::transmute::<[u8; 24], RecordHeader>(raw_hdr) }; + let hdr: RecordHeader = unsafe { + std::mem::transmute::<[u8; REC_HDR_LEN], RecordHeader>(raw_hdr) + }; Ok(hdr) } } -pub struct EventArgPayload {} +#[derive(Clone)] +pub struct EventArgPayload +{ + raw_val: Option, + raw_str: Option, +} + +impl EventArgPayload +{ + fn new(raw_val: Option, raw_str: Option) -> Self + { + EventArgPayload { raw_val, raw_str } + } + + fn get_payload_str( + offset: &mut usize, + args_payload: &[u8], + ) -> Result + { + let length = u32::from_le_bytes( + args_payload[*offset..(*offset + 4)].try_into().unwrap(), + ); + *offset += 4; + let raw_str: &[u8] = args_payload + .get(*offset..(*offset + length as usize)) + .unwrap(); + *offset += length as usize; + Ok(EventArgPayload::new( + None, + Some(String::from_utf8_lossy(raw_str).into_owned()), + )) + } + + fn get_payload_val( + offset: &mut usize, + args_payload: &[u8], + ) -> Result + { + let raw_val = u64::from_le_bytes( + args_payload[*offset..(*offset + 8)].try_into().unwrap(), + ); + *offset += 8; + Ok(EventArgPayload::new(Some(raw_val), None)) + } +} + +#[derive(Clone)] +struct EventEntry +{ + event: Event, + event_id: u64, + timestamp_ns: u64, + record_pid: u32, + rec_args: Vec, +} + +impl EventEntry +{ + fn new( + event: &Event, + event_id: u64, + timestamp_ns: u64, + record_pid: u32, + ) -> Self + { + EventEntry { + event: event.clone(), + event_id, + timestamp_ns, + record_pid, + rec_args: Vec::new(), + } + } +} + +fn get_mapping(mut fobj: &File) -> Result<(u64, String)> +{ + let mut event_id_buf = [0u8; 8]; + fobj.read_exact(&mut event_id_buf) + .map_err(Error::ReadFile)?; + let event_id = u64::from_le_bytes(event_id_buf); + + let mut len_buf = [0u8; 4]; + fobj.read_exact(&mut len_buf).map_err(Error::ReadFile)?; + + let len = u32::from_le_bytes(len_buf); + let mut name_buf = vec![0u8; len as usize]; + fobj.read_exact(&mut name_buf).map_err(Error::ReadFile)?; + let name = String::from_utf8(name_buf.clone()) + .map_err(|_| Error::InvalidEventName(format!("{:?}", name_buf)))?; + + Ok((event_id, name)) +} + +fn read_record(fobj: &File) -> Result +{ + let hdr = RecordHeader::read_header(fobj)?; + let info = hdr.extract_record(fobj)?; + Ok(info) +} + +fn read_trace_header(fobj: &File) -> Result<()> +{ + let log_hdr = LogHeader::read_header(fobj)?; + if log_hdr.event_id != HEADER_EVENT_ID { + return Err(Error::InvalidHeaderId(log_hdr.event_id, HEADER_EVENT_ID)); + } + if log_hdr.magic != HEADER_MAGIC { + return Err(Error::InvalidHeaderMagic(log_hdr.magic, HEADER_MAGIC)); + } + if ![0, 2, 3, 4].contains(&(log_hdr.version as i64)) { + return Err(Error::UnknownVersion(log_hdr.version)); + } + if log_hdr.version != 4 { + return Err(Error::UnsupportedVersion(log_hdr.version)); + } + Ok(()) +} + +fn read_trace_records( + events: &Vec, + fobj: &File, + analyzer: &mut Formatter, + read_header: bool, +) -> Result> +{ + /* backtrace::Backtrace needs this env variable. */ + env::set_var("RUST_BACKTRACE", "1"); + let bt = Backtrace::new(); + let raw_frame = bt.frames().first().unwrap(); + let frameinfo = raw_frame.symbols().first().unwrap(); + + let dropped_event = Event::build( + "Dropped_Event(uint64_t num_events_dropped)", + frameinfo.lineno().unwrap() + 1, + frameinfo.filename().unwrap().to_str().unwrap(), + ) + .unwrap(); + + let mut event_mapping = HashMap::new(); + for e in events { + event_mapping.insert(e.name.clone(), e.clone()); + } + + let drop_str = "dropped".to_string(); + event_mapping.insert(drop_str.clone(), dropped_event.clone()); + let mut event_id_to_name: HashMap = HashMap::new(); + event_id_to_name.insert(DROPPED_EVENT_ID, drop_str.clone()); + + if !read_header { + for (event_id, event) in events.iter().enumerate() { + event_id_to_name.insert(event_id as u64, event.name.clone()); + } + } + + let mut fmt_strs = Vec::new(); + loop { + let rtype = RecordType::read_type(fobj)?; + match rtype { + RecordType::Empty => { + break; + } + RecordType::Mapping => { + let (event_id, event_name) = + get_mapping(fobj).expect("Error reading mapping"); + event_id_to_name.insert(event_id, event_name); + continue; + } + RecordType::Event => { + let rec = read_record(fobj).expect("Error reading record"); + let event_name = + event_id_to_name.get(&rec.event_id).unwrap().to_string(); + let event = event_mapping + .get(&event_name) + .ok_or(Error::UnknownEvent(event_name))?; + + let mut entry = EventEntry::new( + event, + rec.event_id, + rec.timestamp_ns, + rec.record_pid, + ); + let mut offset = 0; + + for arg in &event.args.props { + let payload = if arg.is_string() { + EventArgPayload::get_payload_str( + &mut offset, + &rec.args_payload, + )? + } else { + EventArgPayload::get_payload_val( + &mut offset, + &rec.args_payload, + )? + }; + entry.rec_args.push(payload); + } + + let fmt = analyzer.process_event( + &entry.rec_args, + &entry.event, + entry.event_id, + entry.timestamp_ns, + entry.record_pid, + )?; + fmt_strs.push(fmt); + } + } + } + Ok(fmt_strs) +} trait Analyzer { From patchwork Mon May 27 08:14:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13674767 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D83E8C25B78 for ; Mon, 27 May 2024 08:01:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sBVGx-0004of-Un; Mon, 27 May 2024 03:59:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGK-0004eQ-J5 for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:21 -0400 Received: from mgamail.intel.com ([192.198.163.17]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGI-0004Vj-Q7 for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716796759; x=1748332759; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yDnU3NpuzzE9vncxdnu3+nFMkkDKrrnqtTuk0bRk1Ps=; b=IP/gMv3U3pGX4NxNMthayZ0KqV+f5j2WZ3X5fOLPPb3wfD4TVzMmn1Ib SbaS1H4Btvmw4q/P5WAxO22GeYuphha601pWFi9G3MCZii+6RPNq+jII2 zDk0XTDaW5oPQsWzH7svVN28t9gYhRq8rt95Kk3e1fw9hUVf4RPUXjWdk 3O24j9lybyOeYIBTNlTrLcJiiBGcyH0TEg+1hgtTCt1pj0CbJVRYim50M RcZ3PGjV41TlDrAY6EvPPA0lqwKxoj8xr0GQrCRvz6VgGFq13iR5Pg9yL WaSL+w9hFYkI+Lmy3mkfzqtE7vkZT+XUcDSL9cBM2OqappIN+QHVYTOKj A==; X-CSE-ConnectionGUID: k7p1A+qdRPi+OqIMFmdJhw== X-CSE-MsgGUID: wxf/bMZ/Q2awhq2pYfrTSQ== X-IronPort-AV: E=McAfee;i="6600,9927,11084"; a="12967744" X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="12967744" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2024 00:59:18 -0700 X-CSE-ConnectionGUID: 2O0Hbl4/RhiMr66BWSZhTQ== X-CSE-MsgGUID: 1/mI9UGmTLWYatbApChIQA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="39085008" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by fmviesa005.fm.intel.com with ESMTP; 27 May 2024 00:59:15 -0700 From: Zhao Liu To: Stefan Hajnoczi , Mads Ynddal , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Daniel_P_?= =?utf-8?q?=2E_Berrang=C3=A9?= , Thomas Huth , Markus Armbruster Cc: qemu-devel@nongnu.org, Zhao Liu Subject: [RFC 5/6] scripts/simpletrace-rust: Format simple trace output Date: Mon, 27 May 2024 16:14:20 +0800 Message-Id: <20240527081421.2258624-6-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240527081421.2258624-1-zhao1.liu@intel.com> References: <20240527081421.2258624-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.198.163.17; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -45 X-Spam_score: -4.6 X-Spam_bar: ---- X-Spam_report: (-4.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.145, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Format simple trace output, as in the Python version. Further, complete the trace file input and trace log output. Additionally, remove `#![allow(dead_code)]` and `#![allow(unused_variables)]` to allow rustc to do related checks. Suggested-by: Paolo Bonzini Signed-off-by: Zhao Liu --- scripts/simpletrace-rust/src/main.rs | 80 ++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/scripts/simpletrace-rust/src/main.rs b/scripts/simpletrace-rust/src/main.rs index f9a71d8dc243..ba4b96efb066 100644 --- a/scripts/simpletrace-rust/src/main.rs +++ b/scripts/simpletrace-rust/src/main.rs @@ -8,23 +8,25 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -#![allow(dead_code)] -#![allow(unused_variables)] - mod trace; use std::collections::HashMap; use std::env; +use std::fmt; use std::fs::File; +use std::io::stdout; use std::io::Error as IOError; use std::io::ErrorKind; use std::io::Read; +use std::io::Write; use std::mem::size_of; use backtrace::Backtrace; use clap::Arg; use clap::Command; use thiserror::Error; +use trace::read_events; +use trace::Error as TraceError; use trace::Event; const DROPPED_EVENT_ID: u64 = 0xfffffffffffffffe; @@ -45,8 +47,12 @@ pub enum Error InvalidHeaderId(u64, u64), #[error("Not a valid trace file, header magic {0} != {1}")] InvalidHeaderMagic(u64, u64), + #[error("Failed to open file: {0}")] + OpenFile(IOError), #[error("Failed to read file: {0}")] ReadFile(IOError), + #[error("Failed to read trace: {0}")] + ReadTrace(TraceError), #[error( "event {0} is logged but is not declared in the trace events \ file, try using trace-events-all instead." @@ -58,6 +64,8 @@ pub enum Error UnknownVersion(u64), #[error("Log format {0} not supported with this QEMU release!")] UnsupportedVersion(u64), + #[error("Failed to write trace: {0}")] + WriteTrace(IOError), } pub type Result = std::result::Result; @@ -254,6 +262,30 @@ impl EventArgPayload } } +impl fmt::Display for EventArgPayload +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result + { + if let Some(s) = &self.raw_str { + write!(fmt, "{}", s) + } else { + write!(fmt, "") + } + } +} + +impl fmt::LowerHex for EventArgPayload +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result + { + if let Some(v) = self.raw_val { + write!(fmt, "{:x}", v) + } else { + write!(fmt, "") + } + } +} + #[derive(Clone)] struct EventEntry { @@ -485,10 +517,35 @@ impl Analyzer for Formatter event: &Event, timestamp_ns: u64, pid: u32, - event_id: u64, + _event_id: u64, ) -> Result { - let fmt_str = String::new(); + if self.last_timestamp_ns.is_none() { + self.last_timestamp_ns = Some(timestamp_ns); + } + + let fields: Vec = rec_args + .iter() + .zip(event.args.props.iter()) + .map(|(arg, prop)| { + if prop.is_string() { + format!("{}={}", prop.name, arg) + } else { + format!("{}=0x{:x}", prop.name, arg) + } + }) + .collect(); + + let delta_ns = + timestamp_ns as f64 - self.last_timestamp_ns.unwrap() as f64; + self.last_timestamp_ns = Some(timestamp_ns); + let fmt_str = format!( + "{} {:.3} pid={} {}\n", + event.name, + delta_ns / 1000.0, + pid, + fields.join(" "), + ); Ok(fmt_str) } @@ -501,7 +558,20 @@ fn process( read_header: bool, ) -> Result<()> { + let events = read_events(event_path).map_err(Error::ReadTrace)?; + let trace_fobj = File::open(trace_path).map_err(Error::OpenFile)?; + if read_header { + read_trace_header(&trace_fobj)?; + } + analyzer.begin(); + + let rec_strs = + read_trace_records(&events, &trace_fobj, analyzer, read_header)?; + let mut lock = stdout().lock(); + lock.write_all(rec_strs.join("").as_ref()) + .map_err(Error::WriteTrace)?; + analyzer.end(); Ok(()) From patchwork Mon May 27 08:14:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Liu X-Patchwork-Id: 13674778 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A692EC25B7C for ; Mon, 27 May 2024 08:02:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sBVJC-0007cf-VC; Mon, 27 May 2024 04:02:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGb-0004jf-Cb for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:37 -0400 Received: from mgamail.intel.com ([192.198.163.17]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sBVGL-0004Xs-Uc for qemu-devel@nongnu.org; Mon, 27 May 2024 03:59:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1716796762; x=1748332762; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WeM/edYd9mSl+ORqUJfueVLUMLCrkQ8sggeY8fdRPiE=; b=MjlBMPo+izQKCzR4fg1P2PX1DNvyIHdRJlw++JX38Fw2vGQMGF7oL1Fj KrHZL4pJ+8JuPivlb951vi6e5tx7n/69oqPmAOHvSHHEsvQKhxCddj/BO 6S1cPTer0n8JkDKGn+y2i8PCvKjbTEAB2XTNOlI5Blk3wGHdg8pbGx9Xh pkPRSWYDE11PM8MT5uDyDejB9C+NwXV1N5/kghntCM/6d5okurEz5V0IR OgLcUQGg14AKqD2J6dG9eZz1wZuBN9P+t4DtrUQivqWBGrxmS6lWe29nR LijIo1ISJwUZadyTTaPrY2jjFtCKyEc0D55yakPnrYaCXJvAcGosoFyh0 g==; X-CSE-ConnectionGUID: d4KGOxdjQwyWH+t0i+Hpcw== X-CSE-MsgGUID: gg8WceUUR3+VOjTD+B7/6g== X-IronPort-AV: E=McAfee;i="6600,9927,11084"; a="12967754" X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="12967754" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa111.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2024 00:59:21 -0700 X-CSE-ConnectionGUID: atWCFp4JQ9uMGfR422ZL9g== X-CSE-MsgGUID: Bqrf2WGoQxm3+u/O1eB1fw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,192,1712646000"; d="scan'208";a="39085018" Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.36]) by fmviesa005.fm.intel.com with ESMTP; 27 May 2024 00:59:18 -0700 From: Zhao Liu To: Stefan Hajnoczi , Mads Ynddal , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , =?utf-8?q?Daniel_P_?= =?utf-8?q?=2E_Berrang=C3=A9?= , Thomas Huth , Markus Armbruster Cc: qemu-devel@nongnu.org, Zhao Liu Subject: [RFC 6/6] docs/tracing: Add simpletrace-rust section Date: Mon, 27 May 2024 16:14:21 +0800 Message-Id: <20240527081421.2258624-7-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240527081421.2258624-1-zhao1.liu@intel.com> References: <20240527081421.2258624-1-zhao1.liu@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.198.163.17; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.145, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, T_SPF_HELO_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Describe how to compile and use this Rust version program. And also define the Rust code contribution requirements. Signed-off-by: Zhao Liu --- docs/devel/tracing.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/devel/tracing.rst b/docs/devel/tracing.rst index 043bed7fd0fc..9f31fa38f9bc 100644 --- a/docs/devel/tracing.rst +++ b/docs/devel/tracing.rst @@ -273,6 +273,41 @@ You must ensure that the same "trace-events-all" file was used to build QEMU, otherwise trace event declarations may have changed and output will not be consistent. +Simpletrace-rust +---------------- + +Simpletrace-rust (scripts/Simpletrace-rust) is a Rust implementation of +simpletrace.py, with the same command line arguments as the Python script. + +Simpletrace-rust has faster trace parsing compared to the Python version. + +The script is compiled by:: + + cargo build --manifest-path ./scripts/simpletrace-rust/Cargo.toml --release + +Or under scripts/simpletrace-rust, just use:: + + cargo build --release + +The script also takes the "trace-events-all" file and the binary trace:: + + ./scripts/simpletrace-rust/target/release/simpletrace-rust trace-events-all \ + trace-12345 + +Any contribution to Simpletrace-rust needs to do the following checks: + +Compilation check:: + + cargo build + +Clippy check:: + + cargo clippy + +Code style check:: + + cargo +nightly fmt --check + Ftrace ------