lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20240919215107.2263552-5-stefan.ene@intel.com>
Date: Thu, 19 Sep 2024 14:51:04 -0700
From: Stefan@....codeaurora.org, Ene@....codeaurora.org
To: peterz@...radead.org,
	mingo@...hat.com,
	acme@...nel.org,
	namhyung@...nel.org,
	mark.rutland@....com,
	alexander.shishkin@...ux.intel.com,
	jolsa@...nel.org,
	irogers@...gle.com,
	adrian.hunter@...el.com,
	kan.liang@...ux.intel.com,
	linux-perf-users@...r.kernel.org,
	linux-kernel@...r.kernel.org
Cc: vinicius.gomes@...el.com,
	stefan.ene@...el.com,
	stef_an_ene@...look.com
Subject: [RFC v1 3/3] C and Rust support for perf script

From: Stefan Ene <stefan.ene@...el.com>

[PATCH 3/3] added the Rust sample script

---
 tools/perf/new_script_templates/README   |  61 +++++++++++--
 tools/perf/new_script_templates/lib.rs   | 108 +++++++++++++++++++++++
 tools/perf/new_script_templates/script.c |   6 ++
 tools/perf/util/new_script_rs_lib.h      |  35 ++++++++
 4 files changed, 204 insertions(+), 6 deletions(-)
 create mode 100644 tools/perf/new_script_templates/lib.rs
 create mode 100644 tools/perf/util/new_script_rs_lib.h

diff --git a/tools/perf/new_script_templates/README b/tools/perf/new_script_templates/README
index c2a55a65d444..f16a9759d37e 100644
--- a/tools/perf/new_script_templates/README
+++ b/tools/perf/new_script_templates/README
@@ -2,15 +2,64 @@ Linux kernel additions for C and Rust script support inside the perf-script tool
 
 Steps to use new feature:
 
-    First, use the provided update_perf_tools.sh script to make sure your perf toolset is up to date with the latest implementation:
-        $ bash update_perf_tools.sh
+    First, use run the following lines to make sure your perf toolset is up to date with the latest implementation:
+        $ cd ./tools/perf/
+        $ make
+        $ sudo cp perf /usr/bin
+        $ perf --version
+    Now, you can make use of our new features!
+
 
     a) For C scripts:
-        1. Use the default C template test.c to write your own custom perf event processing
+        1. Use the default C template in tools/perf/new_script_templates/script.c to write your own custom perf event processing
 
         2. Compile the C script into a dynamic library using the following two commands:
-            $ gcc -c -I ~/include -fpic new_script_templates/script.c
-            $ gcc -shared -o test.so new_script_templates/script.o
+            $ gcc -c -I ~/include -fpic script.c
+            $ gcc -shared -o script.so script.o
 
         3. Call the new perf script option to use the newly created .so file using the command:
