From 67f78d3b4ca883d68241cf704a7dbf738eea3b90 Mon Sep 17 00:00:00 2001 From: Valentin Obst Date: Sun, 5 May 2024 23:20:08 +0200 Subject: [PATCH] WIP: lib/ir/project: add/expose functions for benchmarking On stable Rust, Criterion.rs can only use and benchmark public functions. Thus, expose some functions that will be used in the benchmarks. Signed-off-by: Valentin Obst --- .../intermediate_representation/project.rs | 77 +++++++++++++------ 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/src/cwe_checker_lib/src/intermediate_representation/project.rs b/src/cwe_checker_lib/src/intermediate_representation/project.rs index 31e3694e3..49d7b80be 100644 --- a/src/cwe_checker_lib/src/intermediate_representation/project.rs +++ b/src/cwe_checker_lib/src/intermediate_representation/project.rs @@ -1,4 +1,5 @@ use super::*; +use crate::analysis; use crate::utils::log::LogMessage; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; @@ -6,7 +7,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; mod block_duplication_normalization; use block_duplication_normalization::*; /// Contains implementation of the propagate control flow normalization pass. -mod propagate_control_flow; +pub mod propagate_control_flow; use propagate_control_flow::*; /// The `Project` struct is the main data structure representing a binary. @@ -80,7 +81,7 @@ impl Project { impl Project { /// For all expressions contained in the project, /// replace trivially computable subexpressions like `a XOR a` with their result. - fn substitute_trivial_expressions(&mut self) { + pub fn substitute_trivial_expressions(&mut self) { for sub in self.program.term.subs.values_mut() { for block in sub.term.blocks.iter_mut() { for def in block.term.defs.iter_mut() { @@ -272,14 +273,43 @@ impl Project { errors } - /// Run some normalization passes over the project. + /// Performs only the normalizations necessary to analyze the project. + /// + /// Runs only the normalization passes that bring the project to a form + /// in which it can be consumed by the later analyses. Currently those are: + /// + /// - Removal of duplicate TIDs. (This is a workaround for a bug in the + /// P-Code-Extractor and should be removed once the bug is fixed.) + /// - Replace jumps to nonexisting TIDs with jumps to artificial sink + /// targets in the CFG. Also replace return addresses of non-returning + /// external symbols with artificial sink targets. + /// - Duplicate blocks so that if a block is contained in several functions, + /// each function gets its own unique copy. + /// + /// After those passes all of the later analyses can be computed. However, + /// they are expected to run faster if you also run + /// [`Project::normalize_optimize`] beforehand. + #[must_use] + pub fn normalize_basic(&mut self) -> Vec { + let mut logs = self.remove_duplicate_tids(); + logs.append( + &mut self.remove_references_to_nonexisting_tids_and_retarget_non_returning_calls(), + ); + make_block_to_sub_mapping_unique(self); + + logs + } + + /// Performs only the optimization normalization passes. + /// + /// [`Project::normalize_basic`] **must** be called before this method. + /// + /// Runs only the optimization passes that transform the program to an + /// equivalent, simpler representation. This step is exprected to improve + /// the speed and precision of later analyses. + /// + /// Currently, the following optimizations are performed: /// - /// Passes: - /// - Remove duplicate TIDs. - /// This is a workaround for a bug in the P-Code-Extractor and should be removed once the bug is fixed. - /// - Replace jumps to nonexisting TIDs with jumps to artificial sink targets in the CFG. - /// Also replace return addresses of non-returning external symbols with artificial sink targets. - /// - Duplicate blocks so that if a block is contained in several functions, each function gets its own unique copy. /// - Propagate input expressions along variable assignments. /// - Replace trivial expressions like `a XOR a` with their result. /// - Remove dead register assignments. @@ -287,21 +317,24 @@ impl Project { /// - Substitute bitwise `AND` and `OR` operations with the stack pointer /// in cases where the result is known due to known stack pointer alignment. #[must_use] - pub fn normalize(&mut self) -> Vec { - let mut logs = self.remove_duplicate_tids(); - logs.append( - &mut self.remove_references_to_nonexisting_tids_and_retarget_non_returning_calls(), - ); - make_block_to_sub_mapping_unique(self); - crate::analysis::expression_propagation::propagate_input_expression(self); + pub fn normalize_optimize(&mut self) -> Vec { + analysis::expression_propagation::propagate_input_expression(self); self.substitute_trivial_expressions(); - crate::analysis::dead_variable_elimination::remove_dead_var_assignments(self); + analysis::dead_variable_elimination::remove_dead_var_assignments(self); propagate_control_flow(self); - logs.append( - crate::analysis::stack_alignment_substitution::substitute_and_on_stackpointer(self) - .unwrap_or_default() - .as_mut(), - ); + analysis::stack_alignment_substitution::substitute_and_on_stackpointer(self) + .unwrap_or_default() + } + + /// Run all normalization passes over the project. + /// + /// Convenience wrapper that calls [`Project::normalize_basic`] and + /// [`Project::normalize_optimize`]. + #[must_use] + pub fn normalize(&mut self) -> Vec { + let mut logs = self.normalize_basic(); + logs.append(self.normalize_optimize().as_mut()); + logs } }