Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ fn main() {
.log_console(false)
.build();

let applications = vec![
let applications = [
"execsnoop_pb",
"execsnoop_rb",
"funccount",
Expand Down
4 changes: 2 additions & 2 deletions eglswapbuffers/eglswapbuffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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));
}
Expand Down
4 changes: 3 additions & 1 deletion execsnoop_pb/execsnoop_pb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion execsnoop_rb/execsnoop_rb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 13 additions & 15 deletions funccount/funccount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))?;
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions lib/symbolanalyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
84 changes: 39 additions & 45 deletions malloc_free/malloc_free.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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)*))
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -584,14 +583,13 @@ fn find_libc_path_from_proc_maps() -> Option<String> {
};

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());
}
}
}
Expand Down Expand Up @@ -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>;
Expand Down Expand Up @@ -843,6 +842,7 @@ impl OutputManager {
})
}

#[allow(dead_code)]
fn write_line(&mut self, line: &str) -> Result<(), JtraceError> {
self.writer.write_line(line)
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -1304,7 +1302,7 @@ fn print_statistics(
cursor.set_position(0);
value = cursor.read_u64::<NativeEndian>().unwrap_or(0);
}
stats_totals[stat_idx] += value;
*v += value;
}
}
}
Expand Down Expand Up @@ -1442,11 +1440,7 @@ fn handle_output_error(error: &Report<JtraceError>, output_file: Option<&std::pa
}

/// Helper function for handling file operations with comprehensive error mapping
fn handle_file_operation<T, F>(
operation: &str,
path: &std::path::PathBuf,
f: F,
) -> Result<T, JtraceError>
fn handle_file_operation<T, F>(operation: &str, path: &Path, f: F) -> Result<T, JtraceError>
where
F: FnOnce() -> std::io::Result<T>,
{
Expand All @@ -1466,7 +1460,7 @@ where
};

Report::new(JtraceError::FileError {
path: path.clone(),
path: path.to_path_buf(),
operation: operation.to_string(),
source: error_msg,
})
Expand Down
1 change: 1 addition & 0 deletions profile/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading