From c73fc444293bc97101b114bb91ade76e436c3d05 Mon Sep 17 00:00:00 2001 From: Seimizu Joukan Date: Mon, 24 Nov 2025 08:49:35 +0900 Subject: [PATCH] Fix compiliation and clippy warnings. --- build.rs | 2 +- eglswapbuffers/eglswapbuffers.rs | 4 +- execsnoop_pb/execsnoop_pb.rs | 4 +- execsnoop_rb/execsnoop_rb.rs | 4 +- funccount/funccount.rs | 28 +++-- lib/symbolanalyzer.rs | 4 +- malloc_free/malloc_free.rs | 84 +++++++-------- profile/profile.rs | 1 + segfault_analyzer/segfault_analyzer.rs | 138 ++++++++++++++++--------- 9 files changed, 153 insertions(+), 116 deletions(-) diff --git a/build.rs b/build.rs index 4f5f1c0..40804e2 100644 --- a/build.rs +++ b/build.rs @@ -168,7 +168,7 @@ fn main() { .log_console(false) .build(); - let applications = vec![ + let applications = [ "execsnoop_pb", "execsnoop_rb", "funccount", diff --git a/eglswapbuffers/eglswapbuffers.rs b/eglswapbuffers/eglswapbuffers.rs index e4b9fba..6b33075 100644 --- a/eglswapbuffers/eglswapbuffers.rs +++ b/eglswapbuffers/eglswapbuffers.rs @@ -140,7 +140,7 @@ fn process_events( } } - for (_, ((pid, tgid, comm_bytes), count_vec)) in hash_result.iter_mut().enumerate() { + for ((pid, tgid, comm_bytes), count_vec) in hash_result.iter_mut() { let comm = unsafe { bytes_to_string(comm_bytes.as_ptr()) }; println!(); println!("Probe: {}", probe); @@ -157,7 +157,7 @@ fn process_events( } } - for (_i, v) in count_vec.iter().enumerate() { + for v in count_vec.iter() { print!("{:8}ms {:5}|", v.duration_ms, v.count); println!("{}", "*".repeat((v.count * 60 / max_count) as usize)); } diff --git a/execsnoop_pb/execsnoop_pb.rs b/execsnoop_pb/execsnoop_pb.rs index 8f3d7b1..7c81f1c 100644 --- a/execsnoop_pb/execsnoop_pb.rs +++ b/execsnoop_pb/execsnoop_pb.rs @@ -292,7 +292,9 @@ fn main() -> Result<(), JtraceError> { jdebug!(args_count = event.args_count); while parsed_cnt < event.args_count { let p = &event.args[index..index + 16]; - let arg = unsafe { bytes_to_string(std::mem::transmute(p.as_ptr())) }; + let arg = unsafe { + bytes_to_string(std::mem::transmute::<*const u8, *const i8>(p.as_ptr())) + }; arg_parsed.push(arg.clone()); jdebug!(parsed_cnt = parsed_cnt, index = index, arg = arg); diff --git a/execsnoop_rb/execsnoop_rb.rs b/execsnoop_rb/execsnoop_rb.rs index 857da6a..a65ec52 100644 --- a/execsnoop_rb/execsnoop_rb.rs +++ b/execsnoop_rb/execsnoop_rb.rs @@ -292,7 +292,9 @@ fn main() -> Result<(), JtraceError> { jdebug!(args_count = event.args_count); while parsed_cnt < event.args_count { let p = &event.args[index..index + 16]; - let arg = unsafe { bytes_to_string(std::mem::transmute(p.as_ptr())) }; + let arg = unsafe { + bytes_to_string(std::mem::transmute::<*const u8, *const i8>(p.as_ptr())) + }; arg_parsed.push(arg.clone()); jdebug!(parsed_cnt = parsed_cnt, index = index, arg = arg); diff --git a/funccount/funccount.rs b/funccount/funccount.rs index b8dd035..848e146 100644 --- a/funccount/funccount.rs +++ b/funccount/funccount.rs @@ -628,16 +628,20 @@ fn main() -> Result<(), FuncCountError> { .attach_printable("No symbol found"); } + let trace_regex = + Regex::new(r"t:(.+):(.+)").map_err(|_| Report::new(FuncCountError::Unexpected))?; + let uprobe_regex = + Regex::new(r"u:(.+):(.+)").map_err(|_| Report::new(FuncCountError::Unexpected))?; + let kprobe_regex = + Regex::new(r"(k:)*(.+)").map_err(|_| Report::new(FuncCountError::Unexpected))?; + for arg in sym_to_trace { let mut processed = false; jdebug!("arg: {}", arg); - let tre = - Regex::new(r"t:(.+):(.+)").map_err(|_| Report::new(FuncCountError::Unexpected))?; - - if tre.is_match(arg) { - for g in tre.captures_iter(arg) { + if trace_regex.is_match(arg) { + for g in trace_regex.captures_iter(arg) { let pattern = format!("^{}:{}$", &g[1], &g[2]); let re = Regex::new(&pattern) .map_err(|_| Report::new(FuncCountError::Unexpected))?; @@ -688,11 +692,8 @@ fn main() -> Result<(), FuncCountError> { } } - let tre = - Regex::new(r"u:(.+):(.+)").map_err(|_| Report::new(FuncCountError::Unexpected))?; - - if tre.is_match(arg) { - for g in tre.captures_iter(arg) { + if uprobe_regex.is_match(arg) { + for g in uprobe_regex.captures_iter(arg) { let file = &g[1]; let elf = ElfFile::new(file).change_context(FuncCountError::SymbolAnalyzerError)?; @@ -750,11 +751,8 @@ fn main() -> Result<(), FuncCountError> { continue; } - let tre = - Regex::new(r"(k:)*(.+)").map_err(|_| Report::new(FuncCountError::Unexpected))?; - - if tre.is_match(arg) { - for g in tre.captures_iter(arg) { + if kprobe_regex.is_match(arg) { + for g in kprobe_regex.captures_iter(arg) { let mut func_names = vec![]; let pattern = format!("^{}$", &g[2]); let re = Regex::new(&pattern) diff --git a/lib/symbolanalyzer.rs b/lib/symbolanalyzer.rs index c2463b0..5a47864 100644 --- a/lib/symbolanalyzer.rs +++ b/lib/symbolanalyzer.rs @@ -298,14 +298,14 @@ impl KernelMap { ktype, name, module, - len: u64::max_value(), + len: u64::MAX, }); } /* Descending order */ kallsyms.sort_by(|a, b| b.addr().partial_cmp(&a.addr()).unwrap()); - let mut addr = u64::max_value(); + let mut addr = u64::MAX; for v in kallsyms.iter_mut() { if addr >= v.addr() { diff --git a/malloc_free/malloc_free.rs b/malloc_free/malloc_free.rs index b1618d5..46a9b2e 100644 --- a/malloc_free/malloc_free.rs +++ b/malloc_free/malloc_free.rs @@ -1,9 +1,7 @@ #[allow(unused)] use { byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}, - chrono, clap::Parser, - ctrlc, error_stack::{Report, Result, ResultExt}, jlogger_tracing::{ jdebug, jerror, jinfo, jtrace, jwarn, JloggerBuilder, LevelFilter, LogTimeFormat, @@ -99,6 +97,7 @@ macro_rules! output_writeln { }; } +#[allow(unused_macros)] macro_rules! output_write { ($output:expr, $($arg:tt)*) => { $output.write_formatted(format_args!($($arg)*)) @@ -459,7 +458,7 @@ fn calculate_process_statistics_from_records( // Calculate age information from the eBPF-maintained fields let oldest_age_str = if record.oldest_alloc_timestamp > 0 { calculate_allocation_age(record.oldest_alloc_timestamp) - .map(|age| format_age(age)) + .map(format_age) .unwrap_or_else(|_| "unknown".to_string()) } else { "unknown".to_string() @@ -469,7 +468,7 @@ fn calculate_process_statistics_from_records( // Calculate average timestamp, then convert to age let avg_timestamp = record.total_age_sum_ns / record.total_unfreed_count as u64; calculate_allocation_age(avg_timestamp) - .map(|age| format_age(age)) + .map(format_age) .unwrap_or_else(|_| "unknown".to_string()) } else { "unknown".to_string() @@ -584,14 +583,13 @@ fn find_libc_path_from_proc_maps() -> Option { }; let reader = BufReader::new(file); - for line in reader.lines() { - if let Ok(l) = line { - if l.contains("libc.so.6") && l.contains(".so") { - // Extract the path, which is usually the last part of the line after a space - if let Some(path_str) = l.split_whitespace().last() { - jinfo!("Found libc.so.6 in proc maps: {}", path_str); - return Some(path_str.to_string()); - } + // Using map_while() to avoid endless loop on read errors + for line in reader.lines().map_while(|l| l.ok()) { + if line.contains("libc.so.6") && line.contains(".so") { + // Extract the path, which is usually the last part of the line after a space + if let Some(path_str) = line.split_whitespace().last() { + jinfo!("Found libc.so.6 in proc maps: {}", path_str); + return Some(path_str.to_string()); } } } @@ -749,6 +747,7 @@ struct Cli { use std::io::{BufWriter, Write}; /// Trait for writing output to different destinations (stdout or file) +#[allow(dead_code)] trait OutputWriter { fn write_line(&mut self, line: &str) -> Result<(), JtraceError>; fn write_formatted(&mut self, args: std::fmt::Arguments) -> Result<(), JtraceError>; @@ -843,6 +842,7 @@ impl OutputManager { }) } + #[allow(dead_code)] fn write_line(&mut self, line: &str) -> Result<(), JtraceError> { self.writer.write_line(line) } @@ -1030,31 +1030,29 @@ fn process_events( tid )?; } + } else if min_age_filter.is_some() { + output_writeln!( + output, + "{:<4} {:<8} {} malloc: {:<10}({}) free: {:<10}({})", + idx, + event.size, + age_info, + comm, + tid, + free_comm, + free_tid + )?; } else { - if min_age_filter.is_some() { - output_writeln!( - output, - "{:<4} {:<8} {} malloc: {:<10}({}) free: {:<10}({})", - idx, - event.size, - age_info, - comm, - tid, - free_comm, - free_tid - )?; - } else { - output_writeln!( - output, - "{:<4} {:<8} malloc: {:<10}({}) free: {:<10}({})", - idx, - event.size, - comm, - tid, - free_comm, - free_tid - )?; - } + output_writeln!( + output, + "{:<4} {:<8} malloc: {:<10}({}) free: {:<10}({})", + idx, + event.size, + comm, + tid, + free_comm, + free_tid + )?; } idx += 1; @@ -1285,12 +1283,12 @@ fn print_statistics( output_writeln!(output, "\n=== Statistics ===")?; // Read statistics from all CPUs and sum them up (expanded for age statistics) - let mut stats_totals = vec![0u64; 24]; // Increased from 20 to 24 + let mut stats_totals = [0u64; 24]; // Increased from 20 to 24 for cpu in 0..num_cpus::get() { // Perform periodic flush during statistics collection output.flush_if_needed(); - for stat_idx in 0..24 { + for (stat_idx, v) in stats_totals.iter_mut().enumerate() { // Increased from 20 to 24 let key_bytes = (stat_idx as u32).to_ne_bytes(); if let Some(data) = stats_map @@ -1304,7 +1302,7 @@ fn print_statistics( cursor.set_position(0); value = cursor.read_u64::().unwrap_or(0); } - stats_totals[stat_idx] += value; + *v += value; } } } @@ -1442,11 +1440,7 @@ fn handle_output_error(error: &Report, output_file: Option<&std::pa } /// Helper function for handling file operations with comprehensive error mapping -fn handle_file_operation( - operation: &str, - path: &std::path::PathBuf, - f: F, -) -> Result +fn handle_file_operation(operation: &str, path: &Path, f: F) -> Result where F: FnOnce() -> std::io::Result, { @@ -1466,7 +1460,7 @@ where }; Report::new(JtraceError::FileError { - path: path.clone(), + path: path.to_path_buf(), operation: operation.to_string(), source: error_msg, }) diff --git a/profile/profile.rs b/profile/profile.rs index 394f36e..31e8140 100644 --- a/profile/profile.rs +++ b/profile/profile.rs @@ -276,6 +276,7 @@ pub fn process_data( output_file = Some(BufWriter::new( fs::OpenOptions::new() .create(true) + .truncate(true) .write(true) .read(true) .open(file_name) diff --git a/segfault_analyzer/segfault_analyzer.rs b/segfault_analyzer/segfault_analyzer.rs index 3a837a5..6063e39 100644 --- a/segfault_analyzer/segfault_analyzer.rs +++ b/segfault_analyzer/segfault_analyzer.rs @@ -1,7 +1,6 @@ #[allow(unused)] use { clap::Parser, - ctrlc, error_stack::{Report, Result, ResultExt}, jlogger_tracing::{jdebug, jerror, jinfo, jtrace, jwarn, JloggerBuilder, LevelFilter}, libbpf_rs::{ @@ -17,7 +16,7 @@ use { path::PathBuf, sync::{ atomic::{AtomicBool, Ordering}, - Arc, + Arc, Mutex, }, time::{Duration, SystemTime, UNIX_EPOCH}, }, @@ -252,6 +251,12 @@ pub struct StatisticsManager { start_time: SystemTime, } +impl Default for StatisticsManager { + fn default() -> Self { + Self::new() + } +} + impl StatisticsManager { pub fn new() -> Self { let now = SystemTime::now(); @@ -613,7 +618,7 @@ impl ConsoleProcessor { } // Ensure we have an exec map for this PID - if let Err(_) = self.ensure_exec_map(pid) { + if self.ensure_exec_map(pid).is_err() { self.symbol_cache.insert(addr, None); return None; } @@ -983,7 +988,7 @@ impl JsonProcessor { } // Ensure we have an exec map for this PID - if let Err(_) = self.ensure_exec_map(pid) { + if self.ensure_exec_map(pid).is_err() { self.symbol_cache.insert(addr, None); return None; } @@ -1767,14 +1772,14 @@ static mut EVENT_PROCESSOR: Option> = None; static mut PROCESS_NAME_FILTER: Option = None; /// Global event statistics -static mut EVENT_STATS: EventStats = EventStats { +static EVENT_STATS: Mutex = Mutex::new(EventStats { events_received: 0, events_parsed: 0, events_processed: 0, events_filtered_name: 0, parse_errors: 0, process_errors: 0, -}; +}); /// Event processing statistics #[derive(Debug)] @@ -1787,6 +1792,54 @@ struct EventStats { process_errors: u64, } +fn events_received() -> u64 { + EVENT_STATS.lock().unwrap().events_received +} + +fn events_parsed() -> u64 { + EVENT_STATS.lock().unwrap().events_parsed +} + +fn events_processed() -> u64 { + EVENT_STATS.lock().unwrap().events_processed +} + +fn events_filtered_name() -> u64 { + EVENT_STATS.lock().unwrap().events_filtered_name +} + +fn events_parse_errors() -> u64 { + EVENT_STATS.lock().unwrap().parse_errors +} + +fn events_process_errors() -> u64 { + EVENT_STATS.lock().unwrap().process_errors +} + +fn increase_events_received() { + EVENT_STATS.lock().unwrap().events_received += 1; +} + +fn increase_events_parsed() { + EVENT_STATS.lock().unwrap().events_parsed += 1; +} + +fn increase_events_processed() { + EVENT_STATS.lock().unwrap().events_processed += 1; +} + +fn increase_events_filtered_name() { + EVENT_STATS.lock().unwrap().events_filtered_name += 1; +} + +fn increase_parse_errors() { + EVENT_STATS.lock().unwrap().parse_errors += 1; +} + +fn increase_process_errors() { + EVENT_STATS.lock().unwrap().process_errors += 1; +} + /// Check if event should be filtered based on process name fn should_filter_process_name(comm: &str) -> bool { unsafe { @@ -1801,21 +1854,15 @@ fn should_filter_process_name(comm: &str) -> bool { /// Ring buffer event handler callback fn handle_event(data: &[u8]) -> i32 { - unsafe { - EVENT_STATS.events_received += 1; - } + increase_events_received(); match parse_bpf_event(data) { Ok(event) => { - unsafe { - EVENT_STATS.events_parsed += 1; - } + increase_events_parsed(); // Apply process name filter if specified if should_filter_process_name(&event.comm) { - unsafe { - EVENT_STATS.events_filtered_name += 1; - } + increase_events_filtered_name(); jtrace!( "Filtering out event for process '{}' (doesn't match filter)", event.comm @@ -1828,11 +1875,12 @@ fn handle_event(data: &[u8]) -> i32 { if let Some(ref mut processor) = EVENT_PROCESSOR { match processor.process_event(&event) { Ok(()) => { - EVENT_STATS.events_processed += 1; + increase_events_processed(); 0 // Success } Err(e) => { - EVENT_STATS.process_errors += 1; + increase_process_errors(); + jerror!( "Failed to process segfault event for PID {}: {}", event.pid, @@ -1848,9 +1896,7 @@ fn handle_event(data: &[u8]) -> i32 { } } Err(e) => { - unsafe { - EVENT_STATS.parse_errors += 1; - } + increase_parse_errors(); jerror!( "Failed to parse BPF event (size: {} bytes): {}", data.len(), @@ -1905,26 +1951,19 @@ fn print_statistics(skel: &SegfaultAnalyzerSkel) -> Result<(), JtraceError> { // Print userspace event processing statistics jinfo!("Userspace Processing Statistics:"); - unsafe { - jinfo!(" Events received: {}", EVENT_STATS.events_received); - jinfo!(" Events parsed: {}", EVENT_STATS.events_parsed); - jinfo!(" Events processed: {}", EVENT_STATS.events_processed); - jinfo!( - " Events filtered (name): {}", - EVENT_STATS.events_filtered_name - ); - jinfo!(" Parse errors: {}", EVENT_STATS.parse_errors); - jinfo!(" Process errors: {}", EVENT_STATS.process_errors); + jinfo!(" Events received: {}", events_received()); + jinfo!(" Events parsed: {}", events_parsed()); + jinfo!(" Events processed: {}", events_processed()); + jinfo!(" Events filtered (name): {}", events_filtered_name()); + jinfo!(" Parse errors: {}", events_parse_errors()); + jinfo!(" Process errors: {}", events_process_errors()); - // Calculate success rates - if EVENT_STATS.events_received > 0 { - let parse_rate = - (EVENT_STATS.events_parsed as f64 / EVENT_STATS.events_received as f64) * 100.0; - let process_rate = - (EVENT_STATS.events_processed as f64 / EVENT_STATS.events_received as f64) * 100.0; - jinfo!(" Parse success rate: {:.1}%", parse_rate); - jinfo!(" Process success rate: {:.1}%", process_rate); - } + // Calculate success rates + if events_received() > 0 { + let parse_rate = (events_parsed() as f64 / events_received() as f64) * 100.0; + let process_rate = (events_processed() as f64 / events_received() as f64) * 100.0; + jinfo!(" Parse success rate: {:.1}%", parse_rate); + jinfo!(" Process success rate: {:.1}%", process_rate); } Ok(()) @@ -2127,16 +2166,17 @@ fn main() -> Result<(), JtraceError> { } // Print periodic statistics in verbose mode (legacy) - if cli.verbose && !cli.stats { - unsafe { - if EVENT_STATS.events_received > 0 { - let elapsed_secs = start_time.elapsed().as_secs(); - if elapsed_secs > 0 && elapsed_secs % 30 == 0 { - jinfo!("Periodic stats: {} events received, {} processed, {} filtered (name), {} errors", - EVENT_STATS.events_received, EVENT_STATS.events_processed, - EVENT_STATS.events_filtered_name, EVENT_STATS.parse_errors + EVENT_STATS.process_errors); - } - } + if cli.verbose && !cli.stats && events_received() > 0 { + let elapsed_secs = start_time.elapsed().as_secs(); + if elapsed_secs > 0 && elapsed_secs % 30 == 0 { + jinfo!( + "Periodic stats: {} events received, {} processed, {} filtered (name), {} + errors", + events_received(), + events_processed(), + events_filtered_name(), + events_parse_errors() + events_process_errors() + ); } }