-            $ sudo perf script --new_script new_script_templates/script.so
\ No newline at end of file
+            $ sudo perf script --new_script script.so
+
+
+     b) For Rust scripts:
+          1. Create a new Rust project using Cargo:
+               $ cargo new rslib_script --lib
+               $ cd rslib_script
+          
+          2. In the Cargo.toml file, specify the crate type as a dynamic library as follows:
+               [lib]
+               crate-type = ["cdylib"]
+          
+          3. Use the default Rust template in tools/perf/new_script_templates/lib.rs to write your own custom perf event processing, and store it into src/lib.rs inside of the Rust project folder.
+
+          4. Compile the Rust project using Cargo:
+               $ cargo build --release
+          
+          5. Call the new perf script option to use the newly created /target/release/librslib.so within the Rust project using the followig command:
+               $  sudo perf script --new_script rslib/target/release/librslib.so
+
+Enjoy using the new scripting languages for an added bonus of usability and performance over the existent Python and Perl options in the upstream kernel code. 
+
+
+<!-- ============================= -->
+
+This section contains some initial benchmark results on the Intel Lab machine using the perf script tools on a 4026869-byte perf.data file.
+
+Process ----- Time
+
+> Perf tool vanilla:
+perf script raw: 1.425s
+perf script names: 0.915s
+perf script Python: 1.334s
+perf script Perl: 2.210s
+
+
+> Pre-optimizations:
+new_script raw C: 0.284s
+new_script raw Rust: 0.607s
+
+> Post-optimizations:
+new_script raw C batch=1MB: 0.306s 
+new_script raw C batch=2MB: 0.301s 
+new_script raw C batch=4MB: 0.296s 
+new_script raw Rust batch=1MB: 0.262s
\ No newline at end of file
diff --git a/tools/perf/new_script_templates/lib.rs b/tools/perf/new_script_templates/lib.rs
new file mode 100644
index 000000000000..1249d9e9099b
--- /dev/null
+++ b/tools/perf/new_script_templates/lib.rs
@@ -0,0 +1,108 @@
+// Stefan Ene's code, under Intel - Linux Kernel Team
+/*
+ * code for new perf script custom C script template
+ *
+ */
+
+ use std::os::raw::{c_char, c_int, c_void};
+ use std::slice;
+ use std::fmt::Write;
+ 
+ // =================== Needed stuff, DO NOT CHANGE ===================
+ 
+ #[repr(C)]
+ struct NewScript {
+     file: *mut c_char,
+     handle: *mut c_void,
+ 
+     begin: extern "C" fn(*mut c_void, *mut c_void),
+     end: extern "C" fn(*mut c_void, *mut c_void),
+ 
+     process_file_header: extern "C" fn(*mut c_void, *mut c_void) -> c_int,
+     process_event_header: extern "C" fn(*mut c_void, *mut c_void) -> c_int,
+     process_event_raw_data: extern "C" fn(*mut c_void, c_int, *mut c_void) -> c_int,
+ }
+ 
+ #[repr(C)]
+ struct ProcessedFileHeader {
+     size: u64,
+     data_size: u64,
+     data_offset: u64,
+ }
+ 
+ #[repr(C)]
+ struct ProcessedEventHeader {
+     event_type: u32,
+     misc: u16,
+     size: u16,
+ }
+ 
+ //  =================== Editable funtions begin ===================
+ 
+ #[no_mangle]
+ pub extern "C" fn print_begin(_data: *mut c_void, _ctx: *mut c_void) {
+     println!(">> in trace_begin with Rust");
+ }
+ 
+ #[no_mangle]
+ pub extern "C" fn process_file_header(data: *mut c_void, _ctx: *mut c_void) -> c_int {
+     if data.is_null() {
+         println!("> Error dynamically processing file header");
+         return -1;
+     }
+ 
+     let fh = unsafe { &*(data as *const ProcessedFileHeader) };
+ 
+     println!("\nFile header: size={:x}, data.size={}, data.offset={}", fh.size, fh.data_size, fh.data_offset);
+ 
+     0
+ }
+ 
+ #[no_mangle]
+ pub extern "C" fn process_event_header(data: *mut c_void, _ctx: *mut c_void) -> c_int {
+     if data.is_null() {
+         println!("> Error dynamically processing event header");
+         return -1;
+     }
+ 
+     let evh = unsafe { &*(data as *const ProcessedEventHeader) };
+ 
+     println!("\nRS Event header: size={}, type={}, misc={}", evh.size, evh.event_type, evh.misc);
+ 
+     0
+ }
+ 
+ #[no_mangle]
+ pub extern "C" fn process_event_raw_data(data: *mut c_void, size: c_int, _ctx: *mut c_void) -> c_int {
+     let byte_data = unsafe { slice::from_raw_parts(data as *const u8, size as usize) };
+     let mut output = String::new();
+ 
+     for (i, &byte) in byte_data.iter().enumerate() {
+         if i % 16 == 0 {
+             output.push('\n');
+         }
+         write!(&mut output, "{:02x} ", byte).unwrap();
+     }
+ 
+     println!("{}", output);
+     0
+ }
+ 
+ #[no_mangle]
+ pub extern "C" fn print_end(_data: *mut c_void, _ctx: *mut c_void) {
+     println!("\n>> in trace_end");
+ }
+ 
+ // =================== Needed stuff begin, DO NOT CHANGE ===================
+ 
+ #[no_mangle]
+ pub extern "C" fn initialize_new_script(s: *mut NewScript) {
+     if !s.is_null() {
+         let script = unsafe { &mut *s };
+         script.begin = print_begin;
+         script.end = print_end;
+         script.process_file_header = process_file_header;
+         script.process_event_header = process_event_header;
+         script.process_event_raw_data = process_event_raw_data;
+     }
+ }
\ No newline at end of file
diff --git a/tools/perf/new_script_templates/script.c b/tools/perf/new_script_templates/script.c
index e4942ba689db..787f67424d5e 100644
--- a/tools/perf/new_script_templates/script.c
+++ b/tools/perf/new_script_templates/script.c
@@ -1,3 +1,9 @@
+// Stefan Ene's code, under Intel - Linux Kernel Team
+/*
+ * code for new perf script custom C script template
+ *
+ */
+
 #include <stdlib.h>
 #include <stdio.h>
 
diff --git a/tools/perf/util/new_script_rs_lib.h b/tools/perf/util/new_script_rs_lib.h
new file mode 100644
index 000000000000..4a8d6f71b122
--- /dev/null
+++ b/tools/perf/util/new_script_rs_lib.h
@@ -0,0 +1,35 @@
+// Stefan Ene's code, under Intel - Linux Kernel Team
+/*
+ * new_script_lib_rs.h: header file for new_script Rust FFI
+ *
+ */
+
+#ifndef NEW_SCRIPT_LIB_RS_H
+#define NEW_SCRIPT_LIB_RS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+// Match the struct definitions with the Rust code
+struct NewScript {
+    char		*file;
+    void        *handle;
+
+    void (*begin)(void *data, void *ctx);
+	void (*end)(void *data, void *ctx);
+
+    int (*process_file_header)(void *data, void *ctx);
+    int (*process_event_header)(void *data, void *ctx);
+    int (*process_event_raw_data)(void *data, const int size, void *ctx);
+};
+
+void initialize_new_script(struct NewScript* s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NEW_SCRIPT_LIB_RS_H
\ No newline at end of file
-- 
2.46.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