From 56e23432b03f07f84e43a3036b5e33b458557bc1 Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Wed, 16 Feb 2022 03:35:05 +0100 Subject: [PATCH] rbpf-cli: only run static analysis when needed (#23110) --- rbpf-cli/src/main.rs | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/rbpf-cli/src/main.rs b/rbpf-cli/src/main.rs index 210bb971e2..adc7e21661 100644 --- a/rbpf-cli/src/main.rs +++ b/rbpf-cli/src/main.rs @@ -273,17 +273,20 @@ native machine code before execting it in the virtual machine.", check(text_bytes, &config).unwrap(); } Executable::::jit_compile(&mut executable).unwrap(); - let analysis = Analysis::from_executable(&executable); + let mut analysis = LazyAnalysis::new(&executable); match matches.value_of("use") { Some("cfg") => { let mut file = File::create("cfg.dot").unwrap(); - analysis.visualize_graphically(&mut file, None).unwrap(); + analysis + .analyze() + .visualize_graphically(&mut file, None) + .unwrap(); return; } Some("disassembler") => { let stdout = std::io::stdout(); - analysis.disassemble(&mut stdout.lock()).unwrap(); + analysis.analyze().disassemble(&mut stdout.lock()).unwrap(); return; } _ => {} @@ -325,13 +328,15 @@ native machine code before execting it in the virtual machine.", if matches.is_present("trace") { eprintln!("Trace is saved in trace.out"); let mut file = File::create("trace.out").unwrap(); - let analysis = Analysis::from_executable(&executable); - vm.get_tracer().write(&mut file, &analysis).unwrap(); + vm.get_tracer() + .write(&mut file, analysis.analyze()) + .unwrap(); } if matches.is_present("profile") { eprintln!("Profile is saved in profile.dot"); let tracer = &vm.get_tracer(); - let dynamic_analysis = DynamicAnalysis::new(tracer, &analysis); + let analysis = analysis.analyze(); + let dynamic_analysis = DynamicAnalysis::new(tracer, analysis); let mut file = File::create("profile.dot").unwrap(); analysis .visualize_graphically(&mut file, Some(&dynamic_analysis)) @@ -354,3 +359,27 @@ impl Debug for Output { Ok(()) } } + +// Replace with std::lazy::Lazy when stabilized. +// https://github.com/rust-lang/rust/issues/74465 +struct LazyAnalysis<'a> { + analysis: Option>, + executable: &'a Executable, +} + +impl<'a> LazyAnalysis<'a> { + fn new(executable: &'a Executable) -> Self { + Self { + analysis: None, + executable, + } + } + + fn analyze(&mut self) -> &Analysis { + if let Some(ref analysis) = self.analysis { + return analysis; + } + self.analysis + .insert(Analysis::from_executable(self.executable)) + } +}